Quelle manière de compter un nombre de lignes devrait être plus rapide dans MySQL?
Ce:
SELECT COUNT(*) FROM ... WHERE ...
Ou l'alternative:
SELECT 1 FROM ... WHERE ...
// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()
On pourrait penser que la première méthode devrait être plus rapide, car il s'agit clairement d'un territoire de base de données et le moteur de base de données devrait être plus rapide que quiconque pour déterminer de telles choses en interne.
Lorsque vous COUNT(*)
, il faut compter les index de colonne, le résultat sera donc optimal. Mysql avec MyISAM engine stocke réellement le nombre de lignes, il ne compte pas toutes les lignes à chaque fois que vous essayez de compter toutes les lignes. (basé sur la colonne de la clé primaire)
Utiliser PHP pour compter les lignes n'est pas très intelligent, car vous devez envoyer des données de mysql à php. Pourquoi le faire quand vous pouvez obtenir la même chose du côté de mysql?
Si COUNT(*)
est lent, vous devez exécuter EXPLAIN
sur la requête et vérifier si les index sont réellement utilisés et où doivent-ils être ajoutés.
Ce qui suit n’est pas le chemin le plus rapide, mais il existe un cas dans lequel COUNT(*)
ne convient pas vraiment. Lorsque vous commencez à grouper les résultats, vous pouvez rencontrer un problème où COUNT
ne compte pas vraiment toutes les lignes.
La solution est SQL_CALC_FOUND_ROWS
. Ceci est généralement utilisé lorsque vous sélectionnez des lignes mais que vous devez toujours connaître le nombre total de lignes (par exemple, pour la pagination) . Lorsque vous sélectionnez des lignes de données, ajoutez simplement le mot clé SQL_CALC_FOUND_ROWS
après SELECT:
SELECT SQL_CALC_FOUND_ROWS [needed fields or *] FROM table LIMIT 20 OFFSET 0;
Une fois que vous avez sélectionné les lignes nécessaires, vous pouvez obtenir le nombre avec cette requête unique:
SELECT FOUND_ROWS();
FOUND_ROWS()
doit être appelé immédiatement après la requête de sélection des données.
En conclusion, tout dépend en fait du nombre d'entrées que vous avez et de ce qui est dans l'instruction WHERE. Vous devriez vraiment faire attention à la façon dont les index sont utilisés, quand il y a beaucoup de lignes (des dizaines de milliers, des millions et plus).
Après avoir parlé avec mes coéquipiers, Ricardo nous a dit que le moyen le plus rapide est:
show table status like '<TABLE NAME>' \G
Mais vous devez vous rappeler que le résultat peut ne pas être exact.
Vous pouvez aussi l'utiliser en ligne de commande:
$ mysqlshow --status <DATABASE> <TABLE NAME>
Plus d'informations: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html
Et vous pouvez trouver une discussion complète sur mysqlperformanceblog
Bonne question, bonnes réponses. Voici un moyen rapide de faire écho aux résultats si quelqu'un lit cette page et en manque la partie:
$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$count = $num["id"];
echo("$count");
J'ai toujours compris que les réponses ci-dessous me permettraient d'obtenir les temps de réponse les plus rapides.
SELECT COUNT(1) FROM ... WHERE ...
Cette requête (similaire à celle publiée par bayuah) affiche un résumé de Nice de tous les tableaux dans une base de données: (Version simplifiée de procédure stockée de Ivan Cachicatari que je recommande vivement).
SELECT TABLE_NAME AS 'Table Name', TABLE_ROWS AS 'Rows' FROM information_schema.TABLES WHERE TABLES.TABLE_SCHEMA = '
YOURDBNAME' AND TABLES.TABLE_TYPE = 'BASE TABLE'
;
Exemple:
+-----------------+---------+
| Table Name | Rows |
+-----------------+---------+
| some_table | 10278 |
| other_table | 995 |
Si vous devez obtenir le nombre total de résultats, vous pouvez adopter l'approche suivante:
SELECT SQL_CALC_FOUND_ROWS * FROM table_name LIMIT 5;
SELECT FOUND_ROWS();
Normalement, ce n'est pas plus rapide que d'utiliser COUNT
, mais on pourrait penser que c'est l'inverse qui se produit, car le calcul est effectué en interne et ne renvoie pas les données à l'utilisateur. On peut donc penser à une amélioration des performances.
Faire ces deux requêtes est bon pour la pagination pour obtenir les totaux mais pas particulièrement pour l'utilisation de clauses WHERE
.
J'ai fait quelques repères pour comparer l'heure d'exécution de COUNT(*)
à COUNT(id)
(id est la clé primaire de la table - indexée).
Nombre d'essais: 10 * 1000 requêtes
Résultats: COUNT(*)
est plus rapide 7%
VIEW GRAPH: benchmarkgraph
Mon conseil est d'utiliser: SELECT COUNT(*) FROM table
Peut-être que vous voudrez peut-être envisager de faire une SELECT max(Id) - min(Id) + 1
. Cela ne fonctionnera que si vos ID sont séquentiels et que les lignes ne sont pas supprimées. C'est cependant très rapide.
Essaye ça:
SELECT
table_rows "Rows Count"
FROM
information_schema.tables
WHERE
table_name="Table_Name"
AND
table_schema="Database_Name";
J'ai manipulé des tables pour le gouvernement allemand avec parfois 60 millions de disques.
Et nous avions besoin de connaître plusieurs fois le nombre total de lignes.
Nous, les programmeurs de bases de données, avons donc décidé que dans chaque table est un enregistrement, toujours l'enregistrement dans lequel le nombre total d'enregistrements est stocké. Nous avons mis à jour ce nombre, en fonction des lignes INSERT ou DELETE.
Nous avons essayé tous les autres moyens. C'est de loin le moyen le plus rapide.
Une instruction count (*) avec une condition where sur la clé primaire a renvoyé le nombre de lignes beaucoup plus rapidement pour moi en évitant l'analyse complète de la table.
SELECT COUNT(*) FROM ... WHERE <PRIMARY_KEY> IS NOT NULL;
C'était beaucoup plus rapide pour moi que
SELECT COUNT(*) FROM ...
EXPLAIN SELECT id FROM ....
a fait le tour pour moi. et je pouvais voir le nombre de lignes sous la colonne rows
du résultat.