クエリプランナを「手懐ける」技術:join_collapse_limitの深淵
PostgreSQLのクエリプランナと向き合っていると、時折「なぜ、この単純なクエリがこんなに遅いのか」と頭を抱える夜があるはずだ。特にテーブル数が増え、JOINが複雑に絡み合うエンタープライズ級のスキーマでは、プランナは時として迷走する。
その迷走を制御するスイッチの一つが `join_collapse_limit` だ。今日は、このパラメータが単なる設定値を超えて、どのようにPostgreSQLの最適化エンジンと対話しているのか、その深層に踏み込んでみたい。
—
「魔法」の限界:プランナが見ている景色
まず、PostgreSQLのプランナがどのように「結合順序」を決めているかをおさらいしよう。
PostgreSQLは、結合対象のテーブルが増えるほど、検討すべき結合順序の組み合わせを階乗的に増やしていく。数テーブル程度なら全探索(Dynamic Programming)で最適解を見つけられるが、テーブル数が10を超えたあたりから、全探索は現実的ではない計算コストになる。そこで登場するのが、`geqo`(遺伝的アルゴリズム)や、今回解説する `join_collapse_limit` による制限だ。
`join_collapse_limit` は、平たく言えば「プランナがJOINの順序を入れ替えて最適化しようとする際の、最大テーブル数」だ。
デフォルト値は `8`。これは、「8個までのテーブルなら、どんな順序で結合するのが最速か徹底的に検討するよ。それ以上は、書かれた順序を尊重(あるいは制限)するからね」というプランナの意志表示でもある。
なぜこれがトラブルシューティングの鍵になるのか
現場でよくあるのは、複雑な `VIEW` や、動的に生成された `JOIN` が重なり、`join_collapse_limit` の閾値を超えてしまうケースだ。
プランナが最適化を諦めると、クエリは「書かれた順序通り」に実行されることが多くなる。開発者が書いたJOINの順序が、必ずしも統計情報に基づいた最適解とは限らない。特に、絞り込み条件(WHERE句)が後のテーブルにのみ存在する場合、先に巨大なテーブル同士を結合して中間結果を肥大化させる「メモリ殺し」なプランが生成されやすくなる。
ここで `join_collapse_limit` を適度に引き上げることで、プランナの「思考の枠」を広げ、より効率的なネステッドループやハッシュ結合の順序を再発見させることが可能になる。
「引き上げれば万事解決」ではない理由
「じゃあ、全テーブルを最適化対象にするために値を大きくすればいいのでは?」と思うかもしれない。だが、ここにはエンジニアとしての慎重さが求められる。
1. コンパイルタイムの増大
`join_collapse_limit` を大きくしすぎると、クエリの解析・最適化フェーズに費やす時間が爆発的に増える。数秒かかるクエリのために、数秒のプランニング時間を消費するようでは本末転倒だ。
2. 統計情報の精度との戦い
プランナはあくまで「統計情報」を信じて動く。もし統計が古い、あるいはヒストグラムが荒い状態で探索範囲を広げても、プランナは「間違った最適解」に自信を持ってたどり着いてしまう。
現場で「効く」チューニングの勘所
私が実務でこのパラメータを調整する際は、以下のステップを踏むようにしている。
- Explain Analyze でボトルネックの「中身」を見る:
JOINの順序が不自然で、中間結果が巨大になっている箇所を探す。
- 明示的な JOIN 構文を疑う:
`FROM A JOIN B …` という書き方は、実は `join_collapse_limit` の影響を強く受ける。あえて `FROM A, B, C` とカンマ区切りの古い構文(暗黙的JOIN)を混ぜることで、プランナに対して「ここは結合順序を入れ替えていいよ」というヒントを与えるテクニックもある(※ただし、可読性とのトレードオフは大きい)。
- まずは `SET LOCAL` で検証:
グローバル設定をいじる前に、特定のクエリに対してのみ `SET join_collapse_limit = 12;` を実行し、プランがどう変わるか、コストと実行時間がどう推移するかを徹底的に叩く。
最後に
PostgreSQLのプランナは非常に優秀だが、あくまで「確率的な推論」を行うプログラムだ。`join_collapse_limit` は、そのプログラムに「もう少し広い視野で考えてくれ」と頼むためのハンドルである。
パラメータをいじることは、エンジニアにとっての最後の切り札だ。安易に数値をいじるのではなく、なぜ今のプランナがその選択をしたのか、その思考のプロセスを読み解く努力を忘れないでほしい。
データベースエンジニアの醍醐味は、機械と対話し、その制約の中で最大限のパフォーマンスを引き出すことにある。この小さな設定値の向こう側に、あなたのクエリを爆速にする答えが眠っているはずだ。
コメント