🐘

【PostgreSQL】ヒント句効かない時は遺伝的問い合わせ(GEQO)が原因かも

2024/01/16に公開

はじめに

2023年やらかしカレンダーで「障害原因は多分join_collapse_limit!」みたいなこと書いたのですが、今回はその伏線回収です
https://zenn.dev/come25136/articles/fd8c78bc75758c
↑を事前に読むことを推奨します

現象

10個程度のJOINと個数自体が変動するパラメーターのクエリで、hint句が効くときと効かない時がある
(パラメータ固定で再現率100%)

効かない条件

https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/tuningrule9-base/

実行計画に遺伝的問い合わせ最適化が使用される場合、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