sql >> Base de Datos >  >> RDS >> PostgreSQL

Variaciones de rendimiento de consultas LIKE de PostgreSQL

FTS no es compatible con LIKE

La respuesta previamente aceptada era incorrecta. La búsqueda de texto completo con sus índices de texto completo no para el LIKE operador en absoluto, tiene sus propios operadores y no funciona para cadenas arbitrarias. Opera con palabras basado en diccionarios y derivación. lo hace Admite coincidencia de prefijos para palabras , pero no con el LIKE operador:

  • Obtener una coincidencia parcial de la columna TSVECTOR indexada por GIN

Índices de trigramas para LIKE

Instale el módulo adicional pg_trgm que proporciona clases de operadores para índices de trigramas GIN y GiST para admitir todos los LIKE y LIKE patrones , no solo los anclados a la izquierda:

Í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);
  • Diferencia entre el índice GiST y GIN

Ejemplo de consulta:

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?

Palabras con menos de 3 letras en valores indexados todavía 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 buscar patrones con menos de 3 letras? El manual:

Para ambos LIKE y búsquedas de expresiones regulares, tenga en cuenta que un patrón sin trigramas extraíbles degenerará en un escaneo de índice completo.

Lo que significa que los escaneos de índice / índice de mapa de bits aún funcionan (los planes de consulta para la declaración preparada no se romperán), simplemente no le darán un mejor rendimiento. Por lo general, no hay grandes pérdidas, ya que las cadenas de 1 o 2 letras son poco selectivas (más que un pequeño porcentaje de las coincidencias de la tabla subyacente) y, para empezar, la compatibilidad con índices no mejoraría el rendimiento, porque una exploración completa de la tabla es más rápida.


text_pattern_ops para la coincidencia de prefijos

Solo para anclado a la izquierda patrones (sin comodín inicial) obtiene el óptimo con una clase de operador adecuada para un índice btree:text_pattern_ops o varchar_pattern_ops . Ambas características integradas de Postgres estándar, no se necesita ningún módulo adicional. Rendimiento similar, pero índice mucho más pequeño.

Índice de ejemplo:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Ejemplo de consulta:

SELECT * FROM tbl WHERE col LIKE 'foo%';  -- no leading wildcard

O , si debe ejecutar su base de datos con la 'C' configuración regional (efectivamente no locale), entonces todo se ordena de acuerdo con el orden de bytes de todos modos y un índice btree simple con clase de operador predeterminada hace el trabajo.

Más detalles, explicaciones, ejemplos y enlaces en estas respuestas relacionadas en dba.SE:

  • Coincidencia de patrones con LIKE, SIMILAR TO o expresiones regulares en PostgreSQL
  • ¿Cómo se implementa LIKE?
  • Encontrar cadenas similares con PostgreSQL rápidamente