Variante INMUTABLE de unaccent()
Para aclarar la información errónea en la respuesta incorrecta actualmente aceptada
:
Los índices de expresión solo permiten IMMUTABLE
funciones (por razones obvias) y unaccent()
es solo STABLE
. La solución que sugirió en el comentario también es problemático. Explicación detallada y una solución adecuada por eso :
Dependiendo del contenido de tags->name
puede ser útil agregar unaccent()
al índice de expresión, pero eso es ortogonal a la pregunta de por qué no se usó el índice:
Problema real/solución
El operador LIKE
en su consulta es sutilmente incorrecta (más probable). Tu no desea interpretar 'Weststrasse' como patrón de búsqueda, desea hacer coincidir la cadena (normalizada) tal como está. Reemplazar con =
operador, y verá un escaneo de índice (mapa de bits) con su índice actual, independientemente de la volatilidad de la función de unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
¿Por qué?
El operando derecho de LIKE
es un patrón . Postgres no puede usar un índice btree simple para la coincidencia de patrones ( se aplican excepciones
). UN LIKE
con una cadena simple como patrón (sin caracteres especiales) se puede optimizar con una verificación de igualdad en el índice btree. Pero si hay caracteres especiales en la cadena, this el índice está fuera.
Si hay un IMMUTABLE
función a la derecha de LIKE
, se puede evaluar inmediatamente y dicha optimización sigue siendo posible. Por documentación sobre Categorías de volatilidad de funciones
:
No es posible lo mismo con una función de menor volatilidad (STABLE
o VOLATILE
). Es por eso que su "solución" de fingir un IMMUTABLE unaccent()
parecía funcionar, pero en realidad es poner lápiz labial en un cerdo.
Para reiterar:
- Si quieres trabajar con
LIKE
y patrones, use un trigram index . - Si no desea trabajar con
LIKE
y patrones, use el operador de igualdad=