我有一个像
这样的简单查询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需要如此长时间才能进行排序。
答案 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 ...祝你好运!