【PostgreSQL】ヒント句効かない時は遺伝的問い合わせ(GEQO)が原因かも
はじめに
2023年やらかしカレンダーで「障害原因は多分join_collapse_limit
!」みたいなこと書いたのですが、今回はその伏線回収です
↑を事前に読むことを推奨します
現象
10個程度のJOINと個数自体が変動するパラメーターのクエリで、hint句が効くときと効かない時がある
(パラメータ固定で再現率100%)
効かない条件
実行計画に遺伝的問い合わせ最適化が使用される場合、pg_hint_planによる結合順番の制御ができません。
ナ、ナンダッテ...
どうやらPostgreSQLに 遺伝的問い合わせ最適化(GEQO) というものがあり、これが行われると効かないらしい...
どういう時にGEQOが発動するのか
https://www.postgresql.jp/document/15/html/runtime-config-query.html にはこう書かれています
少なくともこれだけの数のFROM項目数があるときに、問い合わせを計画するのに遺伝的問い合わせ最適化を使用します。 (FULL OUTER JOINの生成子は、FROM項目が1つだけとして計算することに注意してください。) デフォルトは12です。
もっと単純な問い合わせでは、通常の、そしてしらみつぶしの検索プランナを使用するのが最善ですが、多くのテーブルを持つ問い合わせでは、しらみつぶしの検索は非常に時間がかかり、しばしば次善の計画を実行する代償より長くなります。
従って、問い合わせの大きさに対する閾値はGEQOの使用を管理するのに便利な方法です。
要はgeqo_threshold(デフォルト12)より多くJOINすると発動するよってことですね
わからせてみる
ヒント句に Set(geqo_threshold 100)
を足すだけ
(もしかしたらSet(geqo false)
でいいかもしれない)
結果
見事にタイムアウトが無くなりました!
めでたしめでたし...
結論
なんもわからん
デフォルト12なのに使ってるの10個だし...
おわりに
効かない条件が全く分からなくて困りました。というかアドカレ書いた時点で分かってないです...
しかし書いた直後、 もしかしてこれでは? と思うものがあったので試した次第です
ちなみに2023年内にやったので持ち越してないです!(前回の記事で年内解決したいと言ってた)
Discussion