La consulta MySQL con JOIN no usa INDEX
Tengo las siguientes dos tablas en MySQL (simplificado).
clicks
(InnoDB)Contiene alrededor de 70,000,000 de registrosTiene un índice en eldate_added
columnaTiene una columnalink_id
que se refiere a un registro en ellinks
mesalinks
(MyISAM)Contiene muchos menos registros, alrededor de 65,000Estoy tratando de ejecutar algunas consultas analíticas utilizando estas tablas. Necesito extraer algunos datos, sobre clics que ocurrieron dentro de dos fechas especificadas mientras aplicaba otros filtros seleccionados por el usuario usando otras tablas y uniéndolos a la tabla de enlaces.
Sin embargo, mi pregunta gira en torno al uso de índices. Cuando ejecuto la siguiente consulta:
SELECT
COUNT(1)
FROM
clicks
WHERE
date_added >= '2016-11-01 00:00:00'
AND date_added <= '2016-11-03 23:59:59';
Recibo una respuesta en 1.40 segundos. UtilizandoEXPLAIN
Encuentro que MySQL usa el índice en eldate_added
columna como se esperaba.
EXPLAIN SELECT COUNT(1) FROM clicks WHERE date_added >= '2016-11-01 00:00:00' AND date_added <= '2016-11-16 23:59:59';
+----+-------------+--------+-------+---------------+------------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+------------+---------+------+---------+--------------------------+
| 1 | SIMPLE | clicks | range | date_added | date_added | 4 | NULL | 1559288 | Using where; Using index |
+----+-------------+--------+-------+---------------+------------+---------+------+---------+--------------------------+
Sin embargo, cuando yoLEFT JOIN
en milinks
En la tabla encuentro que la consulta tarda mucho más en ejecutarse:
SELECT
COUNT(1) AS clicks
FROM
clicks AS c
LEFT JOIN links AS l ON l.id = c.link_id
WHERE
c.date_added >= '2016-11-01 00:00:00'
AND c.date_added <= '2016-11-16 23:59:59';
Que se completó en 6.50 seg. UtilizandoEXPLAIN
Me parece que el índice no se utilizó en eldate_added
columna:
EXPLAIN SELECT COUNT(1) AS clicks FROM clicks AS c LEFT JOIN links AS l ON l.id = c.link_id WHERE c.date_added >= '2016-11-01 00:00:00' AND c.date_added <= '2016-11-16 23:59:59';
+----+-------------+-------+--------+---------------+------------+---------+---------------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+------------+---------+---------------+---------+-------------+
| 1 | SIMPLE | c | range | date_added | date_added | 4 | NULL | 6613278 | Using where |
| 1 | SIMPLE | l | eq_ref | PRIMARY | PRIMARY | 4 | c.link_id | 1 | Using index |
+----+-------------+-------+--------+---------------+------------+---------+---------------+---------+-------------+
Como puede ver, el índice no se está utilizando paradate_added
columna en la tabla más grande y parece tardar mucho más. Esto parece empeorar aún más cuando me uno a otras mesas.
¿Alguien sabe por qué sucede esto o si hay algo que pueda hacer para que use el índice en eldate_added
columna en la tabla de clics?
Editar
Acabo de intentar sacar mis estadísticas de la base de datos usando un método diferente. El primer paso en mi método consiste en extraer un conjunto distinto delink_id
s de la tabla de clics. Descubrí que estoy viendo el mismo problema aquí nuevamente, sin unirme. El índice no se está utilizando:
Mi consulta:
SELECT
DISTINCT(link_id) AS link_id
FROM
clicks
WHERE
date_added >= '2016-11-01 00:00:00'
AND date_added <= '2016-12-05 10:16:00'
Esta consulta tardó casi un minuto en completarse. Corrí unEXPLAIN
en esto y descubrí que la consulta no usa el índice como esperaba:
+----+-------------+---------+-------+---------------+----------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+----------+---------+------+----------+-------------+
| 1 | SIMPLE | clicks | index | date_added | link_id | 4 | NULL | 79786609 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+----------+-------------+
Esperaba que usaría el índice endate_added
para filtrar el conjunto de resultados y luego extraer el distintivolink_id
valores. ¿Alguna idea de por qué está sucediendo esto? Tengo un índice enlink_id
tanto comodate_added
.