J'ai les deux tables suivantes dans MySQL (simplifié).Requête MySQL avec JOIN n'utilisant pas INDEX
clicks
(InnoDB)- contient environ environ 70.000.000 records
- a un index sur la colonne
date_added
- A une colonne
link_id
qui fait référence à un enregistrement de la tablelinks
links
(MyISAM)-
beaucoup moins
- Contient des dossiers, autour d'environ 65.000
Je suis en train d'exécuter des requêtes analytiques en utilisant ces tables. Je dois extraire des données, à propos des clics survenus à l'intérieur de deux dates spécifiées, tout en appliquant d'autres filtres sélectionnés par d'autres utilisateurs en utilisant d'autres tables et en les joignant à la table des liens.
Ma question tourne cependant autour de l'utilisation des index. Lorsque je cours la requête suivante:
SELECT
COUNT(1)
FROM
clicks
WHERE
date_added >= '2016-11-01 00:00:00'
AND date_added <= '2016-11-03 23:59:59';
Je reçois une réponse en 1.40 sec. En utilisant EXPLAIN
, je trouve que MySQL utilise l'index sur la colonne date_added
comme prévu.
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 |
+----+-------------+--------+-------+---------------+------------+---------+------+---------+--------------------------+
Cependant, quand je LEFT JOIN
dans mon tableau links
je trouve que la requête prend beaucoup plus de temps à exécuter:
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';
qui a terminé à 6,50 secondes. En utilisant EXPLAIN
Je trouve que l'indice n'a pas été utilisé sur la date_added
colonne:
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 |
+----+-------------+-------+--------+---------------+------------+---------+---------------+---------+-------------+
Comme vous pouvez le voir l'index n'est pas utilisé pour la colonne date_added
dans la plus grande table et semble prendre beaucoup plus longtemps. Cela semble devenir encore pire quand je me joins à d'autres tables.
Est-ce que quelqu'un sait pourquoi cela se produit ou s'il y a quelque chose que je peux faire pour l'utiliser pour utiliser l'index sur la colonne date_added
dans le tableau des clics?
Modifier
Je viens juste essayé d'obtenir mes statistiques de la base de données en utilisant une autre méthode. La première étape de ma méthode consiste à extraire un ensemble distinct de link_id
depuis la table des clics. J'ai constaté que je vois le même problème ici encore, sans JOIN. L'indice n'est pas utilisé:
Ma requête:
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'
Cette requête a pris près d'une minute.J'ai couru un EXPLAIN
sur ce sujet et trouvé que la requête n'utilise l'index comme je m'y attendais serait:
+----+-------------+---------+-------+---------------+----------+---------+------+----------+-------------+
| 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 |
+----+-------------+---------+-------+---------------+----------+---------+------+----------+-------------+
Je pensais qu'il utiliserait l'index sur date_added
pour filtrer sur le jeu de résultats, puis retirez la valeurs link_id
distinctes. Une idée de pourquoi cela se passe? J'ai un index sur link_id
ainsi que date_added
.
Veuillez ajouter ** index ** sur link_id dans les tables de clics qui peuvent aider à réduire le temps de sortie de la requête –
@SumanEStatic - 'INDEX (link_id)' ne serait pas utile. –
On dirait que vous utilisez MyISAM. S'il vous plaît fournir 'SHOW CREATE TABLE'. –