It still depends.
由于您想要进行一般评估,而不是针对您的查询:您不能做出一般假设,即其中一种方法会更快。 MySQL 将单独处理每个查询,如果找到更快的执行计划,它将使用它。
如果 MySQL 不需要所有行来为您提供请求的结果,添加 limit 可以缩短执行时间。
一个简单的例子是select * from table limit 1。 MySQL 可以取第一行然后停止,而不是读取整个表。
一个简单的反例是select * from table order by some_unindexed_column limit 1。 MySQL 必须读取整个表,对其进行排序,然后返回第一行。
让反例再次变快的一个简单对策是在some_unindexed_column 上添加一个索引。 MySQL 现在可以从索引中读取第一个条目,从表中读取相应的行并停止。 (这里的两个步骤使这个查询比第一个略慢)。
显然,如果添加limit 不会影响执行时间(我不包括必须向客户端发送更少行的影响),sql_calc_found_rows 也不会影响它。
评估相关count(*)-query 的执行时间通常更难,因为它通常只是一个不同的查询,不再具有直接可比性。例如。对于select count(*) from (select * from table order by some_unindexed_column) sub,order by 显然是多余的,如果您手动编写它,您只需将其删除,即使不是,MySQL 也会根据您的版本实际删除它。
所以你实际上会运行select count(*) from table。
完全巧合,这也是相关的count(*)-查询select * from table limit 1
这个计数查询比:
-
select * from table order by some_unindexed_column 因为它不需要做订购
-
select * from table order by some_unindexed_column limit 1 和 select sql_calc_found_rows * from table order by some_unindexed_column limit 1 以及它不需要进行排序(并且sql_calc_found_rows 对这种情况无效)
它比:
- select * from table limit 1 因为它必须读取所有行,而此查询可以在第一行之后停止
- select * from table order by indexed_column limit 1 因为它必须读取所有行,而 limit 查询可以使用 indexed(!) 列提前停止
一个特殊的,可能是唯一有趣的案例,与您阅读的blog 中的情况密切相关,是
select sql_calc_found_rows * from table order by indexed_column limit 1
此查询将读取索引,然后使用索引信息从原始表中读取数据(因为它需要所有列)。这个两步过程非常缓慢。它实际上非常慢,如果 MySQL 怀疑它必须从原始表中读取相当大比例的行,它可以决定不使用索引。另一方面,select count(*) from table 不需要这种两步查找。
这基本上是最相关的一般情况,count-query 表现更好,这正是您博客中发生的情况。 YMMV,但是通过这种方式可以实现 10 倍的性能提升,尽管通常会更少。
还有一种方法可以缓解这个问题:如果你添加一个covering index。如果你例如有一个索引 (a,b,c) 并且只能从中选择,例如select b, c from table order by a,这可以完全在索引内发生,不需要两步查找。
另一种情况是count(*) 允许 MySQL 选择尽可能小的索引。例如。对于select count(*) from table,MySQL 可以选择该表上的任何可用索引,对于小索引,您需要读取更少的字节。这比读取更多字节更快。 (对于 MyISAM 表,我将忽略这一点,计数存储在表中并且可以立即查找)。
可能还有更多的情况(或者像 select very_expensive_function(a) from table 这样的事情,如果你不执行该函数显然会变得更快),这可能会给你带来好处。
总结一下:
- 如果
limit 不改变执行速度,添加sql_calc_found_rows 没有效果,另外运行count(*) 查询显然只会增加更多时间。
- 如果
limit 确实改变了执行速度,那么添加sql_calc_found_rows 会使其变慢。如果运行额外的count(*) 比添加sql_calc_found_rows 更快取决于查询。
值得注意的是,这个分析是针对一个非常琐碎的查询。您的查询越复杂,count-version 比sql_calc_found_rows 快的可能性就越小(只是运气)。它还取决于您的 MySQL 版本。
根据您的描述,您的查询目前属于第一类,如果 MySQL 自己没有找到优化count-version 的方法,预计与原始的(这将使两个查询的总时间增加一倍)。任何更具体的内容(尤其是在您需要优化查询的帮助时)都需要查看您的特定查询。