¿Cómo crear un índice para acelerar una consulta LIKE agregada en una expresión?


20

Puedo estar haciendo una pregunta incorrecta en el título. Aquí están los hechos:

Mi gente de servicio al cliente se ha estado quejando de los tiempos de respuesta lentos al realizar búsquedas de clientes en la interfaz de administración de nuestro sitio basado en Django.

Estamos usando Postgres 8.4.6. Comencé a registrar consultas lentas y descubrí a este culpable:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

Esta consulta tarda más de 32 segundos en ejecutarse. Aquí está el plan de consulta proporcionado por EXPLAIN:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

Debido a que esta es una consulta generada por el Django ORM a partir de un Django QuerySet generado por la aplicación Django Admin, no tengo ningún control sobre la consulta en sí. Un índice parece ser la solución lógica. Intenté crear un índice para acelerar esto, pero no ha hecho una diferencia:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

¿Qué estoy haciendo mal? ¿Cómo puedo acelerar esta consulta?

Respuestas:


21

No hay soporte de índice para LIKE/ ILIKEen PostgreSQL 8.4 , excepto para los términos de búsqueda anclados a la izquierda .

Desde PostgreSQL 9.1, el módulo adicional pg_trgmproporciona clases de operador para los índices de trigrama GIN y GiST que admiten LIKE/ ILIKEo expresiones regulares (operadores ~y amigos). Instalar una vez por base de datos:

CREATE EXTENSION pg_trgm;

Ejemplo de índice GIN:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

Relacionado:


2
Esta es realmente la respuesta correcta.
vonPetrushev

9

Ese índice no va a ayudar debido al '%' al comienzo de su coincidencia: un índice BTREE solo puede coincidir con prefijos y el comodín al comienzo de su consulta significa que no hay un prefijo fijo que buscar.

Es por eso que está haciendo un escaneo de tabla y haciendo coincidir cada registro a su vez con la cadena de consulta.

Probablemente necesite ver el uso de un índice de texto completo y los operadores de coincidencia de texto en lugar de hacer la búsqueda de subcadenas con LIKE que es en este momento. Puede encontrar más información sobre la búsqueda de texto completo en la documentación:

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

De hecho, noto en esa página que LIKE aparentemente nunca usa índices, lo que me parece extraño ya que debería ser capaz de resolver prefijos que no sean comodines usando un índice BTREE. Sin embargo, algunas pruebas rápidas sugieren que la documentación probablemente sea correcta, en cuyo caso ninguna cantidad de indexación ayudará cuando esté usando LIKE para resolver la consulta.


De eso tenía miedo. ¿Hay otro tipo de índice que ayude? Como dije, estoy un poco limitado en mi capacidad de afectar la consulta en sí.
David Eyk

Además, el líder %es una característica necesaria: los representantes de servicio al cliente lo necesitan para encontrar cuentas de clientes, especialmente cuando hay un error tipográfico en la dirección de correo electrónico.
David Eyk

Bueno, después de un poco de investigación sobre LIKE e indexación de texto completo, y estoy empezando a ver su punto.
David Eyk

Por ahora, he encontrado una manera de suprimir el comodín principal. Resulta que puede usar un índice con LIKE, si crea el índice con una clase de operador apropiada . Los documentos están aquí: postgresql.org/docs/8.4/static/indexes-opclass.html
David Eyk

Además, verifique su db para ver si hay hinchazón. Si tienes mucha hinchazón en esa tabla, tomará mucho tiempo seq escanearla. Si tiene algún tiempo de inactividad, simplemente agrúpelo en la clave principal y vea si se vuelve más rápido. Si desea verificar si hay hinchazón, puede ejecutar analizar y luego ejecutar la consulta aquí: wiki.postgresql.org/wiki/Show_database_bloat . Para valores más precisos, vea la parte inferior de esa página.
Scott Marlowe
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.