なぜPostgreSQLのプランナは「あえて」遅い道を選ぶのか?
現場でPostgreSQLをいじっていると、一度は必ずぶち当たる壁がある。「どう見てもインデックスが効くはずのクエリなのに、なぜかSeq Scan(シーケンシャルスキャン)が選ばれている」という現象だ。
実行計画(EXPLAIN ANALYZE)を見て、プランナに悪態をついた経験がある人も多いだろう。だが、少し冷静になってPostgreSQLの心臓部——コストベース・オプティマイザのロジックに耳を傾けてみると、実は彼らなりに「最も合理的な選択」をしていることがわかる。
今回は、プランナが何を基準にスキャン手法を天秤にかけ、そしてなぜ時としてその判断が致命的な悲劇を招くのか、現場の視点から掘り下げていこう。
—
1. コスト計算の「分かれ道」
PostgreSQLのプランナは、クエリを実行する前に「このリクエストを処理するのに最もコストが低い方法はどれか?」を計算する。このコストは、I/Oコスト(ページ読み込み)とCPUコスト(タプル処理)の総和だ。
Index Scan vs Seq Scan の境界線
よく誤解されるが、インデックスは「常に速い」わけではない。
- Seq Scan: テーブルの先頭から末尾まで、まとめてページを読み込む。OSの先読み(Read-ahead)が効きやすく、シーケンシャルI/Oとしては極めて効率的だ。
- Index Scan: インデックスツリーを辿り、そこからヒープ(テーブル本体)のページをランダムアクセスで拾いに行く。
もし取得対象のレコードがテーブル全体の20%や30%を超えると、ランダムアクセスによるI/O負荷は、最初から最後まで総当たりするSeq Scanの負荷をあっという間に追い越してしまう。プランナは、「どれくらいの割合のデータを読み取れば、インデックスを使うよりSeq Scanの方が安上がりか」を、`random_page_cost` や `seq_page_cost` といったパラメータを基に緻密に計算しているんだ。
—
2. 統計情報の「ズレ」が引き起こす悲劇
ここまでは理論上の話だ。問題は、この計算の前提となる「統計情報(`pg_statistic`)」が実態と乖離した瞬間に発生する。
相関関係の盲点
PostgreSQLのプランナは、各カラムの分布をヒストグラムや最頻値で把握している。しかし、複数のカラムに跨がる複雑な条件や、インデックスを貼ったカラムとの「物理的な並び順の相関」までは、デフォルトでは完璧に追いきれない。
例えば、`created_at`(インデックスあり)でソートされたテーブルで、`WHERE created_at > ‘2023-01-01’` と指定したとする。もし統計情報が古く、データが直近で大量に投入されていたらどうなるか。プランナは「対象レコードはごくわずかだ」と誤認し、インデックススキャンを選択する。しかし、実際には膨大な量のレコードがヒットし、ランダムI/Oの嵐となってDBは悲鳴を上げる。
これこそが、パフォーマンストラブルの王道だ。
—
3. トラブルシューティング:我々エンジニアがすべきこと
「プランナが賢い」と信じすぎるのは禁物だ。現場でこの手の問題に遭遇したとき、私はまず以下の順序で切り分ける。
1. 統計情報の鮮度を疑う:
まずは `ANALYZE` だ。これだけで解決することも多い。統計情報が古いせいで、プランナが「過小評価」しているケースは本当に多い。
2. `EXPLAIN (ANALYZE, BUFFERS)` を叩く:
ただの `EXPLAIN` ではなく、`BUFFERS` オプションを付けて実行してほしい。どこでI/Oが発生しているか、共有バッファから読んでいるのか、OSキャッシュなのかが手に取るようにわかる。
3. 相関の強さを教える:
もしカラム間に強い相関があるなら、`CREATE STATISTICS` を使ってプランナに「このカラムとこのカラムはセットで動くんだ」というヒントを与えてやる必要がある。これは、中級者から一歩先へ進むための非常に強力なツールだ。
4. 最終手段としてのパラメータ調整:
`random_page_cost` を下げる(SSD環境ならデフォルトの4.0から1.1程度まで落とすのは定石だ)ことで、プランナの重み付けを現実に近づけることができる。
—
最後に:データベースと対話するということ
結局のところ、PostgreSQLのオプティマイザは、完璧な最適化エンジンではない。「与えられた断片的な情報から、最も確率の高い正解を導き出そうと努力する推論エンジン」だ。
我々エンジニアの仕事は、その推論エンジンが「正しい材料」を持って判断できるようにすること。統計情報を適切にメンテナンスし、時にはクエリの書き方を工夫して、彼らに正しい道筋を示す。この「データベースとの対話」こそが、運用における醍醐味だと思わないか?
次にプランナの選択に疑問を感じたら、ぜひ統計情報の裏側を覗いてみてほしい。そこには、機械的な処理とはまた違う、エンジニアリングの奥深さが詰まっているはずだ。
コメント