MySQL SELECT WHERE 子句上的 MAX 与 ORDER BY LIMIT 1
MySQL SELECT MAX vs ORDER BY LIMIT 1 on WHERE clause
SELECT MAX vs ORDER BY LIMIT 1 问题已经在这里回答了好几次,但是如果我添加一个 WHERE 子句,事情就会发生巨大变化
这是我的 table:
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)
最大值():
-> 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 秒内完成
我也读过这个,但它似乎没有涵盖我的情况
问题是:为什么 MAX() 比 ORDER BY LIMIT 花费的时间长得多?
分析比较:
-> 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 是在该范围的开始或结束处找到的。因此它必须检查 每个 索引中的匹配条目,搜索 id
的最大值(主键隐式地是二级索引的一部分)。没有提前终止的机会,因为在 LIMIT
.
的查询中
SELECT MAX vs ORDER BY LIMIT 1 问题已经在这里回答了好几次,但是如果我添加一个 WHERE 子句,事情就会发生巨大变化
这是我的 table:
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)
最大值():
-> 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 秒内完成
我也读过这个
问题是:为什么 MAX() 比 ORDER BY LIMIT 花费的时间长得多?
分析比较:
-> 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 是在该范围的开始或结束处找到的。因此它必须检查 每个 索引中的匹配条目,搜索 id
的最大值(主键隐式地是二级索引的一部分)。没有提前终止的机会,因为在 LIMIT
.