我有一张约150万行和3列的表格。专栏'时间戳'是REAL类型和索引。我通过PHP PDO访问SQLite数据库。
以下三个选项在不到一毫秒的时间内运行:
select timestamp from trades
select timestamp + 1 from trades
select max(timestamp) from trades
以下选择需要将近半秒钟:
select max(timestamp) + 1 from trades
为什么?
编辑: Lasse要求提供一个"解释查询计划",我已经在PHP PDO查询中运行了这个,因为我目前没有直接的SQLite3命令行工具访问权限。我想这没关系,结果如下:
explain query plan select max(timestamp) + 1 from trades:
[selectid] => 0
[order] => 0
[from] => 0
[detail] => SCAN TABLE trades (~1000000 rows)
explain query plan select max(timestamp) from trades:
[selectid] => 0
[order] => 0
[from] => 0
[detail] => SEARCH TABLE trades USING COVERING INDEX tradesTimestampIdx (~1 rows)
答案 0 :(得分:4)
此查询的原因
select max(timestamp) + 1 from trades
需要很长时间,查询引擎必须为每个记录计算MAX
值,然后向其中添加一个值。计算MAX
值涉及进行全表扫描,并且必须为每条记录重复此操作,因为您要为该值添加一个。
在查询中
select timestamp + 1 from trades
你正在对每条记录进行计算,但引擎只需扫描整个表一次。并在此查询中
select max(timestamp) from trades
引擎 必须扫描整个表格,但它也只扫描一次。
包含单个MIN()或MAX()聚合函数的查询,其参数是索引的最左列可能通过执行单个索引查找而不是通过扫描整个表
我从文档中强调可能,因为对于SELECT MAX(x)+1 FROM table
形式的查询,可能需要进行全表扫描
如果列x
不是索引的最左列。