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   
¿Fue útil?

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';
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top