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
演算子 inを使用して、ワイルドカードを含む文字列を検索できませんSQLite
。ワイルドカードと言うことで_
%
^
!
逃げられないから無理。実際にはできますが、この場合はインデックスを使用できないため、クエリは効率的ではありません。
私は正しいですか?