【问题标题】:MySQL SELECT MAX vs ORDER BY LIMIT 1 on WHERE clauseMySQL SELECT MAX vs ORDER BY LIMIT 1 on WHERE 子句
【发布时间】:2021-12-04 06:50:57
【问题描述】:

SELECT MAX vs ORDER BY LIMIT 1 个问题已经在这里回答了好几次了,但是如果我添加一个 WHERE 子句,事情就会发生巨大的变化

这是我的桌子:

Field Type Null Key Default Extra
id b'int' 'NO' 'PRI' None 'auto_increment'
'open_time' b'bigint' 'NO' 'UNI' None ''

请注意,这两列都已编入索引。

以下是请求:

SELECT id from table
WHERE open_time > 0
ORDER BY id DESC LIMIT 1

SELECT MAX(id) from BTCUSDT1mHist
WHERE open_time > 0

EXPLAIN ANALYZE 显示以下内容: 订购:

-> Limit: 1 row(s)  (cost=0.10 rows=1) (actual time=0.038..0.038 rows=1 loops=1)
    -> Filter: (table.open_time > 0)  (cost=0.10 rows=1) (actual time=0.037..0.037 rows=1 loops=1)
        -> Index scan on table using PRIMARY (reverse)  (cost=0.10 rows=2) (actual time=0.036..0.036 rows=1 loops=1)

MAX():

-> Aggregate: max(table.id)  (cost=325890.06 rows=1081033) (actual time=1025.181..1025.181 rows=1 loops=1)
    -> Filter: (table.open_time > 0)  (cost=217786.76 rows=1081033) (actual time=0.032..866.890 rows=2180645 loops=1)
        -> Index range scan on table using open_time  (cost=217786.76 rows=1081033) (actual time=0.031..705.926 rows=2180645 loops=1)

ORDER BY 在 0.0012 秒内完成,而 MAX() 在 1.026 秒内完成

我也读过这个question,但它似乎没有涵盖我的情况

问题是:为什么 MAX() 花费的时间比 ORDER BY LIMIT 长这么多?

【问题讨论】:

  • MAX查询会先获取open_time>0的所有行,然后检查所有ids,找出id的最大值。使用 ORDER BY 的查询将使用 id 上的索引获取最后一条记录,然后检查 open_time>0,并返回这条记录,如果第一个找到的记录恰好有一个 open_time>0,则速度会更快。
  • @Luuk 可能是这样,但是 SQL 操作的顺序应该首先是 WHERE,然后是 ORDER BY 和 LIMIT,然后是 eversql.com/…
  • 一般来说你可能是对的,但是 MySQL 看到 ORDER BY id LIMIT 1,并决定读取主键是最有效的,所以它评估 WHERE 在第二步。在另一个查询中没有 ORDER BY,但 where 子句使用 open_time,并且该字段上有一个索引,使 MySQL 选择该索引。

标签: mysql query-optimization


【解决方案1】:

在分析中比较:

    -> Index scan on table using PRIMARY (reverse)  (cost=0.10 rows=2) (actual time=0.036..0.036 rows=1 loops=1)

对比:

    -> Index range scan on table using open_time  (cost=217786.76 rows=1081033) (actual time=0.031..705.926 rows=2180645 loops=1)

检查 2 行必须比检查 2,180,645 行快很多。

ORDER BY id DESC LIMIT 1 的查询中,它使用主键索引。它从最后开始,因为它是相反的顺序。然后它只是向下迭代索引的叶节点(按降序排列),直到它检查也匹配open_time > 0 的第一行。然后LIMIT optimization 允许查询执行完成。根据其统计数据,它估计这将在检查 2 行后发生。

在带有MAX(id) 的查询中,它使用open_time 上的索引。但是因为它是一个范围条件open_time > 0,所以它不能假设在该范围的开始或结束处找到最大的 id。因此它必须检查open_time 索引中的每个 匹配条目,搜索id 的最大值(主键隐含地属于二级索引)。与LIMIT 的查询一样,不可能提前终止。

【讨论】:

  • 感谢您的回答!那么,如果没有 LIMIT 优化,MAX 和 ORDER LIMIT 方法会给出或多或少相似的结果?
  • 我想是这样,但是 MySQL 在这个查询中自动执行了 LIMIT 优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
  • 2014-11-30
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多