15

我一直试图让 sqlite 使用一个喜欢的索引,但无济于事。我试过整理 nocase,但仍然没有运气。任何人都对如何让 sqlite 像点击索引有任何想法。提前致谢

DROP TABLE IF EXISTS "test";
DROP TABLE IF EXISTS "test2";
DROP TABLE IF EXISTS "test3";
create table test(name TEXT COLLATE NOCASE);
create table test2(name TEXT);
create table test3(name TEXT);
create index idx_test_name on test(name);
create index idx_test2_name on test2(name);
create index idx_test3_name on test3(name COLLATE NOCASE);
insert into test(name) values('dan');
insert into test2(name) values('dan');
insert into test3(name) values('dan');
--explain query plan select * from test where name like 'test%' 
-- explain query plan select * from test2 where name like 'test%' 
-- explain query plan select * from test3 where name like 'test%' 
4

4 回答 4

19

从 sqlite 邮件列表中引用 (http://www.mail-archive.com/sqlite-users@sqlite.org/msg27760.html)

LIKE 默认情况下不区分大小写。要让它使用您的索引,您需要使索引不区分大小写:

CREATE INDEX test_name ON test (name COLLATE NOCASE);

或使 LIKE 区分大小写:

PRAGMA case_sensitive_like = 1;

于 2012-10-21T04:43:25.590 回答
4

在 SQLite 3.6.23.1 中,test使用了索引:

> explain query plan select * from test where name like 'test%';
TABLE test WITH INDEX idx_test_name

> explain query plan select * from test2 where name like 'test%';
TABLE test2

> explain query plan select * from test3 where name like 'test%';
TABLE test3

使用 SQLite 3.7.15 的开发版本,同时使用test's 和test3' 索引(索引 ontest2用于扫描,而不是搜索):

> explain query plan select * from test where name like 'test%';
SEARCH TABLE test USING COVERING INDEX idx_test_name (name>? AND name<?) (~31250 rows)

> explain query plan select * from test2 where name like 'test%';
SCAN TABLE test2 USING COVERING INDEX idx_test2_name (~500000 rows)

> explain query plan select * from test3 where name like 'test%';
SEARCH TABLE test3 USING COVERING INDEX idx_test3_name (name>? AND name<?) (~31250 rows)

所以答案是更新SQLite。

于 2012-10-21T10:12:29.810 回答
1

文档

由 LIKE 或 GLOB 运算符组成的术语有时可用于约束索引。这种使用有很多条件:

  • LIKE 或 GLOB 运算符的左侧必须是具有 TEXT 关联的索引列的名称。
  • LIKE 或 GLOB 的右侧必须是字符串文字或绑定到不以通配符开头的字符串文字的参数。
  • ESCAPE 子句不能出现在 LIKE 运算符上。
  • 用于实现 LIKE 和 GLOB 的内置函数不得使用 sqlite3_create_function() API 重载。
  • 对于 GLOB 运算符,必​​须使用内置的 BINARY 整理序列对列进行索引。
  • 对于 LIKE 运算符,如果启用 case_sensitive_like 模式,则必须使用 BINARY 排序序列对列进行索引,或者如果禁用 case_sensitive_like 模式,则必须使用内置 NOCASE 排序序列对列进行索引。
于 2017-03-22T20:33:06.603 回答
0

我也有同样的问题org.xerial/sqlite-jdbc "3.25.2"。一个简单的基于文本的索引没有与 LIKE 运算符一起使用。但是,如果我放=,索引就会被使用。我的表架构:

 create table if not exists test (ID INTEGER PRIMARY KEY, VALUE TEXT NOT NULL)
 create index test_idx on test(value)
 insert into test (ID,  VALUE) values (1, 'gold bangles')
 insert into test (ID,  VALUE) values (2, 'gold bandana')
 insert into test (ID,  VALUE) values (2, 'gold bracelet')

 explain query plan select * from test where value='gold bandana'

 Output:
 0|0|0|SEARCH TABLE test USING COVERING INDEX test_idx(VALUE=?)

 explain query plan select * from test where value like 'gold%'

 Output:
 0|0|0|SCAN TABLE test
于 2019-10-08T06:01:53.340 回答