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.