6
sqlite> explain query plan select max(utc_time) from RequestLog;
0|0|0|SEARCH TABLE RequestLog USING COVERING INDEX key (~1 rows) # very fast

sqlite> explain query plan select min(utc_time) from RequestLog;
0|0|0|SEARCH TABLE RequestLog USING COVERING INDEX key (~1 rows) # very fast

sqlite> explain query plan select min(utc_time), max(utc_time) from RequestLog;
0|0|0|SCAN TABLE RequestLog (~8768261 rows) # will be very very slow

当我单独使用minmax时,它工作得很好。但是,当我出于某种原因选择minand时,sqlite 会“忘记”索引。max有没有我可以做的配置(我Analyze已经用过,它不起作用)?或者对这种行为有什么解释吗?

编辑1

sqlite> .schema 

CREATE TABLE FixLog(
                    app_id text,  __key__id INTEGER,
                    secret text, trace_code text, url text,
                    action text,facebook_id text,ip text,
                    tw_time datetime,time datetime,
                    tag text,to_url text,
                    from_url text,referer text,weight integer,
                    Unique(app_id, __key__id)
                    );
CREATE INDEX key4 on FixLog(action);
CREATE INDEX time on FixLog(time desc);
CREATE INDEX tw_time on FixLog(tw_time desc);



sqlite> explain query select min(time) from FixLog;
0|0|0|SEARCH TABLE FixLog USING COVERING INDEX time (~1 rows)
sqlite> explain query select max(time) from FixLog;
0|0|0|SEARCH TABLE FixLog USING COVERING INDEX time (~1 rows)
sqlite> explain query plan select max(time), min(time) from FixLog;
0|0|0|SCAN TABLE FixLog (~1000000 rows)
4

1 回答 1

7

这是 sqlite 查询优化器的一个已知怪癖,如下所述:http ://www.sqlite.org/optoverview.html#minmax :

假设存在适当的索引,将优化以下形式的查询以在对数时间内运行:

 SELECT MIN(x) FROM table;
 SELECT MAX(x) FROM table;

为了使这些优化发生,它们必须完全按照上面显示的形式出现 - 仅更改表和列的名称。不允许添加 WHERE 子句或对结果进行任何算术运算。结果集必须包含单个列。MIN 或 MAX 函数中的列必须是索引列。

更新(2017 年 6 月 23 日):最近,这已更新为索引查找可能会满足包含单个 MAX 或 MIN 的查询(允许算术之类的东西);但是,它们仍然排除在单个查询中拥有多个这样的聚合运算符(因此 MIN,MAX 仍然很慢):

包含单个 MIN() 或 MAX() 聚合函数(其参数是索引的最左列)的查询可能会通过执行单个索引查找而不是扫描整个表来满足。例子:

SELECT MIN(x) FROM table;
SELECT MAX(x)+1 FROM table;
于 2012-08-25T06:12:35.653 回答