sql - 索引字段上的多个过滤器

标签 sql performance sqlite

考虑两个查询:

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值也按顺序排列。该rowidLog.Key相同,因此没有必要进行进一步的排序。

在第二个查询中,Log.Key值来自两次索引运行,因此不能保证对它们进行排序,因此数据库必须对所有结果行进行排序,然后才能返回第一个结果。



为了加快第二个查询的速度,您必须按Log列的顺序读取所有Key行,即,扫描表而不在索引中查找任何Log行。放下FilterKeyIndex或使用... FROM Log NOT INDEXED JOIN ...

关于sql - 索引字段上的多个过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39346438/

相关文章:

java - 如何优化 2d java 游戏渲染?

java - SQLite (JDBC) 不写入数据

c# - 在 SQL Server 中使用 GO 关键字

sql - 是否有必要考虑删除现有索引,因为它是推荐索引的前缀

java - 如何在关闭浏览器时从数据库中删除数据

performance - OpenGL:绘制三角形和四边形混合的最快方法?

sqlite - 柔性 : How do bind an Sqlist query at an S:list to an S:Textarea

c# - SQLite.Net-PCL 连接找不到数据库

SQLITE:如果它们共享一列,则将行合并为单行

SQL Server 时间与午夜以上时间的比较