Lorsque vous limitez le nombre de lignes à renvoyer par une requête SQL, généralement utilisée dans la pagination, il existe deux méthodes pour déterminer le nombre total d'enregistrements:
Méthode 1
Incluez l' SQL_CALC_FOUND_ROWS
option dans l'original SELECT
, puis obtenez le nombre total de lignes en exécutant SELECT FOUND_ROWS()
:
SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();
Méthode 2
Exécutez la requête normalement, puis obtenez le nombre total de lignes en exécutant SELECT COUNT(*)
SELECT * FROM table WHERE id > 100 LIMIT 10;
SELECT COUNT(*) FROM table WHERE id > 100;
Quelle méthode est la meilleure / la plus rapide?
la source
SQL_CALC_FOUND_ROWS
pris plus de 20 secondes; l'utilisation d'uneCOUNT(*)
requête distincte a pris moins de 5 secondes (pour les requêtes de nombre + résultats)SQL_CALC_FOUND_ROWS
sera plus rapide, je me demande dans quelles situations (le cas échéant) il est en fait plus rapide!tblA
,tblB
,tblC
,tblD
,tblY
OÙ tblA.b = tblC.id AND tblA.c = tblB.id AND tblA.d = tblD.id AND tblA.y = tblY.idid
), cela a pris 0,25 seul.FOUND_ROWS()
est obsolète dans MySQL 8.0.17. Voir aussi la réponse de @ madhur-bhaiya.Lors du choix de la «meilleure» approche, une considération plus importante que la vitesse peut être la maintenabilité et l'exactitude de votre code. Si tel est le cas, SQL_CALC_FOUND_ROWS est préférable car vous n'avez besoin de gérer qu'une seule requête. L'utilisation d'une seule requête exclut complètement la possibilité d'une différence subtile entre les requêtes principale et count, ce qui peut conduire à un COUNT inexact.
la source
MySQL a commencé à désapprouver les
SQL_CALC_FOUND_ROWS
fonctionnalités à partir de la version 8.0.17.Par conséquent, il est toujours préférable d'envisager d'exécuter votre requête avec
LIMIT
, puis une deuxième requête avecCOUNT(*)
et sansLIMIT
pour déterminer s'il existe des lignes supplémentaires.À partir de la documentation :
En outre, il
SQL_CALC_FOUND_ROWS
a été observé avoir plus de problèmes en général, comme expliqué dans le MySQL WL # 12615 :la source
LOCK TABLES <tablename>
etUNLOCK TABLES
. La troisième option et (meilleure IMHO) est de repenser la pagination. Veuillez lire: mariadb.com/kb/en/library/pagination-optimizationSelon l'article suivant: https://www.percona.com/blog/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Si vous avez un INDEX sur votre clause where (si id est indexé dans votre cas), il est préférable de ne pas utiliser SQL_CALC_FOUND_ROWS et d'utiliser 2 requêtes à la place, mais si vous n'avez pas d'index sur ce que vous avez mis dans votre clause where (id dans votre cas) alors utiliser SQL_CALC_FOUND_ROWS est plus efficace.
la source
IMHO, la raison pour laquelle 2 requêtes
sont plus rapides que d'utiliser SQL_CALC_FOUND_ROWS
doit être considéré comme un cas particulier.
Elle dépend en fait de la sélectivité de la clause WHERE par rapport à la sélectivité de la clause implicite équivalente à ORDER + LIMIT.
Comme Arvids l'a dit en commentaire ( http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-1174394 ), le fait que l'EXPLAIN utilise, ou non, une table temporelle, devrait être une bonne base pour savoir si SCFR sera plus rapide ou non.
Mais, comme je l'ai ajouté ( http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-8166482 ), le résultat dépend vraiment, vraiment du cas. Pour un paginateur particulier, vous pourriez arriver à la conclusion que «pour les 3 premières pages, utilisez 2 requêtes; pour les pages suivantes, utilisez un SCFR »!
la source
Suppression de certains SQL inutiles, puis
COUNT(*)
sera plus rapide queSQL_CALC_FOUND_ROWS
. Exemple:Alors comptez sans partie inutile:
la source
Il existe d'autres options pour vous de comparer:
1.) Une fonction de fenêtre renverra directement la taille réelle (testée dans MariaDB):
2.) En sortant de la boîte, la plupart du temps, les utilisateurs n'ont pas besoin de connaître la taille EXACTE de la table, une approximation est souvent suffisante.
la source