选择MAX或Order By Limit 1

时间:2010-11-11 17:28:29

标签: mysql performance

MIN/MAX vs ORDER BY and LIMIT

要跟进这个问题:我发现一些结果与Sean McSomething所描述的非常不同:

我有一张大约300M行的表。

Select max(foo) from bar;大约需要15秒。运行

Select foo from bar order by foo desc limit 1;需要3秒。运行

肖恩的陈述“看起来像MIN()是要走的路 - 在最坏的情况下它更快,在最好的情况下无法区分”只是不适用于这种情况......但我不知道为什么。有人可以提供解释吗?

编辑:由于我无法在此处显示表的结构:假设bar是ndb_cluster中没有关系的表,foo是没有索引的任意数据点。

3 个答案:

答案 0 :(得分:6)

要避免完整通过,请在INDEX列上添加foo

答案 1 :(得分:1)

我遇到了这个问题,并认为我添加了我发现的内容。请注意,列已编制索引。我在MariaDB 10.2.14上运行。

我有一个类似SELECT MAX(created) FROM tbl WHERE group=0 AND created IS NOT NULL的查询。 (group,created)上有一个索引(两者都是整数,但创建的可以为NULL)。 group=0有很多条目,created IS NULL的条目不多。 tbl正在使用Aria存储引擎。

EXPLAIN显示正在使用的索引,并且行数为46312,额外说法"使用where;使用索引"

运行查询需要大约0.692秒,但状态有一些有趣的东西:

Handler_read_key: 1 Handler_read_next: 45131 Handler_read_prev: 0

这似乎表明该密钥正在被最大限度地完全扫描;使用MIN代替MAX似乎给出了类似的结果。这似乎表明MIN / MAX实际上无法利用优化来选择索引的第一个/最后一个条目。

但是,如果查询更改为SELECT created FROM tbl WHERE group=0 AND created IS NOT NULL ORDER BY created DESC LIMIT 1,而查询似乎需要大约相同的运行时间,并且EXPLAIN显示相同的信息,则状态显示:

Handler_read_key: 1 Handler_read_next: 0 Handler_read_prev: 0

如果将订单更改为ASC,我会得到类似的结果。在我看来,使用ORDER BY ... LIMIT可以跳过索引扫描,如果有很多行符合索引条件,如果我的理解是正确的话,这可能导致更快的查询。
请注意,对于上述结果,已经分配了足够的RAM和缓存来保存缓存中的所有索引,因此,可能是索引扫描很快。

我还没有完成其他条件(不同的MySQL版本和存储引擎)的任何实验,但我想这个故事的道德是,通过SHOW SESSION STATUS检查查询状态可能有助于为这些事情提供答案。
至少在这种情况下,即使可以使用索引,ORDER BY ... LIMIT也可能比MIN / MAX更有效。

答案 2 :(得分:0)

我有一个类似的情况,有关列的索引,但顺序由&限制解决方案似乎更快。这有多好:)