WordDelimiterGraphFilterを使用した際の過剰なクエリ展開

トピック作成者:ks-solruserml-bot (2024/06/04 22:19 投稿)
3
CloseClose

(The bot translated the original post https://lists.apache.org/thread/kbjgztckqdody9859knq05swvx5xj20f into Japanese and reposted it under Apache License 2.0. The copyright of posted content is held by the original poster.)

こんにちは:

現在、Solrインスタンスを5.1.0から8.7.0にアップグレードしています。インデックスには2億5000万以上のドキュメントがあります。これは以下の検索に対応しています:

https://trove.nla.gov.au/

クエリのフィルターチェーンでWordDelimiterGraphFilterを使用しており:

https://solr.apache.org/guide/8_7/filter-descriptions.html#word-delimiter-graph-filter

一部のクエリに対して非常に多くの句を生成し、クラスタに過度のCPU負荷をかけることが判明しました。場合によってはクラスタを再起動する必要がありました。

例えば、元のユーザークエリに対する“parsedquery”を見ると:

(McGillan OR McGillon OR McGillion OR McGillian OR McGillin OR M'Gillin OR M'Gillan OR M'Gillon)

次のようになっています:

(+((fulltext:"mcgillan mcgillon mcgillion mcgillian mcgillin mgillin mgillan mgillon"~5 fulltext:"mcgillan mcgillon mcgillion mcgillian mcgillin mgillin mgillan m gillon"~5 fulltext:"mcgillan mcgillon mcgillion mcgillian mcgillin mgillin m gillan mgillon"~5 fulltext:"mcgillan mcgillon mcgillion mcgillian mcgillin mgillin m gillan m gillon"~5 fulltext:"mcgillan mcgillon mcgillion mcgillian mcgillin m gillin mgillan mgillon"~5 ….

上記は一部抜粋で、実際のクエリにはこのフィールドに対して512の句が含まれています。他のフィールドでも同様の拡張が発生しており、全体のクエリには非常に多くの句が指定されることになります。

デバッガを使って調べたところ、QueryBuilder.analyzeGraphPhrase()がさまざまな組み合わせを生成しているメソッドであることがわかりました。このメソッドには次のコメントがあります:

“Creates a boolean query from the graph token stream by extracting all the finite strings from the graph and using them to create phrase queries with the appropriate slop.”

WordDelimiterFilter(現在は非推奨)に戻すと、解析されたクエリには次のようなものだけが追加されます:

fulltext:"(mc mcgillan) gillan (mc mcgillon) gillon (mc mcgillion) gillion (mc mcgillian) gillian (mc mcgillin) gillin (m mgillin) gillin (m mgillan) gillan (m mgillon) gillon"~5)

この設定では、他の設定で見られる負荷は発生しません。

WordDelimiterGraphFilterとその出力の解析方法は期待通りに機能していると考えられます。以下の問題に遭遇しました:

https://issues.apache.org/jira/browse/SOLR-13336

しかし、以下の設定:

https://solr.apache.org/guide/8_7/query-settings-in-solrconfig.html#maxbooleanclauses

を大幅に低い数値に設定するのが最善の解決策かどうかはわかりません。

過剰なクエリ展開を避ける方法を見つけたいと考えており、同様の問題に直面した方がいるかどうかをお尋ねしたいと思います。

アドバイスや提案をいただけると幸いです。

よろしくお願いします。

Francis

返信投稿者:ks-solruserml-bot (2024/06/04 22:19 投稿)

こんにちは Francis、

私も同様の問題に遭遇しました。ただし、これは特定のタイプの分析チェーン設定に依存することがわかりました。

この問題を回避するには、実際にグラフトークンストリームを生成しないように分析チェーンを構築することができます。このアドバイスは、一般的にはインデックス時に強く適用されます。なぜなら、インデックス時にトークンストリームのグラフ構造が破棄されるからです。しかし、あなたのケース(比較的大きなインデックスと問題を引き起こしているクエリ)では、次のことが正しい直感であると思います:

  1. 安全策としてmaxBooleanClauses制限を引き下げる。
  2. 最初からこの指数関数的な拡張を減少または排除するように分析チェーンを変更することで、負の機能的な影響を軽減する。

私のおすすめは、次のようにして2つの別々のfulltextフィールドにインデックスすることです:
1つはwdgfを分割のみに設定(例:"generateParts"/"splitOn"など)し、もう1つはwdgfを結合のみに設定(例:"preserveOriginal", "catenate")。これにより、グラフトークンストリームの生成を防ぎ、ここで見られるような指数関数的な拡張を防止することができます。

さらに、両立させたい場合(可能な限り)、上述のように設定された2つのフィールドをフレーズ検索(例:pf=fulltext_split,fulltext_catenate)に使用し、分割および結合に設定された3つ目のフィールド(現在の設定と推測される)をクエリフィールド(例:qf=fulltext_split_and_catenate)として使用できます。この場合の問題は、実際には暗黙のフレーズクエリ(pf)です。したがって、pfを完全に無効にする(空に設定する)ことで実用的な結果が得られるかもしれませんが、これは非常に大雑把な方法なので、絶対に必要でない限りpfを無効にすることはお勧めしません。

また、これに関連する大きな問題も興味深いものです(少なくとも私にとっては!):真の「位置グラフクエリ」の一般的な適用に向けた初期のステップがいくつかありました(例:LUCENE-7638 [1])。しかし、位置グラフクエリに固有の問題(LUCENE-7398 [2]でよく説明されているが、スパンクエリに特有のものではない)により、この機能の多くは最も一般的なクエリパーサーから事実上削除されています(例:LUCENE-8477 [3], LUCENE-9207 [4])。あなたの質問のタイミングは、私が最近、この「指数関数的な拡張」動作のパフォーマンス影響を示すベンチマークを追加する作業をしていることと共鳴しています(LUCENE-9204 [5]のコメント参照)。

Michael

[1] https://issues.apache.org/jira/browse/LUCENE-7638
[2] https://issues.apache.org/jira/browse/LUCENE-7398
[3] https://issues.apache.org/jira/browse/LUCENE-8477
[4] https://issues.apache.org/jira/browse/LUCENE-9207
[5] https://issues.apache.org/jira/browse/LUCENE-9204

ps- 関連するその他の問題やブログ投稿:
https://issues.apache.org/jira/browse/LUCENE-4312

https://opensourceconnections.com/blog/2018/02/20/edismax-and-multiterm-synonyms-oddities/
https://lucidworks.com/post/multi-word-synonyms-solr-adds-query-time-support/
http://blog.mikemccandless.com/2012/04/lucenes-tokenstreams-are-actually.html
https://www.elastic.co/blog/multitoken-synonyms-and-graph-queries-in-elasticsearch
https://michaelgibney.net/lucene/graph/

返信投稿者:ks-solruserml-bot (2024/06/04 22:19 投稿)

こんにちは Michael、

詳細な回答をありがとうございます。大変感謝しています。いくつかの提案を検討してみます。

旧WordDelimiterFilterに戻すとこの問題が発生しないことは分かっているのですが、可能であれば非推奨クラスを使用したくないと考えています。

この動作を回避するために、何らかの制限や閾値を設定できるパラメータや設定があれば素晴らしいのですが。「maxbooleanclauses」の設定を低く設定すると、クエリ処理の他の部分に悪影響を与える可能性があることを懸念しています(ただし、それが実際にどうなるかは確かではありません)。

よろしくお願いします。

Francis

返信投稿者:ks-solruserml-bot (2024/06/04 22:20 投稿)

こんにちは、

Legacy WordDelimiterFilter の件について触れ忘れていました。クエリ時の分析に限定して考えると、WDGF(WordDelimiterGraphFilter)による「指数的だが正確な」クエリの展開を、Legacy WDF(WordDelimiterFilter)による「線形だが不正確な」クエリに置き換えることになると90%確信しています。これが実際にあなたにとって有効な解決策かもしれませんが、これではグラフクエリの本来の動作を破壊してしまうでしょう。

fieldType の enableGraphQueries プロパティ [1] を false に設定してみましたか? ドキュメントは少し不透明ですが、QueryBuilder のコードを見ると、このプロパティは MultiPhraseQuery の使用を強制するようです。MultiPhraseQuery は同じ指数的な展開問題を抱えていないと思います。これがうまく機能すれば、確かにあなたが望んでいる「シンプルな切り替えスイッチ」になるはずで、指数的な展開を完全に回避するための「最も誤りの少ない」方法になるでしょう。(確実ではありませんが、これは WDGF を WDF に置き換えたときに得られるクエリと同じクエリを構築する結果になるかもしれません)... 特に、あなたの「フレーズスロップ」5 は、ほとんどの「通常のクエリ」に対して誤りを回避するための十分な余地を提供するはずです。

最初に提案したように、両方の方法でインデックスを作成する(1 つは分割、1 つは連結)ことでより良い機能を得られると思いますが、そこには検討すべきトレードオフがあります(特にインデックスサイズ!)。そしてそのアプローチでも完全に「正しい」わけではないと思います。

Michael

[1] https://solr.apache.org/guide/8_9/field-type-definitions-and-properties.html#general-properties

トピックへ返信するには、ログインが必要です。

KandaSearch

Copyright © 2006-2024 RONDHUIT Co, Ltd. All Rights Reserved.

投稿の削除

この投稿を削除します。よろしいですか?