FTS no admite LIKE
La respuesta previamente aceptada era incorrecta. La búsqueda de texto completo con sus índices de texto completo no es para el LIKE
operador en absoluto, tiene sus propios operadores y no funciona para cadenas arbitrarias. Funciona con palabras basadas en diccionarios y derivaciones. Se hace de soporte emparejamiento de prefijo para las palabras , pero no con el LIKE
operador:
Índices de trigram para LIKE
Instalar el módulo adicional pg_trgm
que proporciona clases de operador de ginebra y de trigramas GiST índices para apoyar todas LIKE
y ILIKE
patrones , no sólo los de la izquierda anclados:
Índice de ejemplo:
CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
O:
CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Consulta de ejemplo:
SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well
Trigramas? ¿Qué pasa con las cuerdas más cortas?
Las palabras con menos de 3 letras en valores indexados aún funcionan. El manual:
Se considera que cada palabra tiene dos espacios como prefijo y un espacio como sufijo al determinar el conjunto de trigramas contenidos en la cadena.
¿Y patrones de búsqueda con menos de 3 letras? El manual:
Tanto LIKE
para búsquedas como para búsquedas de expresiones regulares, tenga en cuenta que un patrón sin trigramas extraíbles degenerará en un escaneo de índice completo.
Es decir, que los escaneos de índice / mapa de bits aún funcionan (los planes de consulta para la declaración preparada no se romperán), simplemente no le dará un mejor rendimiento. Por lo general, no hay una gran pérdida, ya que las cadenas de 1 o 2 letras apenas son selectivas (más de un pequeño porcentaje de las coincidencias de la tabla subyacente) y el soporte de índices no mejoraría el rendimiento para empezar, porque un escaneo completo de la tabla es más rápido.
text_pattern_ops
para la coincidencia de prefijo
Solo para patrones anclados a la izquierda (sin comodines iniciales), obtiene el óptimo con una clase de operador adecuada para un índice btree: text_pattern_ops
ovarchar_pattern_ops
. Ambas características integradas de Postgres estándar, no se necesitan módulos adicionales. Rendimiento similar, pero índice mucho menor.
Índice de ejemplo:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
Consulta de ejemplo:
SELECT * FROM tbl WHERE col LIKE 'foo%'; -- no leading wildcard
O , si debe ejecutar su base de datos con la configuración regional 'C' (de hecho, no configuración regional), entonces todo se ordena según el orden de bytes de todos modos y un índice btree simple con la clase de operador predeterminada hace el trabajo.
Más detalles, explicación, ejemplos y enlaces en estas respuestas relacionadas en dba.SE:
pg_trgm
necesita una cadena de consulta de al menos 3 caracteres de longitud, por ejemplofo%
, no presionaría el índice sino que haría un escaneo. Algo a tener en cuenta.Posiblemente los más rápidos son patrones anclados con mayúsculas y minúsculas como los que pueden usar índices. es decir, no hay comodines al principio de la cadena de coincidencia, por lo que el ejecutor puede usar un escaneo de rango de índice. ( el comentario relevante en los documentos está aquí ) Inferior e ilike también perderán su capacidad para usar el índice a menos que cree específicamente un índice para ese propósito (vea índices funcionales ).
Si desea buscar una cadena en el medio del campo, debe buscar en los índices de texto completo o de trigramas . El primero de ellos está en el núcleo de Postgres, el otro está disponible en los módulos contrib.
fuente
Puede instalar Wildspeed , un tipo diferente de índice en PostgreSQL. Wildspeed funciona con comodines% word%, no hay problema. La desventaja es el tamaño del índice, que puede ser grande, muy grande.
fuente
Ejecute la consulta mencionada a continuación para mejorar el rendimiento de la consulta LIKE en postgresql. crea un índice como este para tablas más grandes:
fuente
por lo que vale, Django ORM tiende a usar
UPPER(text)
para todas lasLIKE
consultas para que no distinga entre mayúsculas y minúsculas,Agregar un índice en
UPPER(column::text)
ha acelerado enormemente mi sistema, a diferencia de cualquier otra cosa.En cuanto al% inicial, sí, eso no usará un índice. Consulte este blog para obtener una gran explicación:
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
fuente
Recientemente tuve un problema similar con una tabla que contiene 200000 registros y necesito hacer consultas LIKE repetidas. En mi caso, se corrigió la cadena que se buscaba. Otros campos variaron. Por eso, pude reescribir:
como
Me encantó cuando las consultas volvieron rápidamente y verifiqué que el índice se estaba utilizando con
EXPLAIN ANALYZE
:fuente
Sus consultas similares probablemente no pueden usar los índices que creó porque:
1) su criterio LIKE comienza con un comodín.
2) ha utilizado una función con sus criterios LIKE.
fuente
Siempre que utilice una cláusula en una columna con funciones, por ejemplo, LIKE, ILIKE, superior, inferior, etc. Entonces, Postgres no tendrá en cuenta su índice normal. Hará un escaneo completo de la tabla pasando por cada fila y por lo tanto será lento.
La forma correcta sería crear un nuevo índice de acuerdo con su consulta. Por ejemplo, si quiero hacer coincidir una columna sin distinción entre mayúsculas y minúsculas y mi columna es un varchar. Entonces puedes hacerlo así.
Del mismo modo, si su columna es un texto, haga algo como esto
Del mismo modo, puede cambiar la función superior a cualquier otra función que desee.
fuente