sql >> Databáze >  >> RDS >> PostgreSQL

unaccent() bránící použití indexu v Postgresu

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 =



  1. Jak se vyhnete konfliktům názvů sloupců?

  2. PHP Aktualizace MySQL tabulky pomocí HTML formuláře

  3. mysqlworkbench hlásí chybu verze při exportu databáze

  4. Jak nastavit režim spánku pro čtení/zápis do různých zdrojů dat?