Variante IMMUTABLE de unaccent()
Pour clarifier la désinformation dans la actuellement acceptée, réponse incorrecte
:
Les index d'expression n'autorisent que IMMUTABLE
fonctions (pour des raisons évidentes) et unaccent()
est seulement STABLE
. La solution que vous avez suggérée dans le commentaire est également problématique. Explication détaillée et solution appropriée pour ça :
Selon le contenu de tags->name
il peut être utile d'ajouter unaccent()
à l'expression index, mais c'est orthogonal à la question de savoir pourquoi l'index n'était pas utilisé :
Problème réel/solution
L'opérateur LIKE
dans votre requête est subtilement erroné (probablement). Vous ne faites pas voulez interpréter 'Weststrasse' comme modèle de recherche, vous voulez faire correspondre la chaîne (normalisée) telle quelle. Remplacez par le =
opérateur, et vous verrez un balayage d'index (bitmap) avec votre index actuel, indépendamment de la volatilité de la fonction de unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Pourquoi ?
L'opérande droit de LIKE
est un motif . Postgres ne peut pas utiliser un index btree simple pour la correspondance de modèle ( des exceptions s'appliquent
). Un LIKE
avec une chaîne simple comme modèle (pas de caractères spéciaux) peut être optimisé avec un contrôle d'égalité sur l'index btree. Mais s'il y a des caractères spéciaux dans la chaîne, ceci l'index est sorti.
S'il y a un IMMUTABLE
fonction à droite de LIKE
, elle peut être évaluée immédiatement et ladite optimisation est encore possible. Par documentation sur les catégories de volatilité des fonctions
:
La même chose n'est pas possible avec une moindre volatilité de la fonction (STABLE
ou VOLATILE
). C'est pourquoi votre "solution" de simuler un IMMUTABLE unaccent()
semblait fonctionner, mais c'est vraiment mettre du rouge à lèvres sur un cochon.
Pour réitérer :
- Si vous souhaitez travailler avec
LIKE
et modèles, utilisez un index trigramme . - Si vous ne voulez pas travailler avec
LIKE
et les motifs, utilisez l'opérateur d'égalité=