SQLite未将索引用于LIKE查询

1yjd4xko  于 2022-11-15  发布在  SQLite
关注(0)|答案(5)|浏览(196)

我一直在尝试让SQLite使用带有LIKE的索引,但无济于事。我试着整理了所有的案例,但还是没有结果。任何人都有任何关于如何让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%'
ztyzrc3y

ztyzrc3y1#

引用自SQLITE邮件列表(http://www.mail-archive.com/sqlite-users@sqlite.org/msg27760.html)
默认情况下,Like不区分大小写。要让它使用您的索引,您需要使索引不区分大小写:
在测试上创建索引TEST_NAME(名称COLLATE NOCASE);
或使类似区分大小写:
语法词大小写敏感类=1;

bxjv4tth

bxjv4tth2#

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

ilmyapht

ilmyapht3#

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

  • LIKE或GLOB运算符的左侧必须是具有文本关联性的索引列的名称。
  • LIKE或GLOB的右侧必须是字符串文字或绑定到不以通配符开头的字符串文字的参数。
  • 转义子句不能出现在LIKE运算符上。
  • 用于实现LIKE和GLOB的内置函数不得使用SQlite3_Create_Function()接口重载。
  • 对于GLOB运算符,必须使用内置的二进制排序序列对列进行索引。
  • 对于LIKE运算符,如果启用CASE_SENSITIVE_LIKE模式,则必须使用二进制归类序列对列进行索引,或者如果禁用CASE_SENSITIVE_LIKE模式,则必须使用内置的NOCASE归类序列对列进行索引。
qnakjoqk

qnakjoqk4#

我对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
aamkag61

aamkag615#

ILike确实有效,它基于dbeaver(chinook.db)中包含的SQLite数据库,

> sqlite3 chinook.db
> create index idx_artist_name_ic on Artist (Name collate nocase);
> .eqp on
> select Name from Artist where Name like = 'd%';
`--SEARCH TABLE Artist USING COVERING INDEX idx_artist_name_ic (Name>? AND Name<?)

这表明SQLite足够聪明,可以将类似于iCASE的函数转换为规则和。Unicode-字符可能会有问题。

相关问题