IMMUTABEL variant af unaccent()
For at afklare misinformationen i det aktuelt accepterede, forkerte svar
:
Udtryksindekser tillader kun IMMUTABLE
funktioner (af indlysende årsager) og unaccent()
er kun STABLE
. løsningen, du foreslog i kommentaren er også problematisk. Detaljeret forklaring og en rigtig løsning for det :
Afhængigt af indholdet af tags->name
det kan være nyttigt at tilføje unaccent()
til udtryksindekset, men det er ortogonalt i forhold til spørgsmålet, hvorfor indekset ikke blev brugt:
Faktisk problem/løsning
Operatøren LIKE
i din forespørgsel er subtilt forkert (højst sandsynlig). Det gør du ikke ønsker at fortolke 'Weststrasse' som søgemønster, vil du matche den (normaliserede) streng, som den er. Erstat med =
operator, og du vil se en (bitmap) indeksscanning med dit nuværende indeks, uanset af funktionen volatilitet af unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Hvorfor?
Den højre operand af LIKE
er et mønster . Postgres kan ikke bruge et almindeligt btree-indeks til mønstermatchning ( undtagelser gælder
). En LIKE
med en almindelig streng som mønster (ingen specialtegn) kan optimeres med et lighedstjek på btree-indekset. Men hvis der er specialtegn i strengen, dette indekset er ude.
Hvis der er en IMMUTABLE
funktion til højre for LIKE
, kan den evalueres med det samme, og den nævnte optimering er stadig mulig. I henhold til dokumentation om Funktionsvolatilitetskategorier
:
Det samme er ikke muligt med en mindre funktionsvolatilitet (STABLE
eller VOLATILE
). Det er derfor din "løsning" med at forfalske en IMMUTABLE unaccent()
så ud til at virke, men det er virkelig at sætte læbestift på en gris.
For at gentage:
- Hvis du vil arbejde med
LIKE
og mønstre, brug et trigramindeks . - Hvis du ikke vil arbejde med
LIKE
og mønstre, brug lighedsoperatoren=