在不牺牲索引使用的情况下,在SQLite LIKE中转义通配符(%,_)?

时间:2012-10-24 19:19:19

标签: c# .net performance sqlite indexing

我对SQLite查询有几个问题。实际上我开始认为SQLite不是为超过10行的表而设计的,实际上,SQLite是一场噩梦。

以下查询

SELECT * FROM [Table] WHERE [Name] LIKE 'Text%'

工作正常。 EXPLAIN表示使用了索引,并在约70ms之后返回结果。

现在我需要从.NET SQLite驱动程序运行此查询,因此我正在更改查询

SELECT * FROM [Table] WHERE [Name] LIKE @Pattern || '%'

未使用索引。当我在任何SQLite工具中运行以下查询时,也不使用索引

SELECT * FROM [Table] WHERE [Name] LIKE 'Text' || '%'

所以我猜SQLite没有实现任何类型的预处理逻辑。

行。让我们尝试解决它,我仍然绑定变量并执行以下操作

SELECT * FROM [Table] WHERE [Name] LIKE @Pattern

但现在我将%通配符添加到我的模式字符串的末尾,就像这样

command.Parameters.Add(new SQLiteParameter("@Pattern", pattern + '%'));

效果很慢。我不能说为什么,因为当我从SQLite工具运行此查询时,它工作正常,但是当我从.NET代码绑定此变量时,它运行缓慢。

行。我还在努力解决这个问题。我正在摆脱模式参数绑定并动态地构建这个条件。

pattern = pattern.Replace("'", "''");
pattern = pattern.Replace("%", "\\%");
where = string.Format("LIKE '{0}%' ESCAPE '\\'", pattern);

不再使用索引。由于ESCAPE,因此未使用它。当我跑

时,我看到了
EXPLAIN QUERY PLAN SELECT * FROM [Table] WHERE [Name] LIKE 'Text%' ESCAPE '\'

一旦我删除ESCAPE,它就会再次开始使用索引,查询结束时间为60-70毫秒。

更新

以下是结果。

EXPLAIN QUERY PLAN
SELECT * FROM [RegistryValues]
WHERE
     [ValueName] LIKE 'windir%' ESCAPE '\' 

SCAN TABLE RegistryValues (~3441573 rows)

和没有ESCAPE

的那个
EXPLAIN QUERY PLAN
SELECT * FROM [RegistryValues]
WHERE
     [ValueName] LIKE 'windir%'

SEARCH TABLE RegistryValues USING INDEX IdxRegistryValuesValueNameKeyIdKeyHiveFileId (ValueName>? AND ValueName<?) (~31250 rows)

更新

刚刚找到了这个

http://www.sqlite.org/optoverview.html

4.0 LIKE优化

The ESCAPE clause cannot appear on the LIKE operator

那我该怎么办呢?

我理解对吗?我无法在LIKE中使用SQLite运算符搜索包含通配符的字符串。我说通配符是_ % ^ !

这是不可能的,因为我无法摆脱他们。 实际上我可以,但在这种情况下我不能使用索引,因此查询效率不高。

我是对的吗?

2 个答案:

答案 0 :(得分:5)

LIKE在最后时,索引只能与%子句一起使用,以便SQLite可以将其重写为两个简单的比较(如EXPLAIN输出中所示)

因此,要获得相同的效果,请自行编写比较。 这要求您构造一些保证比任何匹配值“更大”的字符串(谨防非ASCII字符)。 而不是:

... WHERE Name LIKE 'Text%'

使用:

... WHERE Name BETWEEN 'Text' AND 'Textzzzzzzzzzzzzz'

或,作为参数:

... WHERE Name BETWEEN @Pattern AND @Pattern || 'zzzzzzzzzz'

(此构造永远不需要转义。:)

答案 1 :(得分:-1)

确保将查询包装在事务中。我一直在通过没有它的库进行一些查询,并且添加它会使速度提高10倍。

可能是性能问题的最佳资源:Improve INSERT-per-second performance of SQLite?