IMMUTABLE Variante von unaccent()
Um die Fehlinformationen in der derzeit akzeptierten, falschen Antwort
zu klären :
Expression-Indizes erlauben nur IMMUTABLE
Funktionen (aus offensichtlichen Gründen) und unaccent()
ist nur STABLE
. Die Lösung, die Sie im Kommentar vorgeschlagen haben ist auch problematisch. Detaillierte Erklärung und eine richtige Lösung dafür :
Abhängig vom Inhalt von tags->name
es kann nützlich sein, unaccent()
hinzuzufügen zum Ausdrucksindex, aber das ist orthogonal zu der Frage, warum der Index nicht verwendet wurde:
Eigentliches Problem / Lösung
Der Operator LIKE
in Ihrer Abfrage ist subtil falsch (höchstwahrscheinlich). Du nicht Wenn Sie „Weststraße“ als Suchmuster interpretieren möchten, möchten Sie die (normalisierte) Zeichenfolge so abgleichen, wie sie ist. Ersetzen Sie durch =
-Operator, und Sie sehen einen (Bitmap-)Index-Scan mit Ihrem aktuellen Index, ungeachtet der Funktionsvolatilität von unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Warum?
Der rechte Operand von LIKE
ist ein Muster . Postgres kann keinen einfachen btree-Index für den Musterabgleich verwenden ( Ausnahmen gelten
). Ein LIKE
mit einem einfachen String als Muster (keine Sonderzeichen) kann mit einer Gleichheitsprüfung auf dem btree-Index optimiert werden. Aber wenn der String Sonderzeichen enthält, this Index ist aus.
Wenn es einen IMMUTABLE
gibt Funktion rechts von LIKE
, kann es sofort ausgewertet werden und die besagte Optimierung ist noch möglich. Per Dokumentation zu Funktionsvolatilitätskategorien
:
Dasselbe ist mit einer geringeren Volatilität der Funktion nicht möglich (STABLE
oder VOLATILE
). Deshalb Ihre "Lösung", einen IMMUTABLE unaccent()
vorzutäuschen schien zu funktionieren, aber es ist wirklich Lippenstift auf ein Schwein.
Um es noch einmal zu wiederholen:
- Wenn Sie mit
LIKE
arbeiten möchten und Muster verwenden Sie einen Trigrammindex . - Wenn Sie nicht mit
LIKE
arbeiten möchten und Muster verwenden Sie den Gleichheitsoperator=