Je pose peut-être la mauvaise question dans le titre. Voici les faits:
Mes gens du service client se sont plaints de la lenteur des temps de réponse lors de la recherche de clients sur l'interface d'administration de notre site basé à Django.
Nous utilisons Postgres 8.4.6. J'ai commencé à enregistrer des requêtes lentes et j'ai découvert ce coupable:
SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')
Cette requête prend plus de 32 secondes pour s'exécuter. Voici le plan de requête fourni par 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)
Comme il s'agit d'une requête générée par l'ORM Django à partir d'un ensemble de requêtes Django généré par l'application d'administration Django, je n'ai aucun contrôle sur la requête elle-même. Un index semble être la solution logique. J'ai essayé de créer un index pour accélérer cela, mais cela n'a fait aucune différence:
CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))
Qu'est-ce que je fais mal? Comment puis-je accélérer cette requête?
Cet index ne va pas aider à cause du '%' au début de votre correspondance - un index BTREE ne peut correspondre qu'aux préfixes et le caractère générique au début de votre requête signifie qu'il n'y a pas de préfixe fixe à rechercher.
C'est pourquoi il effectue un balayage de table et fait correspondre chaque enregistrement tour à tour avec la chaîne de requête.
Vous devez probablement envisager d'utiliser un index de texte intégral et les opérateurs de correspondance de texte plutôt que de faire la recherche de sous-chaîne avec LIKE que vous êtes en ce moment. Vous pouvez trouver plus d'informations sur la recherche en texte intégral dans la documentation:
http://www.postgresql.org/docs/8.4/static/textsearch-intro.html
En fait, je remarque sur cette page que LIKE n'utilise apparemment jamais d'index, ce qui me semble étrange car il devrait être capable de résoudre les préfixes non génériques à l'aide d'un index BTREE. Quelques tests rapides suggèrent cependant que la documentation est probablement correcte, auquel cas aucune quantité d'indexation ne vous aidera pendant que vous utilisez LIKE pour résoudre la requête.
la source
%
est une fonctionnalité nécessaire: les représentants du service client en ont besoin pour trouver des comptes clients, en particulier lorsqu'il y a une faute de frappe dans l'adresse e-mail.