Tengo problemas de rendimiento en ciertas consultas de bases de datos que tienen grandes conjuntos de resultados posibles.
La consulta en cuestión, tengo tres AND
s en la cláusula WHERE
¿Importa el orden de las cláusulas?
Como en, si pongo la cláusula ASI_EVENT_TIME primero (ya que eso eliminaría la mayoría de los resultados de cualquiera de las cláusulas.
¿Mejorará eso el tiempo de ejecución de la consulta?
CONSULTA:
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
EXPLICAR la 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 |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
Utilizando:
PHP 5.2
MySQL 5.0.51a-3ubuntu5.4
Propel 1.3
Symfony 1.2.5
mysql
performance
mysql-5
Patricio
fuente
fuente
order by
pertenece a la base de datos.Respuestas:
No lo creo. El optimizador de consultas debe ser lo suficientemente inteligente.
Puede intentar reorganizar las cláusulas WHERE y ver que EXPLAINS le dice lo mismo en cada caso.
Acerca de lo que se puede hacer para optimizar esta consulta: ¿Hay un índice en ASI_EVENT_TIME? (Esto es lo más importante que creo para esta consulta, ya que también clasifica los resultados al usarlo).
¿Hay índices en los otros dos campos (ASI_SEISMO_ID y ASI_ACTIVITY_ID)?
Sería útil si publicara la estructura de la tabla.
fuente
De la documentación :
Entonces sí, debería ser el mismo que el orden de las columnas en un índice compuesto .
fuente
WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'
y el índice aún es elegible para su uso.No, no importa
El optimizador realiza un montón de transformaciones simples justo después de analizar el SQL; esta es una de ellas.
fuente
optimiza lo mismo que
Sin embargo,
No se pueden optimizar ambas partes. Por ejemplo,
no puede hacer un buen uso de INDEX (a, b) o INDEX (b, a)
Para expresarlo de manera diferente, cualquier prueba '=' Y juntas en la cláusula WHERE se usa primero, luego se puede manejar una no '=' (IN, BETWEEN,>, etc.). No más de uno puede ser optimizado efectivamente.
Su consulta tiene 3 de estas cláusulas.
Como resultado, el ÍNDICE (EVENT_TIME) es probablemente el más útil: ayudará con uno de los AND, y podría usarse para evitar "ordenar archivos" para ORDER BY.
Si no hay filas duplicadas (¿por qué habría de haberlas?), Elimine DISTINCT. Eso causa aún más esfuerzo.
Proporcione SHOW CREATE TABLE y SHOW TABLE STATUS cuando haga preguntas de rendimiento.
Actualización ... Las versiones más recientes (por ejemplo, MySQL 5.7) pueden, en algunas situaciones, tratarse
IN( list of constants )
casi como=
. Para ir a lo seguro, siga este orden (cada parte es opcional):=
.INs
.fuente
MySQL donde el documento de optimización dice:
De esta manera, es racional que el optimizador de consultas omita el orden CÓMO utilizamos las columnas en la consulta (No solo MySQL sino SQL es un lenguaje declarativo y debe hacer lo que queremos, no cómo queremos).
Sin embargo, todavía me encanta tener el mismo tipo para las columnas de una clave compuesta en la consulta, pero a veces es inevitable, por ejemplo, cuando usamos ORM o ActiveRecord, en algunos marcos como yii2, la personalización de los criterios de relación se agregará al final de una condición "activada" pero aún necesitamos las capacidades de QueryBuilders en diferentes partes de una aplicación.
fuente
CUALQUIER campo que se use en sus cláusulas WHERE / HAVING y tenga una alta selectividad (el número de valores únicos / el número total de registros> 10% ~ 20%) DEBE indexarse.
Entonces, si su
ASI_EVENT_TIME
columna tiene muchos valores posibles, primero indexe todos. Luego, como le dijo @ypercube, intente reorganizarlos y vea lo que EXPLAIN le dice. Debería ser todo lo mismo.Además, desea que eche un vistazo a la indexación de filtros SQL LIKE . Aunque no es para lo que necesita una respuesta, aún así aprenderá cómo funciona la indexación bajo el capó.
* Editar: consulte los enlaces que se proporcionan a continuación en los comentarios para obtener más información sobre la indexación.
fuente