【发布时间】:2018-06-09 15:53:09
【问题描述】:
我有一个简单的查询,例如
SELECT * FROM "mytable" where col1="foo"
在大约 0.5 秒内解决(大约 100'000 行的 700 MB 数据库文件的大约 100 个结果)
但是,我添加 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'ed 数据库并检查了数据库的完整性(好的),这个问题仍然存在。
我正在使用 SQLite 版本:3.7.7.1,减速出现在 phpLITEadmin 和我的 PHP 代码中。
编辑
EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo"
选择ID|订单|来自|详细信息
0| 0| 0|SCAN TABLE mytable(~11345 行)
EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo" ORDER BY col2
选择ID|订单|来自|详细信息
0| 0| 0|SEARCH TABLE mytable 使用自动覆盖索引 (col1=?) (~7 行)
0| 0| 0|使用 TEMP B-TREE 进行排序
解决方案
好的,我们似乎找到了解决方案:出于某种神秘原因需要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 创建索引只用了 1.5 秒。因此,即使假设这种速度变慢的原因是 SQLite 自动为查询创建了一个临时索引,它仍然无法解释 SQLite 需要这么长时间来排序的原因。
【问题讨论】:
-
你知道什么是索引吗?
-
EXPLAIN QUERY PLAN 的输出是什么?
-
@rustyx
EXPLAIN QUERY PLAN SELECT * FROM "mytablename" WHERE col1="foo"selectid|order|from|detail 0|0|0|SCAN TABLE mytablename(~11345 行)EXPLAIN QUERY PLAN SELECT * FROM "mytablename" WHERE col1="foo" ORDER BY col2selectid|order|from|detail 0|0|0|使用自动覆盖索引 (col1=?) 搜索表 mytablename (~7 行) 0|0|0|使用 TEMP B-TREE FOR ORDER BY -
在 col2 上创建索引,这样可以避免创建临时 btree
-
@Peeyush col2 上已有索引。我在 col2 上运行了有无索引的测试,结果相同 = 120 秒。
标签: database performance sqlite sorting