Eu posso estar fazendo a pergunta errada no título. Aqui estão os fatos:
Meu pessoal de atendimento ao cliente está reclamando de tempos de resposta lentos ao fazer pesquisas de clientes na interface de administração do nosso site baseado em Django.
Estamos usando o Postgres 8.4.6. Comecei a registrar consultas lentas e descobri o culpado:
SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')
Esta consulta está demorando mais de 32 segundos para ser executada. Aqui está o plano de consulta fornecido pelo 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)
Como esta é uma consulta gerada pelo Django ORM a partir de um Django QuerySet gerado pelo aplicativo Admin do Django, não tenho controle sobre a própria consulta. Um índice parece ser a solução lógica. Tentei criar um índice para acelerar isso, mas não fez diferença:
CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))
O que estou fazendo errado? Como posso acelerar esta consulta?
Esse índice não ajudará por causa do '%' no início da sua correspondência - um índice BTREE pode corresponder apenas a prefixos e o curinga no início da sua consulta significa que não há prefixo fixo para procurar.
É por isso que está fazendo uma varredura de tabela e combinando todos os registros, por sua vez, com a string de consulta.
Provavelmente, você precisa usar um índice de texto completo e os operadores de correspondência de texto, em vez de fazer a pesquisa de substring com LIKE que você está no momento. Você pode encontrar mais informações sobre a pesquisa de texto completo na documentação:
http://www.postgresql.org/docs/8.4/static/textsearch-intro.html
Na verdade, percebo nessa página que LIKE aparentemente nunca usa índices, o que me parece estranho, pois deveria ser capaz de resolver prefixos não curinga usando um índice BTREE. No entanto, alguns testes rápidos sugerem que a documentação provavelmente está correta, caso em que nenhuma quantidade de indexação ajudará enquanto você estiver usando o LIKE para resolver a consulta.
fonte
%
é um recurso necessário: os representantes de atendimento ao cliente precisam dele para encontrar contas de clientes, especialmente quando há um erro de digitação no endereço de e-mail.