当前位置:  开发笔记 > 后端 > 正文

哪个最快?SELECT SQL_CALC_FOUND_ROWS FROM`table`或SELECT COUNT(*)

如何解决《哪个最快?SELECTSQL_CALC_FOUND_ROWSFROM`table`或SELECTCOUNT(*)》经验,为你挑选了6个好方法。

当您限制通常在分页中使用的SQL查询返回的行数时,有两种方法可以确定记录总数:

方法1

SQL_CALC_FOUND_ROWS在原始文件中包含该选项SELECT,然后通过运行获取总行数SELECT FOUND_ROWS():

SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();  

方法2

正常运行查询,然后通过运行获取总行数 SELECT COUNT(*)

SELECT * FROM table WHERE id > 100 LIMIT 10;
SELECT COUNT(*) FROM table WHERE id > 100;  

哪种方法最好/最快?



1> nathan..:

这取决于.请参阅有关此主题的MySQL性能博客文章:http: //www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/

只是一个简短的总结:彼得说这取决于你的指数和其他因素.该帖子的许多评论似乎都说SQL_CALC_FOUND_ROWS几乎总是比运行两个查询慢 - 有时慢10倍.


我可以确认一下 - 我刚刚在168,000行数据库上更新了一个包含4个连接的查询.用`SQL_CALC_FOUND_ROWS`选择前100行花了20多秒; 使用单独的`COUNT(*)`查询花了不到5秒(对于计数+结果查询).
老话题,但对于那些仍然有趣的人!刚从10次检查完成对INNODB的检查我可以告诉它是26(2次查询)对9.2(1次查询)SELECT SQL_CALC_FOUND_ROWS tblA.*,tblB.id AS'b_id',tblB.city AS'b_city',tblC.id AS 'c_id',tblC.type AS'c_type',tblD.id AS'd_id',tblD.extype AS'd_extype',tblY.id AS'y_id',tblY.ydt AS y_ydt FROM`tblA`,`tblB`, `tblC`,`tblD`,`tblY` WHERE tblA.b = tblC.id AND tblA.c = tblB.id AND tblA.d = tblD.id AND tblA.y = tblY.id
非常有趣的发现.由于[MySQL的文档](http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows)明确建议`SQL_CALC_FOUND_ROWS`会更快,我想知道在什么情况下(如果有的话,它实际上*更快!
我刚刚运行了这个实验,SQLC_CALC_FOUND_ROWS比两个查询快得多.现在我的主表只有65k和两个数百的连接,但主查询有或没有SQLC_CALC_FOUND_ROWS需要0.18秒,但当我用COUNT(`id`)运行第二个查询时,它只需要0.25.

2> Jeff Clemens..:

在选择"最佳"方法时,比速度更重要的考虑因素可能是代码的可维护性和正确性.如果是这样,SQL_CALC_FOUND_ROWS是首选,因为您只需要维护一个查询.使用单个查询完全排除了主查询和计数查询之间存在细微差别的可能性,这可能导致COUNT不准确.


这取决于您的设置.如果您正在使用某种ORM或查询构建器,则可以非常轻松地使用相同的两个查询条件,交换计数的选择字段并删除限制.你永远不应该写两次标准.

3> patapouf_ai..:

根据以下文章:https://www.percona.com/blog/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/

如果你的where子句有一个INDEX(如果在你的情况下id被索引),那么最好不要使用SQL_CALC_FOUND_ROWS而是使用2个查询,但是如果你没有索引你在where子句中放入的内容(在您的情况下为id)然后使用SQL_CALC_FOUND_ROWS更有效.



4> Madhur Bhaiy..:

SQL_CALC_FOUND_ROWS8.0.17版开始,MySQL已开始弃用该功能。

因此,它总是优先考虑与执行查询LIMIT,然后用第二个查询COUNT(*),并没有LIMIT确定是否有其他行。

从文档:

从MySQL 8.0.17开始,SQL_CALC_FOUND_ROWS查询修饰符和随附的FOUND_ROWS()函数已弃用,并将在以后的MySQL版本中删除。

COUNT(*)受到某些优化。SQL_CALC_FOUND_ROWS导致一些优化被禁用。

请改用以下查询:

SELECT * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT COUNT(*) WHERE id > 100;

另外,SQL_CALC_FOUND_ROWS如MySQL WL#12615中所述,通常会遇到更多问题:

SQL_CALC_FOUND_ROWS有很多问题。首先,它很慢。通常,使用LIMIT运行查询,然后对同一查询使用单独的SELECT COUNT(运行会比较便宜,因为COUNT()可以利用在搜索整个结果集(例如文件排序)时无法完成的优化可以跳过COUNT(*),而对于CALC_FOUND_ROWS,我们必须禁用一些文件排序优化以保证正确的结果)

更重要的是,它在许多情况下的语义非常不清楚。特别是,当一个查询具有多个查询块(例如,使用UNION)时,根本无法在生成有效查询的同时计算“必须拥有”的行数。随着迭代器执行器朝着这类查询的方向发展,真正很难尝试保留相同的语义。此外,如果查询中有多个LIMIT(例如,对于派生表),则不一定清楚SQL_CALC_FOUND_ROWS应该指向哪个。因此,与之前相比,这种非平凡的查询在迭代器执行器中必然会获得不同的语义。

最后,大多数使用SQL_CALC_FOUND_ROWS似乎有用的用例应该仅通过除LIMIT / OFFSET之外的其他机制解决。例如,电话簿应按字母(在UX和索引使用方面)而不是记录号进行分页。讨论越来越按日期(再次允许使用索引)而不是按帖子编号分页进行无限滚动。等等。



5> Pierre-Olivi..:

恕我直言,2查询的原因

SELECT * FROM count_test WHERE b = 666 ORDER BY c LIMIT 5;
SELECT count(*) FROM count_test WHERE b = 666;

比使用SQL_CALC_FOUND_ROWS更快

SELECT SQL_CALC_FOUND_ROWS * FROM count_test WHERE b = 555 ORDER BY c LIMIT 5;

必须被视为一个特例.

事实上,它取决于WHERE子句的选择性与隐含的ORDER + LIMIT的选择性相比.

正如Arvids在评论中所说(http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-1174394),EXPLAIN使用与否的事实,一个临时表,应该是了解SCFR是否更快的良好基础.

但是,正如我添加的那样(http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-8166482),结果确实取决于具体情况.对于特定的分页符,您可以得出结论"对于3个首页,使用2个查询; 对于以下页面,使用SCFR"!



6> Jessé Catrin..:

删除一些不必要的SQL,然后COUNT(*)比删除速度更快SQL_CALC_FOUND_ROWS。例:

SELECT Person.Id, Person.Name, Job.Description, Card.Number
FROM Person
JOIN Job ON Job.Id = Person.Job_Id
LEFT JOIN Card ON Card.Person_Id = Person.Id
WHERE Job.Name = 'WEB Developer'
ORDER BY Person.Name

然后计算没有不必要的部分:

SELECT COUNT(*)
FROM Person
JOIN Job ON Job.Id = Person.Job_Id
WHERE Job.Name = 'WEB Developer'

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有