【问题标题】:sqlite3 select min, max together is much slower than select them separatelysqlite3 select min, max together 比单独选择它们要慢得多
【发布时间】:2012-07-17 02:12:24
【问题描述】:
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,但它运行良好。但是,当我出于某种原因同时选择minmax 时,sqlite 会“忘记”索引。有什么我可以做的配置吗(我已经使用了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)

【问题讨论】:

  • 你能添加你的索引定义吗?没有它就很难弄清楚发生了什么。
  • 我已经添加索引信息了。

标签: sql sqlite sql-execution-plan


【解决方案1】:

这是 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;

【讨论】:

    猜你喜欢
    • 2013-10-16
    • 2012-09-15
    • 1970-01-01
    • 2011-11-20
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    相关资源
    最近更新 更多