Pourquoi le décompte (*) est-il lent, alors que expliquer connaît la réponse?


14

Cette requête: select count(*) from planner_eventprend très longtemps à s'exécuter - si longtemps, j'ai abandonné et l'ai tuée avant qu'elle ne se termine. Cependant, lorsque je cours explain select count(*) from planner_event, je peux voir une colonne dans la sortie avec le nombre de lignes (14m).

Pourquoi expliquer peut-il obtenir le nombre de lignes instantanément, mais compter (*) prend beaucoup de temps pour s'exécuter?


COUNT (*) sans cause WHERE provoquera une analyse de table sur le moteur InnoDB. MyISAM peut délivrer le compte directement car le COUNT est conservé dans le fichier d'en-tête de la table.
Raymond Nijland

Réponses:


16

Explain utilise des statistiques précédemment collectées (utilisées par l'optimiseur de requêtes). Faire un select count(*)lit CHAQUE bloc de données.

Voici un moyen peu coûteux d'obtenir un nombre de lignes estimé:

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

Même si vous l'avez fait select count(id), cela peut encore prendre beaucoup de temps, sauf si vous disposez d'un index secondaire id(en supposant également qu'il ids'agit d'une CLÉ PRIMAIRE). Étant donné que toutes les données (y compris les données de ligne) sont stockées dans des index B-Tree, effectuer un select count(PK_COLUMN)est toujours une quantité considérable d'E / S (doit lire toutes les pages de données). Si vous avez un index secondaire sur le champ PK, il pourra effectuer moins d'E / S pour effectuer un comptage.


I_S.TABLES vous donne la même estimation que celle que EXPLAINvous donne.
Rick James

La requête est manquante AND TABLE_SCHEMA='my_database', sinon vous obtiendrez plusieurs résultats si vous avez une table avec le même nom dans une autre base de données.
cz

3

Explain obtient le nombre de certaines "statistiques" utilisées pour estimer les choses pour l'Optimizer. Ce nombre peut être loin d'être correct - je le vois parfois être plus d'un facteur 2 (supérieur ou inférieur) à la valeur exacte.

L'exécution de la COUNT(*)sur une table InnoDB doit analyser la table pour éviter les enregistrements erronés qui sont occupés à être insérés / supprimés par d'autres connexions mais pas encore "validés". En fait, il suffit de faire une analyse complète sur certains index, pas nécessairement sur toute la table (qui contient le PRIMARY KEY).

De combien de RAM disposez-vous? Quelle est la valeur de innodb_buffer_pool_size? Cela pourrait aider si c'était environ 70% de RAM.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.