sqlite没有使用类似查询的索引

时间:2012-10-21 04:02:14

标签: sqlite

我一直试图让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 个答案:

答案 0 :(得分:14)

引用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;

答案 1 :(得分:3)

在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的开发版本,使用testtest3的索引(test2上的索引用于扫描,而不是搜索):

> 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。

答案 2 :(得分:1)

来自docs

  

有时由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整理顺序。
  •   

答案 3 :(得分:0)

我对org.xerial/sqlite-jdbc "3.25.2"也有同样的问题。一个简单的基于TEXT的索引不会与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