q パラメータと fq パラメータの処理順序

(The bot translated the original post https://lists.apache.org/thread/4tokrxod41g2zb22sh42to1yzhc328x5 into Japanese and reposted it under Apache License 2.0. The copyright of posted content is held by the original poster.)
こんにちは、
検索クエリに q パラメータと fq パラメータの両方が含まれる場合、Solr または Lucene の内部ではどちらが先に実行されますか?
また、この実行順序を変更することは可能でしょうか?
よろしくお願いします。
Mingchun


こんにちは、Zhaoさん
こちらのキャッシュおよびコストのローカルパラメータを確認してみてください:
Solr公式ドキュメント
フィルタクエリがキャッシュされておらず、非常にコストが高い場合、上記のパラメータを使用することで、すべての q および fq の処理が終わった後に実行するよう Solr に指示することが可能です。
ただし、正確にどの順序で実行されるかは分かりませんが、おそらく並列で実行され、後で結果の積集合または和集合が作成されるのではないかと思います。
- Ufuk


こんにちは Ufukさん
ご回答いただきありがとうございます!
cost ローカルパラメータを使用して fq パラメータの実行順序を変更できるかどうか、試してみたいと思います。
また、Solr と Lucene のソースコードを調べて q のメインクエリと fq のフィルタクエリの実行順序を確認しようとしましたが、該当する部分を見つけることができませんでした。
もし何かヒントがあれば、ぜひ教えていただけると助かります。
よろしくお願いいたします。
Mingchun


失礼しました、交差 (intersection) のみが行われていると思います。
こちらをご覧ください:
SolrIndexSearcher.java の該当部分
--
よろしくお願いします、
Mikhail Khludnev


こんにちは Mikhail さん、
とても有益な情報を提供していただき、ありがとうございます!
通常のフィルターは最初に実行され、キャッシュされる(該当する場合)。その後、クエリが実行され、ポストフィルターが見つかった各ドキュメントに対して適用される。
このソースによると、スコア付きクエリ(q パラメータ)とフィルタークエリ(fq パラメータ)を組み合わせて BooleanQuery を作成する際、まず scoreQuery が追加され、その後に filterQuery が追加されるようです。
return new BooleanQuery.Builder()
.add(scoreQuery, Occur.MUST)
.add(filterQuery, Occur.FILTER)
.build();
ここで、2つの質問があります。
質問 1:
これは q パラメータによるインデックス検索が最初に実行され、その後に fq パラメータによるインデックス検索が実行されることを意味しますか?
質問 2:q パラメータと fq パラメータのインデックス検索の処理順序に関係なく、検索全体のパフォーマンスには影響がないと考えています。この理解は正しいでしょうか?
非常に参考になるヒントをいただき、本当にありがとうございます。
よろしくお願いします。
Mingchun


ここに2つの回答があります。
BooleanQuery.Builder.add()の呼び出し順やOccurの設定が、実行順序を決定するわけではありません。BooleanQueryは動的にインターセクション(AND 条件)を実行し、実際の値に適応します。これには多くの条件や特例があります。しかし、
SolrIndexSearcher.getProcessedFilter()を確認すると、フィルターは積極的に(eagerly)実行され、キャッシュされることがわかります(どちらもパラメータに依存します)。そのため、ほとんどの場合filterQueryはビットセット(またはその他の)として実体化されたフィルターになります。
これは、q と fq の選択性(マッチするドキュメント数)によって異なります。
特定のケースでは、コストが 100 を超えるフィルターを遅延適用することで、大きなパフォーマンス向上が得られる可能性があります。
--
よろしくお願いします、
Mikhail Khludnev


こんにちは、Mikhail。
回答ありがとうございます!
理解しました!
getProcessedFilter() メソッドについては、ソースコードで確認したところ、あなたの説明通りでした。
これは、
qとfqの選択性(マッチするドキュメント数)によって異なります。
特定のケースでは、コストが 100 を超えるフィルターを遅延適用することで、大きなパフォーマンス向上が得られる可能性があります。
この部分については少し理解できなかったのですが、もう少し詳しく説明していただけますか?
q と fq の一致するドキュメントの数に応じて、インターセクション計算の負荷が変動するために、検索全体のパフォーマンスが異なると言っているのでしょうか?それとも、q と fq が一致するドキュメントの数に応じて、filterQuery のフィルタリングプロセスの負荷が変化するということでしょうか?
私の理解では、filterQuery はスコアクエリとは独立して実行され、インデックス全体にフィルターロジックを適用してから、各々の結果のインターセクションを計算するので、q と fq の処理順序が検索全体のパフォーマンスに影響を与えることはないと思っていました。
よろしくお願いします。
Mingchun


高度に選択的な q(少数のドキュメントに一致する)と、選択性が低い fq(多くのドキュメントに一致する、ここではアクセス制御クエリとしましょう)を考えてみましょう。
これらをそのままクエリすると、フィルタクエリが重いものだと、フィルターの実行に時間がかかり、その後、少数のクエリ結果とのインターセクションをチェックするだけになります。
したがって、fq={!... cost=200 cache=false } ... のように指定すると、フィルタの実行が遅延され、主なクエリに一致する少数のドキュメントだけがチェックされるため、パフォーマンスが大幅に向上します。
注意:Luceneを直接使って、q= +{!.. main q} +{!.. filter q} のようにクエリを作成すると、最も効果的な方法でクエリを組み合わせることができ、主なクエリがインターセクションを駆動します。
注:Occur.FILTER をパーサーで使うのはまだ一般的ではありませんが、すでに # として表示されており、2つのクエリを組み合わせるのはクエリパーサーのクセにより簡単ではないかもしれません。
--
よろしくお願いします、
Mikhail Khludnev


こんにちは、Mikhail、
ご説明ありがとうございます。
パフォーマンスの向上は、小さなセットを大きなセットに対してインターセクションさせることによって達成されることが理解できました。
ああ、それは良いですね!
理解しました。
再度、ご丁寧な回答に感謝します。
よろしく、
Mingchun


はい。
通常のフィルターは最初に実行され、キャッシュされます(もしキャッシュが適用される場合)。その後、クエリが実行され、見つかった各ドキュメントに対してポストフィルターがチェックされます。
--
よろしくお願いします、
Mikhail Khludnev
トピックへ返信するには、ログインが必要です。