我有一个表t1和两个索引:
create index if not exists timeindex on t1(time, "Bytes Received")
create index if not exists filenameindex on t1(filename)
下一个查询执行得足够快:
select "Bytes Received" from t1 where time>="11:19:31.18" and time <= "11:19:36.18"
但是当我向WHERE语句添加一个附加条件时,查询会大大减慢
select "Bytes Received"
from t1
where time>="11:19:31.18" and time <= "11:19:36.18"
and filename = "SE12.log"
我尝试创建新索引t1(time, "Bytes Received", filename)
,但执行速度没有改变。
如何更改表中的索引以加快查询速度?
答案 0 :(得分:5)
使用BETWEEN
和以下索引:
CREATE INDEX IF NOT EXISTS fntimeindex ON t1(filename ASC, time ASC);
SELECT "Bytes Received"
FROM t1 INDEXED BY fntimeindex
WHERE filename = 'SE12.log'
AND time BETWEEN '11:19:31.18' AND '11:19:36.18';
另请注意,SQL字符串用简单的引号括起来(双引号用于表,模式和列名)。
答案 1 :(得分:1)
Benoit的答案是正确的,因为BETWEEN告诉Sqlite一个范围即将到来,所以它只需要在AND表达式中搜索索引一次(否则,它会搜索索引两次,一次搜索左手)一边,一边为右边)。这样可以减少一半的记录数量。 (如果在sqlite命令行工具中运行EXPLAIN QUERY PLAN,它将清楚地显示此信息。)
但是,Sqlite中的查询规划器喜欢每个表使用1个索引。为了解决这个问题,规范解决方案是将查询显式重写为一系列INTERSECTing子选择:
SELECT "Bytes Received" FROM t1 WHERE ROWID IN
(SELECT ROWID FROM t1 WHERE filename = 'SE12.log'
INTERSECT
SELECT ROWID FROM t1 WHERE time BETWEEN '11:19:31.18' AND '11:19:36.18'
)
显然,您可以添加更多子选项来处理其他条款。
使用INDEXED BY不是必需的,因为它不是一个“提示机制”,而是一个硬性要求(如果模式更改使索引消失,将导致错误 - 但也许这就是你想。)