选择MAX或Order By Limit 1

Mr *_*ver 11 mysql performance

MIN/MAX与ORDER BY和LIMIT

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

我有一个大约300M行的表.

Select max(foo) from bar;大约需要15秒.跑步

Select foo from bar order by foo desc limit 1;需要3秒.跑步

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

编辑:因为我无法在这里显示表的结构:假设bar是ndb_cluster中没有关系的表,foo是没有索引的任意数据点.

Svi*_*ack 6

要避免完整传递,请添加一个INDEXon foo列.

  • 因为缺少索引意味着需要在表上进行完整传递. (3认同)
  • 假设foo上有一个索引,那么`MAX(foo)`或`by foo DESC limit 1`会更快吗? (2认同)

zin*_*nga 2

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

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

EXPLAIN 显示正在使用索引,并给出行数 46312,并额外说明“Using where;Using index”

运行查询大约需要 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 更有效。