I have this query that I've optimized to be run in half the time it was in the beginning.
Now I want to improve it's execution creating some indexes, but haven't found the way to do it.
The query is:
SELECT straight_join CONCAT(IFNULL(u.nombre,''), ' ', IFNULL(u.apellidos,''), ' ', IFNULL(u.apellido2,''), ' ; ', IFNULL(u.correo,''), ' ; ', IFNULL(u.telefono,''), ' ',
IFNULL(u.horario,''), ' ; ', IFNULL(u.telefono2,''), ' ', IFNULL(u.horario2,''), ' ; ', IFNULL(u.fecha_prox_llamada,'')) AS datos,
usuariohist1.web, usuariohist1.comentario, u.usuario_id, estad.estad_id,
estad.fecha, estad.tipoinf, estad.web_id, estad.procede, estad.convocatoria_id, eventos.evento as curso,
centros.centro, centros.centro_id
FROM centros
INNER JOIN convocatorias ON centros.centro_id = convocatorias.centro_id
INNER JOIN eventos ON eventos.evento_id = convocatorias.evento_id
INNER JOIN estad ON estad.convocatoria_id = convocatorias.convocatoria_id
INNER JOIN usuarios AS u ON estad.usuario_id = u.usuario_id
LEFT JOIN (select web, comentario, usuario_id FROM usuariohist order by fecha desc, id desc ) as usuariohist1
ON u.usuario_id = usuariohist1.usuario_id OR u.n_usuario = usuariohist1.usuario_id
WHERE centros.segcupones = 1 and u.fecha_prox_llamada = '2013-02-13'
group by u.usuario_id, estad.web_id, estad.convocatoria_id
order by estad.fecha desc \G
The execution plan is:
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: centros
type: ALL
possible_keys: PRIMARY,centro_id,centro_id_2
key: NULL
key_len: NULL
ref: NULL
rows: 2622
Extra: Using where; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: convocatorias
type: ref
possible_keys: PRIMARY,FK_convocatorias_evento_id,FK_convocatorias_centro_id
key: FK_convocatorias_centro_id
key_len: 3
ref: formaweb_op.centros.centro_id
rows: 66
Extra: Using where
*************************** 3. row ***************************
id: 1
select_type: PRIMARY
table: eventos
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: formaweb_op.convocatorias.evento_id
rows: 1
Extra:
*************************** 4. row ***************************
id: 1
select_type: PRIMARY
table: estad
type: ref
possible_keys: FK_Estad_Convocatorias,FK_Estad_Usuarios
key: FK_Estad_Convocatorias
key_len: 4
ref: formaweb_op.convocatorias.convocatoria_id
rows: 4
Extra:
*************************** 5. row ***************************
id: 1
select_type: PRIMARY
table: u
type: eq_ref
possible_keys: PRIMARY,usuario_id
key: PRIMARY
key_len: 4
ref: formaweb_op.estad.usuario_id
rows: 1
Extra: Using where
*************************** 6. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 23971
Extra:
*************************** 7. row ***************************
id: 2
select_type: DERIVED
table: usuariohist
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 28594
Extra: Using filesort
7 rows in set (0.48 sec)
I've created a covering index on centros table (centro_id, centro, segcupones), but performance has not improved (or very little). Now execution plan shows using index but also using temporary and filesort.
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: centros
type: index
possible_keys: PRIMARY,centro_id,centro_id_2,centro_id_3
key: centro_id_3
key_len: 307
ref: NULL
rows: 2873
Extra: Using where; Using index; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: convocatorias
type: ref
possible_keys: PRIMARY,FK_convocatorias_evento_id,FK_convocatorias_centro_id
key: FK_convocatorias_centro_id
key_len: 3
ref: formaweb_op.centros.centro_id
rows: 66
Extra: Using where
*************************** 3. row ***************************
id: 1
select_type: PRIMARY
table: eventos
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: formaweb_op.convocatorias.evento_id
rows: 1
Extra:
*************************** 4. row ***************************
id: 1
select_type: PRIMARY
table: estad
type: ref
possible_keys: FK_Estad_Convocatorias,FK_Estad_Usuarios
key: FK_Estad_Convocatorias
key_len: 4
ref: formaweb_op.convocatorias.convocatoria_id
rows: 4
Extra:
*************************** 5. row ***************************
id: 1
select_type: PRIMARY
table: u
type: eq_ref
possible_keys: PRIMARY,usuario_id
key: PRIMARY
key_len: 4
ref: formaweb_op.estad.usuario_id
rows: 1
Extra: Using where
*************************** 6. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 23971
Extra:
*************************** 7. row ***************************
id: 2
select_type: DERIVED
table: usuariohist
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 28594
Extra: Using filesort
7 rows in set (0.54 sec)
I've also created index for table usuariohist (DERIVED) but no success, the query plan still the same. I've tried these indexes: (fecha, id), (usuario_id, fecha, id) and a covering index (usuario_id, fecha, id, web, comentario).
Index from tables involved:
CREATE TABLE `centros` (
...FIELDS...
PRIMARY KEY (`centro_id`),
KEY `FK_Centros_Aux_Paises` (`pais_id`),
KEY `FK_Centros_Aux_Provincias` (`provincia_id`),
KEY `FK_Centros_Centros_Grupo` (`grupo_id`),
KEY `centro_id_2` (`centro_id`,`tipouniversidad`),
KEY `centro_id` (`centro_id`,`padre_id`,`provincia_id`),
KEY `centro_id_3` (`centro_id`,`centro`,`segcupones`),
CONSTRAINT `FK_Centros_Aux_Paises` FOREIGN KEY (`pais_id`) REFERENCES `aux_paises` (`pais_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Centros_Aux_Provincias` FOREIGN KEY (`provincia_id`) REFERENCES `aux_provincias` (`provincia_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Centros_Centros_Grupo` FOREIGN KEY (`grupo_id`) REFERENCES `centros_grupo` (`grupo_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3373 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `convocatorias` (
...FIELDS...
PRIMARY KEY (`convocatoria_id`),
KEY `FK_Convocatorias_Centros` (`centro_id`),
KEY `FK_Convocatorias_Eventos` (`evento_id`),
CONSTRAINT `FK_Convocatorias_Centros` FOREIGN KEY (`centro_id`) REFERENCES `centros` (`centro_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Convocatorias_Eventos` FOREIGN KEY (`evento_id`) REFERENCES `eventos` (`evento_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `eventos` (
...FIELDS...
PRIMARY KEY (`evento_id`),
KEY `evento` (`evento`,`temario`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `estad` (
...FIELDS...
CONSTRAINT `FK_Estad_Convocatorias` FOREIGN KEY (`convocatoria_id`) REFERENCES `convocatorias` (`convocatoria_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Estad_Usuarios` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`usuario_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=360851 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `usuarios` (
...FIELDS...
PRIMARY KEY (`usuario_id`),
KEY `FK_Usuarios_WEBS` (`web_id`),
KEY `usuario` (`usuario`,`clave`),
KEY `usuario_id` (`usuario_id`,`web_id`),
CONSTRAINT `FK_usuarios_web_id` FOREIGN KEY (`web_id`) REFERENCES `webs` (`web_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=256323 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `usuariohist` (
...FIELDS...
PRIMARY KEY (`id`),
KEY `usuario_id` (`usuario_id`,`fecha`,`id`),
KEY `usuario_id_2` (`usuario_id`,`fecha`,`id`,`web`,`comentario`(255))
) ENGINE=InnoDB AUTO_INCREMENT=28153 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Anyone knows how I can optimize this query creating indexes, please explain the solution.
Thanks in advance!
Just a couple of pointers - I don't have time right now for a full analysis:
For any query to reach it's maximum potential, if there are explicit values provided, it helps enormously if they drive the query.
Your query has specific values for centros.segcupones and u.fecha_prox_llamada but there is no index on the last one, and a only joint index on the first one, so your first port of call is to create an index for u.fecha_prox_llamada, then maybe see how an single index on centros.segcupones goes.