SQLite加速选择collat​​e nocase

时间:2017-07-06 11:18:09

标签: sql sqlite select

我有SQLite db:

CREATE TABLE IF NOT EXISTS Commits
(
    GlobalVer INTEGER PRIMARY KEY,
    Data blob NOT NULL
) WITHOUT ROWID;
CREATE TABLE IF NOT EXISTS Streams
(
    Name char(40) NOT NULL,
    GlobalVer INTEGER NOT NULL,
    PRIMARY KEY(Name, GlobalVer)
) WITHOUT ROWID;

我想做1选:

SELECT Commits.Data
  FROM Streams JOIN Commits ON Streams.GlobalVer=Commits.GlobalVer
 WHERE 
    Streams.Name = ?
ORDER BY Streams.GlobalVer
LIMIT ? OFFSET ?

之后我想再做一次选择:

SELECT Commits.Data,Streams.Name
  FROM Streams JOIN Commits ON Streams.GlobalVer=Commits.GlobalVer
 WHERE 
    Streams.Name = ? COLLATE NOCASE
ORDER BY Streams.GlobalVer
LIMIT ? OFFSET ?

问题是第二选择工作超慢。我认为这是因为COLLATE NOCASE。我想加快它。我试图添加索引,但它没有帮助(可能是我做错了吗?)。如何以大约等于第一个查询的速度执行第二次查询?

1 个答案:

答案 0 :(得分:6)

只有当索引使用与查询相同的排序规则时,才能使用索引来加速搜索。

默认情况下,索引从表列中获取排序规则,因此您可以更改表定义:

CREATE TABLE IF NOT EXISTS Streams
(
    Name      char(40) NOT NULL COLLATE NOCASE,
    GlobalVer INTEGER  NOT NULL,
    PRIMARY KEY(Name, GlobalVer)
) WITHOUT ROWID;

但是,这会使第一个查询变慢。

要加速两个查询,您需要两个索引,每个索引一个。因此,对隐式索引使用默认排序规则,对显式索引使用NOCASE:

CREATE TABLE IF NOT EXISTS Streams
(
    Name      char(40) NOT NULL COLLATE NOCASE,
    GlobalVer INTEGER  NOT NULL,
    PRIMARY KEY(Name, GlobalVer)
) WITHOUT ROWID;
CREATE INDEX IF NOT EXISTS Streams_nocase_idx ON Streams(Name COLLATE NOCASE, GlobalVar);

(将第二列添加到索引会加快此查询中的ORDER BY。)