使用ORDER BY,SQLITE极其缓慢

时间:2018-06-09 15:53:09

标签: database performance sqlite sorting

我有一个像

这样的简单查询
SELECT * FROM "mytable" where col1="foo"

在约0.5秒内解析(大约100个结果,大约100,000行700 MB数据库文件)

但是,只要我添加ORDER BY,就需要120秒。

SELECT * FROM "mytable" where col1="foo" ORDER BY col2

即使我限制结果如此

SELECT * FROM (SELECT * FROM "mytable" where col1="foo" LIMIT 1) ORDER BY col2

它需要120秒,尽管几乎无需排序。

唯一的例外是如果我使用ORDER BY rowid(而不是ORDER BY col2)排序,或者当我这样做(0.5秒)时:

SELECT * FROM "mytable" WHERE rowid IN (SELECT rowid FROM "mytable"  WHERE col1="foo") ORDER BY col2

VACUUM对数据库进行了检查,并检查了数据库的完整性(确定),此问题仍然存在。 我使用的是SQLite版本:3.7.7.1,在phpLITEadmin和我的PHP代码中都出现了减速。

修改

EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo" 
selectid|order|from|detail
       0|    0|   0|SCAN TABLE mytable (~11345 rows)
EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo" ORDER BY col2
selectid|order|from|detail
       0|    0|   0|SEARCH TABLE mytable USING AUTOMATIC COVERING INDEX (col1=?) (~7 rows)
       0|    0|   0|USE TEMP B-TREE FOR ORDER BY

解决方案

好的,似乎我们找到了解决方案:出于某种神秘的原因需要CREATE INDEX col1_idx ON "mytable" (col1)。在col2上创建索引(要排序的列)没有区别(使用或不使用col2的索引排序120秒)。对我来说似乎是一个SQLite错误,因为没有索引col1的查询结果很快(0.5秒)并且排序一个非索引行(=根本没有排序)不应该花费120秒。即使对整个表SELECT * FROM "mytable" ORDER BY col2进行排序,SQLite也只需要7秒。

同样有趣的是:col1和col2的CREATE INDEX只用了1.5秒。因此,即使假设这种放缓的原因是SQLite自动创建查询的临时索引,它仍然无法解释SQLite需要如此长时间才能进行排序。

2 个答案:

答案 0 :(得分:1)

因此,似乎SQLite错误地认为构建临时索引({{3}})以运行查询而不是在内存中排序会更便宜。显然,为每个查询构建100,000行的索引并不是最优的查询计划。

一个明显的解决方案是在要执行查询/排序的列上添加索引。

CREATE INDEX col1_idx ON mytable (col1);
CREATE INDEX col2_idx ON mytable (col2);

答案 1 :(得分:0)

我们遇到了类似的问题,添加了一个虚拟计算值并将其用于排序解决了该“错误”:

SELECT *, (col2+0) AS col2_forSort FROM "mytable" where col1="foo" ORDER BY col2_forSort

或字符串(不是我们的情况):

SELECT *, (col2 || "") AS col2_forSort FROM "mytable" where col1="foo" ORDER BY col2_forSort

YMMV ...祝你好运!