IMMUTABAR variant av unaccent()
För att förtydliga den felaktiga informationen i det för närvarande accepterade, felaktiga svaret
:
Uttrycksindex tillåter endast IMMUTABLE
funktioner (av uppenbara skäl) och unaccent()
är bara STABLE
. lösningen som du föreslog i kommentaren är också problematiskt. Detaljerad förklaring och en rätt lösning för det :
Beroende på innehållet i tags->name
det kan vara användbart att lägga till unaccent()
till uttrycksindexet, men det är ortogonalt till frågan varför indexet inte användes:
Faktiskt problem/lösning
Operatören LIKE
i din fråga är subtilt fel (mest troligt). Det gör du inte Om du vill tolka 'Weststrasse' som sökmönster, vill du matcha den (normaliserade) strängen som den är. Ersätt med =
operatorn, och du kommer att se en (bitmapp) indexskanning med ditt nuvarande index, oavsett av funktionsvolatiliteten för unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Varför?
Den högra operanden av LIKE
är ett mönster . Postgres kan inte använda ett vanligt btree-index för mönstermatchning ( undantag gäller
). En LIKE
med en vanlig sträng som mönster (inga specialtecken) kan optimeras med en likhetskontroll på btree-indexet. Men om det finns specialtecken i strängen, detta index är ute.
Om det finns en IMMUTABLE
funktion till höger om LIKE
, kan den utvärderas omedelbart och nämnda optimering är fortfarande möjlig. Enligt dokumentation om Funktionsvolatilitetskategorier
:
Detsamma är inte möjligt med en mindre funktionsvolatilitet (STABLE
eller VOLATILE
). Det är därför din "lösning" att fejka en IMMUTABLE unaccent()
verkade fungera, men det är verkligen att sätta läppstift på en gris.
För att upprepa:
- Om du vill arbeta med
LIKE
och mönster, använd ett trigramindex . - Om du inte vill arbeta med
LIKE
och mönster, använd likhetsoperatorn=