考虑两个问题:
SELECT Log.Key, Time, Filter.Name, Text, Blob
FROM Log
JOIN Filter ON FilterKey = Filter.Key
WHERE FilterKey IN (1)
ORDER BY Log.Key
LIMIT @limit
OFFSET @offset
和
SELECT Log.Key, Time, Filter.Name, Text, Blob
FROM Log
JOIN Filter ON FilterKey = Filter.Key
WHERE FilterKey IN (1,2)
ORDER BY Log.Key
LIMIT @limit
OFFSET @offset
差异为IN(1)
vs IN(1,2)
。问题:第二次查询慢50倍(在3 Gb数据库上0.2s
与13.0s
相比)!
我知道WHERE FilterKey IN (1,2)
等于WHERE FilterKey = 1 OR FilterKey = 2
。似乎只有单个过滤器才能与索引一起使用。为什么呢?
如何提高第二次查询的性能(使用多个条件)?
结构:
CREATE TABLE Filter (Key INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT)
CREATE TABLE Log (Key INTEGER PRIMARY KEY AUTOINCREMENT, Time DATETIME, FilterKey INTEGER, Text TEXT, Blob BLOB)
CREATE INDEX FilterKeyIndex on Log(FilterKey)
答案 0 :(得分:1)
FilterKeyIndex
不仅存储FilterKey
值,还存储实际表的rowid
,以便能够找到相应的行。索引按两列排序。
在第一个查询中,当按顺序读取FilterKey
为1的所有索引条目时,rowid
值也按顺序排列。 rowid
与Log.Key
相同,因此无需进行任何进一步排序。
在第二个查询中,Log.Key
值来自两个索引运行,因此无法保证它们已排序,因此数据库必须先对所有结果行进行排序,然后才能返回第一个结果行。
要加快第二个查询,您必须按Log
列的顺序读取所有Key
行,即扫描表而不查找任何Log
行在索引中。可以删除FilterKeyIndex
,也可以使用... FROM Log NOT INDEXED JOIN ...
。