10

我创建一个表使用这样的模式:

CREATE TABLE wordIndex(id integer primary key, word varchar(128), offset integer, length integer);
CREATE INDEX word_idx on wordIndex(word);

现在表有大约 450,000 行记录。当我在 ipod4 上使用下面的 Like 语句时,性能不好: select * from wordIndex where word like 'test acces%'; 使用解释输出:

explain select * from wordIndex where word like 'test acces%';
0|Trace|0|0|0||00|
1|Goto|0|16|0||00|
2|OpenRead|0|2|0|4|00|
3|Rewind|0|14|0||00|
4|String8|0|2|0|test acces%|00|
5|Column|0|1|3||00|
6|Function|1|2|1|like(2)|02|
7|IfNot|1|13|1||00|
8|Rowid|0|4|0||00|
9|Column|0|1|5||00|
10|Column|0|2|6||00|
11|Column|0|3|7||00|
12|ResultRow|4|4|0||00|
13|Next|0|4|0||01|
14|Close|0|0|0||00|
15|Halt|0|0|0||00|
16|Transaction|0|0|0||00|
17|VerifyCookie|0|2|0||00|
18|TableLock|0|2|0|wordIndex|00|
19|Goto|0|2|0||00|

可能我需要建立一个额外的倒排索引来提高性能还是......?提前谢谢!

4

3 回答 3

13

索引like在大多数数据库中并不一致。最好的办法是尽可能将查询重写为范围查询,因为随后将使用索引:

select *
from wordIndex
where word between 'test acces' and 'test acces{'

(左大括号是紧跟在“z”之后的 ASCII 字符。)

如果您正在寻找单词开头的模式(例如“%test”),那么您可能不得不让自己接受全表扫描。

编辑:

如今,当模式以常量开头时,大多数数据库中的索引和like*do` 都可以相处,因此您可以这样做:

select *
from wordIndex
where word like 'test acces%' ;

不过,我不是 100% 确定 SQLite,所以请检查执行计划以查看它是否使用索引。

于 2012-12-27T15:11:58.077 回答
5

Try this:

SELECT * FROM wordIndex
WHERE word COLLATE NOCASE BETWEEN @SearchString AND @SearchString || '~~~~~~~~~~'

"~" is the biggest ASCII symbol.

于 2012-12-27T15:16:37.593 回答
2

I will have a slightly different answer than Gordon Linoff, but with the same approach.

If you want to keep any characters that follow 'test acces' you should try this:

SELECT * FROM wordIndex
WHERE word > 'test acces' AND word < 'test accet';
于 2013-01-18T13:13:13.527 回答