26

複数のフィールドを持つDBがあります

word_id — INTEGER PRIMARY_KEY
word — TEXT
...

..そして〜15万行。

'search_string%'これは辞書なので、 LIKE を使用してマスク付きの単語を検索しています。以前は問題なく動作し、一致する行を見つけるのに 15 ミリ秒かかりました。テーブルにはフィールドのインデックスがあります'word'。最近、テーブル (スコープ外のテーブルのいくつかのフィールド) を変更しましたが、何かが発生しました。クエリの実行に 400 ミリ秒かかっているため、現在はインデックスを使用できないことを理解しています。like の代わりに = を使用した単純なクエリは、10ms の結果を示します。誰かがここで何が起こっているのか知っていますか?

4

1 に答える 1

37

この場合、インデックスは安全に使用できません。素朴な実装はこれを変換します:

... WHERE word LIKE 'search_string%'

の中へ

... WHERE word >= 'search_string' AND word < 'search_strinh'

検索文字列の最後の文字をインクリメントします。大なり演算子と小なり演算子ではインデックスを使用できますが、LIKE では使用できません。

残念ながら、それは一般的なケースでは機能しません。演算子は大文字と小文字を区別しません。LIKEつまり、これ'a' LIKE 'A'は true です。上記の変換により、大文字の検索文字列が壊れてしまいます。

ただし、大文字と小文字の区別が特定の列に関係なく、上記の変換が安全であることがわかっている場合もあります。この場合、2 つのオプションがあります。

  1. NOCASEこの特定のフィールドをカバーするインデックスで照合シーケンスを使用します。
  2. LIKE実行して、オペレータープログラム全体の動作を変更しますPRAGMA case_sensitive_like = ON;

これらの動作のいずれかにより、SQLite は透過的に上記の変換を行うことができます。いつものように使い続けるだけLIKEで、SQLite は基になるクエリを書き換えてインデックスを使用します。

「LIKE 最適化」について詳しくは、SQLite クエリ オプティマイザーの概要ページをご覧ください。

于 2011-12-21T07:31:07.403 に答える