如何优化SQLite索引?

时间:2011-03-18 10:39:11

标签: sqlite indexing

我有一个表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),但执行速度没有改变。

如何更改表中的索引以加快查询速度?

2 个答案:

答案 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不是必需的,因为它不是一个“提示机制”,而是一个硬性要求(如果模式更改使索引消失,将导致错误 - 但也许这就是你想。)