2017-09-10 1 views
1

J'ai une capture d'écran de table avec 3 champs:Index sur le champ de date mysql

CREATE TABLE `screenshot` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `UserID` int(11) NOT NULL, 
    `DateTaken` date NOT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `DateTaken` (`DateTaken`), 
    KEY `UserID` (`UserID`) USING BTREE, 
    CONSTRAINT `userID_foreign_key` FOREIGN KEY (`UserID`) REFERENCES `users` (`UserID`) 
) ENGINE=InnoDB AUTO_INCREMENT=22514871 DEFAULT CHARSET=latin1 

Et

SELECT @@innodb_buffer_pool_size 

Résultat: 16777216

Requête:

SELECT COUNT(ID) total 
     FROM screenshot WHERE DateTaken BETWEEN '2000-05-01' AND '2000-06-10' 

Résultat: 2828844

EXPLAIN:

ID|select_type| table |type |possible_keys| key |key_len| rows |Extra 
1 | SIMPLE |screenshot|range| DateTaken |DateTaken| 3 |5730138|Using where; Using index 

Voici mon problème: je index ajouté à la colonne DateTaken et encore les lignes de balayage (Expliquer la sortie) est plus grand que le résultat. Il semble que cela fasse toute une table de balayage. Et l'exécution de requête pour la requête prend 15 secondes. Comment puis-je améliorer la vitesse dans la requête ci-dessus?

Répondre

0

Vous pouvez essayer d'ajouter un indice composite

create index test on screenshot (DateTaken, id) 
+0

merci pour l'aide. La vitesse s'est améliorée mais le résultat de la ligne d'analyse est toujours le même. Connaissez-vous la raison pour laquelle? :) –

+0

Les index InnoDB incluent toujours la clé primaire. Remarquez que la sortie EXPLAIN de l'OP affiche "Using index" qui montre que même avec l'index à colonne unique sur DateTaken. Si elle était légèrement plus rapide après avoir suivi votre suggestion, je suggère que cela était dû au fait que l'index était complètement chargé dans le pool de mémoire tampon. –

0

Essayez d'exécuter cette requête:

SELECT COUNT(*) as total 
FROM screenshot 
WHERE DateTaken BETWEEN '2000-05-01' AND '2000-06-10'; 

La référence à ID dans le SELECT pourrait affecter l'utilisation de l'indice.

+0

J'ai une autonomie de 20 secondes. –

1

Il n'y a pas de problème. Votre index est bien. Pour expliquer ...

Le 5730138 dans EXPLAIN est une estimation. Il peut être plus grand ou plus petit que la valeur réelle, parfois d'une grande quantité. Ne soyez pas dérangé par cela.

Vous avez 2,8M de captures d'écran dans cette période, c'est bien? Eh bien, cela peut prendre 15 secondes pour analyser l'index pour compter autant de lignes.

Si vous souhaitez une analyse plus approfondie, s'il vous plaît fournir:
taille de la RAM
innodb_buffer_pool_size
SHOW CREATE TABLE screenshot; (cela va montrer le moteur)
Quelle est la taille de la table est (GB)
Quel type de disque que vous avez (spinning versus SSD)

Avec ceux-ci, nous pouvons discuter plus loin de l'impact de la mise en cache et des E/S et du moteur. Et cela peut aider à expliquer les "15 secondes" contre "20".

(Et, oui, utilisez COUNT(*), pas COUNT(x) à moins que vous devez tester x pour NULL.)

Si vous utilisez InnoDB, alors INDEX(DateTaken, id) est identique à INDEX(DateTaken), donc je suggère que vous étiez hâtive à accepter que répondre.

pool tampon

innodb_buffer_pool_size devrait être fixé à environ 70% de la RAM. Ce que vous avez est si petit (l'ancien 16M par défaut), que même l'index suggéré ne peut pas tenir dans le cache. Par conséquent, la requête va toujours frapper le disque, au moins une partie du temps. Augmenter le pool de mémoire tampon devrait améliorer considérablement la vitesse, peut-être jusqu'à 2 secondes.

+0

Quelle est la différence entre 'COUNT (*)' et 'COUNT (x)'? Je pense juste que 'COUNT (x)' est plus rapide, mais j'ai besoin de savoir pourquoi? Votre aide est grandement appréciée. :) –

+0

'COUNT (x)' a le surcoût supplémentaire de vérifier 'x IS NOT NULL' avant d'incrémenter le compteur de 1. Donc, dans presque toutes les applications,' COUNT (*) 'est meilleur. Vos horaires au contraire pourraient être un coup de chance. –

+0

J'ai ajouté plus ... –