Optimización de consultas utilizando dónde está en
-
24-10-2019 - |
Pregunta
Me pregunto si alguien puede explicar cómo se calcula el en. Bueno, en última instancia, estoy tratando de averiguar por qué esta consulta es lenta y cómo optimizarla. Esperé más de 3 minutos y cuando cancelé la consulta, solo había devuelto 1000 líneas, lo que no parece que deba llevar tanto tiempo.
SELECT t2.*
FROM report_tables.roc_test_results as t2
WHERE t2.job IN (SELECT DISTINCT(t1.job)
FROM report_tables.roc_test_results as t1
WHERE t1.operation = 'TEST'
AND result = 'Passed'
AND STR_TO_DATE(t1.date_created,'%d-%M-%Y') BETWEEN '2009-10-01'
AND '2009-10-31')
No estoy seguro de qué debe devolver la consulta total, si tuviera que adivinar que diría alrededor de 2000 registros, el subconsulto devuelve 332 (336 cuando no es distinto).
¿Alguien puede darme algunos consejos sobre cómo optimizar esta consulta? Además, me pregunto, ¿calcula la subconsulta cada vez o simplemente una vez y la almacena?
Según lo solicitado, los resultados para Desc ... (por cierto, por favor no se ríen, soy autodidacta, así que estoy seguro de que esta mesa está diseñada horriblemente).
Field Type Null Key Default Extra
------ ----- ----- --- ------- -----
operation varchar(10) NO
tester varchar(25) NO
result varchar(45) NO
fail_mode varchar(45) NO
primary_failure varchar(25) NO
ref_des varchar(45) NO
rf_hours varchar(15) NO
ac_hours varchar(15) NO
comments text NO
job varchar(15) NO
rma bigint(20) unsigned NO
item varchar(45) NO
item_description text NO
serial varchar(25) NO
created_by varchar(25) NO
collection bigint(20) unsigned NO PRI
date_created varchar(15) NO
Solución
los date_created
El tipo de datos debe cambiar para ser una fecha y hora antes de que valga la pena definir un índice en la columna. La razón es que el índice no valdrá nada si está cambiando el tipo de datos de String a DateTime como lo es actualmente.
Has mencionado que estás usando LOAD DATA INFILE
, y que el archivo de origen contiene fechas en formato DD-Mon-Yy. MySQL convertirá implícitamente las cadenas en DateTime si se usa el formato YY-MM-DD, entonces, si puede corregir esto en su archivo fuente antes de usar LOAD DATA INFILE
El resto debe caer al lugar.
Después de eso, un índice de cobertura usando:
- trabajo
- operación
- resultado
- fecha de creacion
... sería una buena idea.
Otros consejos
En primer lugar, no necesita lo distinto en la subconsulta, ya que en Eliminados duplicados de todos modos, ¿necesita la llamada de función en la cláusula WHERE y tiene e indexan en la columna date_created?
Que pasa cuando cambias
WHERE STR_TO_DATE(t1.date_created,'%d-%M-%Y')
BETWEEN '2009-10-01' AND '2009-10-31')
a
WHERE 1.date_created >= '2009-10-01'
AND 1.date_created < '2010-01-01'
A veces no se utilizarán los índices si usa funciones en la columna
Mi consejo es reemplazar el IN con una unión, y luego considerar agregar índices en algunas de sus columnas, como el trabajo, y tal vez la operación y/o el resultado. Debe leer en los índices en el manual de MySQL, y también en usar Explicar para optimizar sus consultas:
http://dev.mysql.com/doc/refman/5.1/en/indexes.html
http://dev.mysql.com/doc/refman/5.1/en/using-explain.html
Aquí hay un ejemplo de convertir el IN a A Join:
SELECT distinct t2.*
FROM roc_test_results as t2
inner join roc_test_results as t1 on t1.job = t2.job
WHERE t1.operation = 'TEST'
AND t1.result = 'Passed'
AND STR_TO_DATE(t1.date_created,'%d-%M-%Y') BETWEEN '2009-10-01' AND '2009-10-31';