Estou tendo problemas de desempenho em determinadas consultas ao banco de dados que possuem grandes conjuntos de resultados possíveis.
A consulta em questão, eu tenho três AND
s na cláusula WHERE
A ordem das cláusulas é importante?
Por exemplo, se eu colocar a cláusula ASI_EVENT_TIME em primeiro lugar (pois isso removeria a maioria dos resultados de qualquer uma das cláusulas.
Isso melhorará o tempo de execução na consulta?
INQUERIR:
SELECT DISTINCT activity_seismo_info.*
FROM `activity_seismo_info`
WHERE
activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL AND
activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND
(
activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND
activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
)
ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC
EXPLAIN da consulta:
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
| 1 | SIMPLE | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5 | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
Usando:
PHP 5.2
MySQL 5.0.51a-3ubuntu5.4
Propel 1.3
Symfony 1.2.5
mysql
performance
mysql-5
Patrick
fonte
fonte
order by
pertence ao banco de dados.Respostas:
Eu penso que não. O otimizador de consulta deve ser inteligente o suficiente.
Você pode tentar reorganizar as cláusulas WHERE e ver que EXPLAINS diz o mesmo em cada caso.
Sobre o que pode ser feito para otimizar esta consulta: Existe um índice em ASI_EVENT_TIME? (acho que é o mais crucial para esta consulta, pois você também classifica os resultados usando-a).
Existem índices nos outros dois campos (ASI_SEISMO_ID e ASI_ACTIVITY_ID)?
Seria útil se você publicasse a estrutura da tabela.
fonte
A partir da documentação :
Então, sim, deve ser igual à ordem das colunas em um índice composto .
fonte
WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'
e o índice ainda estiver qualificado para uso.Não, isso não importa.
O otimizador faz várias transformações simples logo após analisar o SQL - este é um deles.
fonte
otimiza o mesmo que
Contudo,
Não é possível otimizar ambas as partes. Por exemplo,
não pode fazer bom uso de INDEX (a, b) ou INDEX (b, a)
Para expressá-lo de maneira diferente, todos os testes '=' AND 'juntos na cláusula WHERE são usados primeiro, então um não -' = '(IN, BETWEEN,>, etc) pode ser tratado. Não mais que um pode ser efetivamente otimizado.
Sua consulta possui 3 cláusulas.
Como se vê, INDEX (EVENT_TIME) é provavelmente o mais útil - ele ajudará em um dos ANDs e pode ser usado para evitar "sortimento de arquivos" para o ORDER BY.
Se não houver linhas duplicadas (por que diabos haveria?), Livre-se do DISTINCT. Isso causa ainda mais esforço.
Forneça SHOW CREATE TABLE e SHOW TABLE STATUS ao fazer perguntas sobre desempenho.
Atualizar ... Versões mais recentes (por exemplo, MySQL 5.7) podem, em algumas situações, tratar
IN( list of constants )
quase como=
. Para garantir a segurança, siga esta ordem (cada parte é opcional):=
.INs
.fonte
MySQL, onde o documento de otimização diz:
Dessa forma, é racional que o otimizador de consulta omita a ordem HOW, que usamos as colunas na consulta (não apenas o MySQL, mas o SQL é uma linguagem declarativa e deve fazer o que queremos, e não o que queremos).
No entanto, ainda gosto de ter a mesma classificação para as colunas de uma chave composta na consulta, mas às vezes é inevitável, por exemplo, quando usamos ORM ou ActiveRecord, em algumas estruturas como yii2, a personalização dos critérios de relação será anexada ao final de uma condição "on", mas ainda precisamos dos recursos do QueryBuilders em diferentes partes de um aplicativo.
fonte
QUALQUER campo usado nas cláusulas WHERE / HAVING e com alta seletividade (o número de valores únicos / o número total de registros> 10% ~ 20%) DEVE ser indexado.
Portanto, se sua
ASI_EVENT_TIME
coluna tiver muitos valores possíveis, primeiro indexe todos eles. Então, como o @ypercube disse, tente reorganizá-los e veja o que EXPLAIN lhe diz. Deve ser o mesmo.Além disso, você deve dar uma olhada em Indexar SQL LIKE Filters . Embora não seja para isso que você precisa de uma resposta, você ainda aprenderá como a indexação funciona sob o capô.
* Editar: consulte os links fornecidos abaixo nos comentários para saber mais sobre a indexação.
fonte