简体   繁体   中英

Optimize very slow Mysql Query

I need help optimizing this query:

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 
)

EXPLAIN output:

+----+--------------------+-------+------+-----------------+-------+---------+-----------------------------------------+--------+-------------+
| 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 |
+----+--------------------+-------+------+-----------------+-------+---------+-----------------------------------------+--------+-------------+

I think you can rewrite it to avoid the correlated subquery:

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)

An index on (rut, curso, fetcha) would be good for this query.


Another solution would be:

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  
       ) 

This will show different result (in case of ties, only one of the tied rows will be shown) but it could be even faster if you want to limit the number of rows.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM