考虑两个查询:
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)
与IN(1,2)
。问题:第二个查询的速度要慢大约50倍(在3 Gb数据库上,它是0.2s
vs 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)
最佳答案
FilterKeyIndex
不仅存储FilterKey
值,还存储实际表的rowid
,以便能够找到相应的行。索引在两列上排序。
在第一个查询中,当按顺序读取所有FilterKey
为1的索引条目时,rowid
值也按顺序排列。该rowid
与Log.Key
相同,因此没有必要进行进一步的排序。
在第二个查询中,Log.Key
值来自两次索引运行,因此不能保证对它们进行排序,因此数据库必须对所有结果行进行排序,然后才能返回第一个结果。
为了加快第二个查询的速度,您必须按Log
列的顺序读取所有Key
行,即,扫描表而不在索引中查找任何Log
行。放下FilterKeyIndex
或使用... FROM Log NOT INDEXED JOIN ...
。
关于sql - 索引字段上的多个过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39346438/