2011-12-21 9 views
14

私はいくつかのフィールドSQLite:LIKE 'searchstr%'はインデックスを使用する必要がありますか?

word_id — INTEGER PRIMARY_KEY 
word — TEXT 
... 

..and〜150kの行でDBを持っています。

これは辞書なので、LIKEを使用してマスク'search_string%'で単語を検索しています。 これはうまく動作していましたが、一致する行を見つけるのに15msを要しました。このテーブルには、フィールド'word'のインデックスがあります。 最近、私はテーブルを修正しました(そのテーブルのいくつかのフィールドは範囲外です)何かが起きました。クエリを実行するのに400msかかるので、今はインデックスを使用できません。 likeの代わりに=を使用した簡単なクエリは、10msの結果を示します。 誰かがここで何が起こっているのか考えていますか?

+0

私はそう思うでしょう、あなたはおそらくBツリーは範囲のクエリと比較のような効率的なので、Bツリーを見たいと思うでしょう。 – Jasonw

+0

ええと、インデックスを作成しないで、b-treeの作成を考えていますか?つまり、自分でbツリーを作成する必要がありますか? – nikans

+0

%は検索語の最後にのみ表示されます。 – mikel

答えて

25

インデックスはこのケースでは安全に使用できません。検索文字列の最後の文字をインクリメントすることにより

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

... WHERE word LIKE 'search_string%'

:素朴な実装では、この変換でしょう。より大きいおよびより小さい演算子は、索引を使用できます(LIKEは索引を使用できません)。

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

ただし、をご存知の場合特定の列では大文字と小文字の区別が関係しないため、上記の変換は安全です。この場合、2つの選択肢があります。

  1. この特定のフィールドをカバーするインデックスにNOCASE照合シーケンスを使用してください。
  2. 変更透過的にあなたのための上記の変換を行うためのSQLiteを可能にします

これらの行動のどちらかPRAGMA case_sensitive_like = ON;を実行して、プログラム全体LIKEオペレータの行動。いつものようにLIKEをそのまま使用すれば、SQLiteはインデックスを使用するために基礎となるクエリを書き換えます。

SQLite Query Optimizer Overview pageの「LIKE最適化」について詳しく読むことができます。

+1

くそー!上記のスレッドでは、前回作成したインデックスを作成したときにいくつかのパラメータを使用していることに触れました。だから、それは '一括 'です。私は無駄にそれを見つけるために6時間のように過ごしました。ニースのリンク、私もそれを読んだが、それはちょうど私の注意から滑っているようだ。ありがとう、ホーマー!あなたは私を救ったばかりですが、神はどれくらいの時間を知っていますか? – nikans

+0

私はあなたが 'PRAGMA case_sensitive_like = ON;を意味すると思います。あなたが言ったように、' LIKE'はデフォルトで大文字と小文字を区別しません。あなたがリンクしている記事から: "組み込みのBINARY照合順序を使用して演算子の左側に指定された列が索引付けされ、case_sensitive_likeがオンになっている場合、LIKE最適化が行われる可能性があります。 –

+0

ああ、本当です。私はそれを修正します。ありがとう! –

関連する問題