Tenho uma tabela com registros de contato e os clientes desejam pesquisar nessa tabela para encontrar registros com um endereço de e-mail correspondente (filtrado pelo ID da conta). Os resultados são paginados por uma API RESTful.
Isso resulta em consultas como as abaixo sendo executadas:
SELECT * FROM CONTACT
WHERE deleted is null AND email like '%Matt%' AND accountid=1
ORDER BY lastname LIMIT 0,50;
Nesta tabela, existem índices em email
, accountid
e lastname
. No geral, esta tabela possui 3,6 milhões de linhas e, neste exemplo específico accountid
, possui 170.000 linhas. Esta consulta específica está levando cerca de 2 minutos e 30 segundos para ser concluída.
Se eu alterar a consulta para remover a ORDER BY
cláusula, a consulta terminará em cerca de 0,6 segundos. Se eu alterar a consulta para remover a LIMIT
cláusula, a consulta terminará em cerca de 0,23 segundos.
Eu li este artigo , mas não tenho certeza do que mais posso fazer para melhorar esta consulta. Sei que o email
índice não será usado por causa da pesquisa curinga completa, mas achei que o lastname
índice ajudaria nas coisas de ORDER BY
qualquer maneira.
mysql> explain SELECT * FROM CONTACT WHERE deleted is null AND email like '%Matt%' AND accountid=1 ORDER BY lastname LIMIT 0,50;
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | a | index | accountid | lastname | 53 | NULL | 5804 | Using where |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
1 row in set (0.00 sec)
Como posso melhorar esta consulta para terminar mais rapidamente com as cláusulas ORDER BY
e ?LIMIT 0,50
Este índice composto pode ajudar:
Ao adicioná-lo, você também pode remover
INDEX(account_id)
, pois ele será redundante.Isso pode ser ainda melhor, mas não tenho certeza:
No entanto, não substitui
INDEX(account_id)
.