Vamos caminando
No he podido recrear completamente todas tus tablas (me falta info
) pero... recree 4 las primeras 4 que vi en tu mega consulta
(constate que me estoy basando en registros imaginarios). Estas son las 4 tablas basadas en la tuya:
mysql> DESCRIBE Agenda;
+-------------+---------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | Extra |
+-------------+---------+------+-----+---------+-------+
| hora | TIME | YES | MUL | NULL | |
| agenda | INT(11) | YES | | NULL | |
+-------------+---------+------+-----+---------+-------+
2 ROWS IN SET (0.04 sec)
mysql> DESCRIBE Postoper
+-----------------+---------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | Extra |
+-----------------+---------+------+-----+---------+-------+
| postop | INT(11) | YES | UNI | NULL | |
| preop | INT(11) | YES | MUL | NULL | |
+-----------------+---------+------+-----+---------+-------+
2 ROWS IN SET (0.02 sec)
mysql> DESCRIBE Preoper;
+----------------+---------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | Extra |
+----------------+---------+------+-----+---------+-------+
| nota_preop | INT(11) | YES | UNI | NULL | |
| hora | TIME | YES | | NULL | |
+----------------+---------+------+-----+---------+-------+
2 ROWS IN SET (0.00 sec)
mysql> DESCRIBE Quirofano;
+-------------+------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | Extra |
+-------------+------+------+-----+---------+-------+
| hora | TIME | YES | MUL | NULL | |
| fecha | DATE | YES | | NULL | |
+-------------+------+------+-----+---------+-------+
2 ROWS IN SET (0.00 sec)
Y llene cada una con miles de registros:
mysql> SELECT COUNT(*) FROM Agenda;
+----------+
| COUNT(*) |
+----------+
| 22998 |
+----------+
1 ROW IN SET (0.00 sec)
mysql> SELECT COUNT(*) FROM Postoper;
+----------+
| COUNT(*) |
+----------+
| 56000 |
+----------+
1 ROW IN SET (0.00 sec)
mysql> SELECT COUNT(*) FROM Quirofanos;
+----------+
| COUNT(*) |
+----------+
| 35000 |
+----------+
1 ROW IN SET (0.00 sec)
mysql> SELECT COUNT(*) FROM Preoper;
+----------+
| COUNT(*) |
+----------+
| 35800 |
+----------+
1 ROW IN SET (0.00 sec)
Bien basandome un poco en el ejemplo que hablamos de tu consulta actual SQL tendria algo como esto:
SELECT COUNT(a.postop) FROM Postoper a INNER JOIN Preoper b ON a.preop = b.preop INNER JOIN agenda c ON c.hora = b.hora INNER JOIN quirofano f ON f.hora = b.hora;
+--------------------------+
| COUNT(a.cve_nota_postop) |
+--------------------------+
| 12000 |
+--------------------------+
1 ROW IN SET (45 MIN 52 sec)
Si tuve que esperarme todo eso (42 minutos casi 1 hora) para obtener 12 mil registros que concordaban... sin embargo ejecute el fabuloso EXPLAIN y que vi
+----+-------------+-------+------+----------------+-------------+---------+---------------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+----------------+-------------+---------+---------------------------+-------+--------------------------+
| 1 | SIMPLE | b | ALL | preop | NULL | NULL | NULL | 35800 | |
| 1 | SIMPLE | a | ref | indice | indice | 5 | primaria.b.preop | 1 | Using where |
| 1 | SIMPLE | f | ref | hora | hora | 4 | primaria.b.hora | 12 | Using where; Using index |
| 1 | SIMPLE | c | ref | hora | hora | 4 | primaria.f.hora | 12 | Using where; Using index |
+----+-------------+-------+------+----------------+-------------+---------+---------------------------+-------+--------------------------+
4 rows in set (0.00 sec)
La tabla Preoper.... se le escapa filtrar un indice
y analiza todos los registros... Asi que altere dicha tabla y le agregue una clave candidata :
mysql> DESCRIBE preoper;
+----------------+---------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | Extra |
+----------------+---------+------+-----+---------+-------+
| preop | INT(11) | YES | UNI | NULL | |
| hora | TIME | YES | | NULL | |
| id | INT(11) | YES | MUL | NULL | |
+----------------+---------+------+-----+---------+-------+
3 ROWS IN SET (0.00 sec)
el nuevo campo ID es un indice y tiene un dato fijo = 1 Ahora reconstruyo la consulta:
mysql> SELECT COUNT(a.postop) FROM postoper a INNER JOIN preoper b ON a.preop = b.preop INNER JOIN agenda c ON c.hora = b.hora INNER JOIN quirofano f ON f.hora = b.hora AND b.preop = (SELECT COUNT(*) FROM preoper WHERE id = 1);
+--------------------------+
| COUNT(a.cve_nota_postop) |
+--------------------------+
| 12000 |
+--------------------------+
1 ROW IN SET (0.12 sec)
De 45 minutos a 12 segundos...
vaya lo que hace una clave candidata en estas cosas es increible
si activo el buffer cache la segunda vez en vez de 12 segundos deberian ser 0.01 segundos al menos .....
Modifique los nombres de los campos para proteger tu informacion como querias
detallame mas por msn, y seguro que podremos dar con cuales tablas se cuelan los indices para agregar mas claves candidatas.