У меня есть пара проблем с 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 нет какой-либо логики предварительной обработки.
OK. Попробуем его решить, я все еще привязываю переменные и делаю следующее
SELECT * FROM [Table] WHERE [Name] LIKE @Pattern
Но теперь я добавляю символ %
подстановочного символа в конец строки шаблона, например
command.Parameters.Add(new SQLiteParameter("@Pattern", pattern + '%'));
Он работает очень медленно. Я не могу сказать, почему, потому что, когда я запускаю этот запрос из инструмента SQLite, он отлично работает, однако, когда я привязываю эту переменную от .NET-кода, он работает медленно.
OK. Я все еще пытаюсь решить это. Я избавляюсь от привязки параметров шаблона и динамически строю это условие.
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 мс.
UPDATE
Вот результаты.
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)
UPDATE
Просто нашел это
http://www.sqlite.org/optoverview.html
4.0 Оптимизация LIKE
The ESCAPE clause cannot appear on the LIKE operator
Итак, что мне тогда делать?
Я правильно понимаю? Я не могу искать строку, содержащую подстановочные знаки, используя оператор LIKE
в SQLite
. Говоря подстановочные знаки, я имею в виду _
%
^
!
Это невозможно просто потому, что я не могу избежать их. На самом деле я могу, но я не могу использовать индексы в этом случае, поэтому запрос не будет эффективным.
Я прав?