IMMUTABLE varianta unaccent()
Abychom objasnili dezinformace v aktuálně přijímané nesprávné odpovědi
:
Indexy výrazů umožňují pouze IMMUTABLE
funkcí (ze zřejmých důvodů) a unaccent()
je pouze STABLE
. řešení, které jste navrhli v komentáři je také problematické. Podrobné vysvětlení a správné řešení za to :
V závislosti na obsahu tags->name
může být užitečné přidat unaccent()
k indexu výrazu, ale to je ortogonální k otázce, proč se index nepoužíval:
Skutečný problém / řešení
Operátor LIKE
ve vašem dotazu je jemně chybný (pravděpodobně). Ne chcete interpretovat 'Weststrasse' jako vyhledávací vzor, chcete odpovídat (normalizovanému) řetězci tak, jak je. Nahraďte znakem =
a uvidíte (bitmapový) index skenování s vaším aktuálním indexem, bez ohledu volatility funkce unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Proč?
Pravý operand LIKE
je vzor . Postgres nemůže použít prostý index btree pro porovnávání vzorů ( platí výjimky
). LIKE
s jednoduchým řetězcem jako vzorem (bez speciálních znaků) lze optimalizovat kontrolou rovnosti na indexu btree. Ale pokud jsou v řetězci speciální znaky, toto index je mimo.
Pokud existuje IMMUTABLE
funkce napravo od LIKE
, lze jej ihned vyhodnotit a uvedená optimalizace je stále možná. Podle dokumentace o kategoriích volatility funkcí
:
Totéž není možné s menší volatilitou funkce (STABLE
nebo VOLATILE
). To je důvod, proč vaše "řešení" předstírat IMMUTABLE unaccent()
Zdálo se, že to funguje, ale je to opravdu nanášení rtěnky na prase.
Pro zopakování:
- Pokud chcete pracovat s
LIKE
a vzory, použijte trigram index . - Pokud nechcete pracovat s
LIKE
a vzory, použijte operátor rovnosti=