首选解决方案
首先,found_rows() 函数不可移植(它是 MySQL 扩展)并且将被删除。正如用户 @Zveddochka 指出的那样,它已经在 MySQL 8.0.17 中被弃用。
但更重要的是,事实证明如果您使用正确的索引,那么运行两个查询实际上会更快。 SQL_CALC_FOUND_ROWS 指令是通过产生额外恢复成本的“虚拟扫描”实现的。当查询未编入索引时,此成本将与 COUNT() 相同,因此运行两个查询将成本翻倍 - 即,使用 SQL_CALC_FOUND_ROWS 将使运行速度提高 50%。
但是当查询被正确编入索引时会发生什么? The guys at Percona checked it out。事实证明,不仅COUNT() 非常快,因为它只访问元数据和索引,而且没有SQL_CALC_FOUND_ROWS 的查询更快,因为它不会产生任何额外的成本; 两个查询组合的成本低于增强型单个查询的成本:
SQL_CALC_FOUND_ROWS 的结果如下:对于每个 b 值
执行非缓存需要 20-100 秒,预热后需要 2-5 秒。这样的
差异可以通过此查询所需的 I/O 来解释
– mysql 访问该查询可能产生的所有 10k 行,没有 LIMIT
子句。
结果如下:运行此查询需要 0.01-0.11 秒
第一次和所有连续运行的 0.00-0.02 秒。
所以,正如我们所见,SELECT+COUNT 的总时间(0.00-0.15 秒)很多
少于原始查询的执行时间(2-100 秒)。让我们来一个
看看解释...
那么,该怎么办?
// Run two queries ensuring they satisfy exactly the same conditions
$field1 = "Field1, Field2, blah blah blah";
$field2 = "COUNT(*) AS rows";
$where = "Field5 = 'X' AND Field6 = 'Y' AND blah blah";
$cntQuery = "SELECT {$field2} FROM {$joins} WHERE {$where}";
$rowQuery = "SELECT {$field1} FROM {$joins} WHERE {$where} LIMIT {$limit}";
现在第一个查询返回计数,第二个查询返回实际数据。
旧答案(仅对非索引表有用)
不要这样做。如果您发现答案的这一部分比上面的部分更适合您,这几乎肯定是一个信号,表明您的设置中的其他东西不是最佳的 - 很可能您没有正确使用索引,或者您需要更新您的MySQL 服务器,或运行数据库分析/优化以更新基数统计信息。
你可以,但我认为这会成为性能杀手。
您最好的选择是使用SQL_CALC_FOUND_ROWS MySQL 扩展并发出第二个查询以使用 FOUND_ROWS() 恢复全部行数。
SELECT SQL_CALC_FOUND_ROWS * FROM t WHERE t.nid <1000 LIMIT 10;
SELECT FOUND_ROWS();
参见例如http://www.arraystudio.com/as-workshop/mysql-get-total-number-of-rows-when-using-limit.html
或者您可以简单地运行没有LIMIT 子句的完整查询,并且只检索前十行。然后您可以根据需要使用一个查询,还可以通过mysql_num_rows() 获取行数。这并不理想,但对于大多数查询来说也不是那么灾难性。
如果你最后这样做,关闭查询并释放其资源时要非常小心:我发现检索不到完整结果集并忘记释放 rs 句柄是 @ 987654323@.