Оптимизировать очень медленный Mysql Query - PullRequest
1 голос
/ 12 января 2012

Мне нужна помощь в оптимизации этого запроса:

SELECT 
    c.rut, c.nombre, c.apellido, c.estado, c.porcentajeavance,  
    c.porcentajenota, c.nota, c.curso, c.fecha_inicio,   
    c.fecha_termino, c.grupo, c.fecha, c.cargo
FROM tbl_historico c
WHERE fecha = ( 
    SELECT max( t.fecha ) fecha
    FROM tbl_historico t
    WHERE t.rut = c.rut AND c.curso = t.curso 
)

ОБЪЯСНИТЕ вывод:

+----+--------------------+-------+------+-----------------+-------+---------+-----------------------------------------+--------+-------------+
| id | select_type        | table | type | possible_keys   | key   | key_len | ref                                     | rows   | Extra       |
+----+--------------------+-------+------+-----------------+-------+---------+-----------------------------------------+--------+-------------+
|  1 | PRIMARY            | c     | ALL  | NULL            | NULL  | NULL    | NULL                                    | 158008 | Using where |
|  2 | DEPENDENT SUBQUERY | t     | ref  | rut,rut_2,rut_3 | rut_3 | 514     | campus_mdle1.c.rut,campus_mdle1.c.curso |     27 | Using index |
+----+--------------------+-------+------+-----------------+-------+---------+-----------------------------------------+--------+-------------+

Ответы [ 2 ]

2 голосов
/ 12 января 2012

Я думаю, что вы можете переписать его, чтобы избежать коррелированного подзапроса:

SELECT c.rut, c.nombre, c.apellido, c.estado, c.porcentajeavance
     , c.porcentajenota, c.nota, c.curso, c.fecha_inicio
     , c.fecha_termino, c.grupo, c.fecha, c.cargo
FROM 
      tbl_historico AS c
  JOIN
      ( SELECT rut, curso, MAX(fetcha) AS fetcha
        FROM tbl_historico 
        GROUP BY rut, curso 
      ) AS grp
    ON (grp.rut, grp.curso, grp.fetcha)
     = ( c.rut,   c.curso,   c.fetcha)

Индекс на (rut, curso, fetcha) был бы хорош для этого запроса.


Другое решение будет:

SELECT c.rut, c.nombre, c.apellido, c.estado, c.porcentajeavance
     , c.porcentajenota, c.nota, c.curso, c.fecha_inicio
     , c.fecha_termino, c.grupo, c.fecha, c.cargo
FROM 
      ( SELECT rut, curso
        FROM tbl_historico
        GROUP BY rut, curso
        ORDER BY rut, curso                --- custom order and
        LIMIT 30 OFFSET 0                  --- limit here
      ) AS dc
  JOIN
      tbl_historico AS c
    ON c.PK =                              --- the Primary Key of the table here
       ( SELECT h.PK                       --- and here
         FROM tbl_historico AS h
         WHERE (h.rut, h.curso) = (dc.rut, dc.curso)
         ORDER BY h.fetcha DESC
         LIMIT 1  
       ) 

Это покажет другой результат (в случае связей будет показана только одна из связанных строк), но это может быть даже быстрее, если вы хотите ограничить количество строк.

1 голос
/ 12 января 2012
SELECT c.rut, c.nombre, c.apellido,c.estado, c.porcentajeavance,  
       c.porcentajenota, c.nota, c.curso, c.fecha_inicio, c.fecha_termino,c.grupo,c.fecha,c.cargo
FROM tbl_historico c
ORDER BY c.fecha DESC
LIMIT 1
...