MySQL从SQL_CALC_FOUND_ROWS
8.0.17版本开始就开始弃用功能。
因此,它总是优先考虑与执行查询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和索引使用方面)而不是记录号进行分页。讨论越来越按日期(再次允许使用索引)进行无限滚动,而不是按帖子编号分页。等等。
SQL_CALC_FOUND_ROWS
耗时超过20秒;使用单独的COUNT(*)
查询花费了不到5秒的时间(对于count + results查询)。