10

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。ワイルドカードと言うことで_ % ^ !

逃げられないから無理。実際にはできますが、この場合はインデックスを使用できないため、クエリは効率的ではありません。

私は正しいですか?

4

2 に答える 2

6

インデックスは、SQLite が (出力に示されているように) 2 つの単純な比較に書き直すことができるように、最後にあるLIKE場合にのみ句と共に使用できます。%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 の 1 秒あたりの INSERT パフォーマンスを向上させますか?

于 2012-10-24T20:45:18.647 に答える