Kouhei Sutou
kou****@clear*****
2013年 8月 15日 (木) 17:53:47 JST
須藤です。 In <7D2B4****@mail*****> "[groonga-dev,01626] match_column と Bool の演算を伴うフィルタを組み合わせた検索の挙動" on Wed, 14 Aug 2013 00:19:45 +0900, Motoi Washida <wm3****@mail*****> wrote: > さて早速なのですが、若干怪しい挙動を見つけてしまったのでお伝えします。 ありがとうございます! > 現象 > ---------------- > > フィルタとクエリを組み合わせて検索しようした時に、検索が引っかからないという現象に遭遇しました。 > > 具体的には、 > > - filter に何らかの Bool 演算を使用する > - その上で、 query に検索対象を明記しない(match_column を使う) > > と、一部検索が引っかかりませんでした。 > > - filter で Bool 演算や型を使用しない > - query で「content:夏休み」のように検索対象を明記する > > と期待通りにうまく行っているようでした。 例をつけてもらってありがとうございます。手元でも再現したので 確認しました。インデックスを使わない検索になり、かつ、 match_columnsを使う、とヒットしなくなっていました。 まず、どういうときにインデックスを使わなくなるかというと、例 えば否定演算子を使う時です。具体的にいうと、 --filter '!true' というようなときです。 これは、 > - filter に何らかの Bool 演算を使用する に対応します。 否定演算子を使うとどうしてインデックスを使わなくなるかという と、 すべてのレコード - 条件にマッチしたレコード という操作が必要になって、すべてのレコードが多ければ多いほど、 あるいは、条件にマッチしたレコードが多ければ多いほど遅くなる からです。すべてのレコードが多いと、最初に「すべてのレコード」 を用意するのが遅くなります。条件にマッチしたレコードが多いと、 すべてのレコードから該当レコードを除く回数が増えて遅くなりま す。 そうすると、インデックスを使ったほうが遅くなることがあるので、 インデックスを使わなくなります。 こういうときは、 --filter 'b == true' --filter 'b == false' というように「==」を使えばインデックスを使います。この場合は 条件にマッチしたレコード だけを求めればよくなるのでインデックスを使ったほうが効率よく なります。 (「==」を使う以外に「&!」を使うという方法もあります。) 次に、どうしてmatch_columnsを使うとヒットしなくなるかです。 これは、 > - その上で、 query に検索対象を明記しない(match_column を使う) に対応します。 match_columnsには複数の値を指定できます。例えば、 --match_columns 'a || b' と書くと、aまたはbのカラムの値にマッチする、という意味になり ます。 インデックスを使うときはここもいい感じに頑張るように作ってあ りますが、インデックスを使わないときは、grepのように逐次検索 をしています。このとき、すべてのレコードに対して、それぞれ 「カラムの値をとってきて、--queryに指定した値を含むか」をチェッ クします。このとき、match_columnsに指定したすべてのカラムにつ いて「カラムの値をとってきて、--queryに指定した値を含むか」を チェックするようにすればインデックスを使わない場合でもそれっ ぽく動くのですが、今はそこまで作りこんでいません。なぜなら、 インデックスを使わない検索処理をがんばるよりはインデックスを 使った検索処理の方に力を入れて高速にしたほうがうれしい場合が 多からです。また、そっちの方が「高速な全文検索エンジン」とい うgroongaの大事にしているポイントと合致するからです。 ということで、match_columnsを使ったときにインデックスを使わな いで検索する処理を頑張っていないからヒットしないのです。 次に、どうして > - filter で Bool 演算や型を使用しない > - query で「content:夏休み」のように検索対象を明記する > > と期待通りにうまく行っているようでした。 で期待通りに動くかです。 > - filter で Bool 演算や型を使用しない はインデックスを使った検索になるからです。 > - query で「content:夏休み」のように検索対象を明記する はカラムが特定できるのでカラムの値を取得して逐次検索ガ動くか らです。 とすると、インデックスを使っているかどうかはどうやって知れば いいの?というのが気になるところだと思います。実は、今は知る 方法はありません。。。速く結果が返ってきたら使っているだろう なぁというくらいです。groonga.logにどのインデックスを使った、 みたいなのを出そうと思っているのですが、まだ実装できていませ ん。。。 -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270) groongaサポート: http://groonga.org/ja/support/ パッチ採用はじめました: http://www.clear-code.com/recruitment/ コミットへのコメントサービスはじめました: http://www.clear-code.com/services/commit-comment.html