10

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

以下查询

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

它工作正常。EXPLAIN表示使用了索引,并且在 about 之后返回了结果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运算符 in搜索包含通配符的字符串SQLite。通过说通配符,我的意思是_ % ^ !

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

我对吗?

4

2 回答 2

6

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

因此,要获得相同的效果,请自己编写比较。这要求您构造一些保证比较“大于”任何匹配值的字符串(注意非 ASCII 字符)。代替:

... WHERE Name LIKE 'Text%'

采用:

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

或者,作为参数:

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

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

于 2012-10-25T07:12:37.743 回答
-1

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

可能是关于性能问题的最佳资源:提高 SQLite 的每秒插入性能?

于 2012-10-24T20:45:18.647 回答