LIKE 'searchstr%' 应该使用索引吗?

问题描述 投票:0回答:2

我有一个包含多个字段的数据库:

word_id — INTEGER PRIMARY_KEY
word — TEXT
...

还有大约 15 万行。由于这是一本字典,因此我正在使用

'search_string%'
搜索带有掩码
LIKE
的单词。它曾经有效,需要 15 毫秒才能找到匹配的行。该表有一个字段索引
'word'

我修改了表(一些字段超出了范围),执行查询需要 400 毫秒,所以我明白了,因为它现在无法使用索引。使用

=
而不是
LIKE
进行直接查询会显示 10 毫秒结果。这里发生了什么事?

sql sqlite cocoa query-optimization sql-like
2个回答
42
投票

在这种情况下不能安全地使用索引。一个简单的实现将改变这一点:

... WHERE word LIKE 'search_string%'

进入

... WHERE word >= 'search_string' AND word < 'search_strinh'

通过增加搜索字符串的最后一个字符。大于和小于运算符可以使用索引,而 LIKE 则不能。

不幸的是,这在一般情况下不起作用。

LIKE
运算符不区分大小写,这意味着
'a' LIKE 'A'
为 true。上述转换将破坏任何带有大写字母的搜索字符串。

然而,在某些情况下,您“知道”区分大小写与特定列无关,并且上述转换是安全的。在这种情况下,您有两个选择。

在覆盖此特定字段的索引上使用

NOCASE
    整理序列。
  1. 通过运行 
    LIKE
  2. 在程序范围内更改
    PRAGMA case_sensitive_like = ON;
    运算符的行为
    
    
    这些行为中的任何一个都将使 SQLite 透明地为您完成上述转换;您只需像往常一样继续使用
  3. LIKE
,SQLite 将重写底层查询以使用索引。

您可以在 
SQLite 查询优化器概述页面

阅读有关“LIKE 优化”的更多信息。


8
投票
GLOB prefix*

解决方法

此方法确实使用索引,因此对于 LIKE prefix%

来说这是一个很好的解决方法,不需要修改表排序规则:

SELECT * FROM mytable WHERE mycolumn GLOB 'myprefix*'

来自
文档

GLOB
运算符与

LIKE

 类似,但其通配符使用 Unix 文件通配符语法。此外,与 
GLOB
 不同,
LIKE
 区分大小写。
另请参阅:

文本列上的索引可以加速基于前缀的 LIKE 查询吗?

在 Sqlite 3.40.1、Ubuntu 23.04 的大型数据库的TEXT

列上进行了测试,我拥有 7.5 亿行。查询结果几乎是即时的。

	

© www.soinside.com 2019 - 2024. All rights reserved.