【テクニカル・上級編】 クエリプランナのコストモデル – PostgreSQL

PostgreSQLのクエリプランナと「コスト」の正体:ハードウェアを味方につけるための深層心理

PostgreSQLのパフォーマンスチューニングにおいて、多くのエンジニアがインデックスの追加や`VACUUM`の頻度に頭を悩ませます。しかし、いざスロークエリに直面したとき、`EXPLAIN ANALYZE`の結果を眺めても「なぜプランナはあえてそのインデックスを選ばなかったのか?」という疑問に辿り着いたことはありませんか?

プランナが下す判断の根拠。それは、データベースの深淵に刻まれた「コストモデル」です。今回は、プランナが何を考え、どうハードウェアの特性を解釈しているのか。その内幕を少し掘り下げてみましょう。

—

コストとは「理想化された時間」である

PostgreSQLのクエリプランナは、提示されたクエリに対して数千から数百万通りの実行計画を検討します。その中で「最もコストの低いもの」を選ぶわけですが、ここで言うコストは単なる「秒数」ではありません。

コストモデルの基盤となっているのは、以下のパラメータ群です。

  • `seq_page_cost`: シーケンシャルスキャンで1ページを読み込むコスト(デフォルト: 1.0)
  • `random_page_cost`: ランダムアクセスで1ページを読み込むコスト(デフォルト: 4.0)

この数値を変更するということは、プランナに対して「君が使っているストレージは、ランダムアクセスに対してどれだけ重いのか?」というハードウェアの特性を再定義することを意味します。

「デフォルト値」という名の呪縛

デフォルトの`random_page_cost = 4.0`。この設定は、HDD(ハードディスクドライブ)全盛期の遺産です。物理ヘッドが物理的に移動しなければならないHDDにおいて、シーケンシャルアクセスに比べてランダムアクセスは数倍遅いのが当然でした。

しかし、現代はどうでしょう。NVMe SSDが当たり前の環境において、シーケンシャルとランダムの読み込み速度の差は、HDDほど極端ではありません。

もしあなたがAWSのEBS(特にio1やgp3)や、高速なNVMe SSD上でPostgreSQLを運用しているなら、`random_page_cost`が4.0のままであることは、プランナに「ウソの情報」を与え続けているのと同じです。結果として、プランナは「ランダムアクセスが発生するインデックススキャン」を過度に避け、無駄な「テーブルフルスキャン(シーケンシャルスキャン)」を選択してしまうのです。

チューニングの現場:そのパラメータは誰のためにあるのか

私が大規模なデータベースのトラブルシューティングを依頼された際、真っ先に確認するのがこのコスト関連パラメータと、ストレージ特性の整合性です。

SSD環境であれば、`random_page_cost`を1.1〜1.5程度まで下げてみることを推奨します。これだけで、これまで無視されていたインデックスが急に採用され、劇的にクエリが高速化するケースを何度も見てきました。

ただし、注意が必要です。

1. 統計情報の鮮度: コストモデルはあくまで「統計情報(`pg_stats`)」に基づいて計算されます。`ANALYZE`が適時に実行されていない環境でコストパラメータだけをいじっても、プランナは盲目のまま走り出すことになります。
2. メモリの影響: `effective_cache_size`の設定も重要です。これは「OSがキャッシュとして使えるメモリ量」をプランナに伝えるものですが、この値が実態より小さいと、プランナは「ディスクからの読み込みが頻発する」と判断し、インデックススキャンを忌避する傾向があります。

最後に:プランナを「信じる」ことと「疑う」こと

データベースエンジニアとして長く仕事をしていると、プランナは時として驚くほど賢く、時として信じられないほど愚かな選択をすることが分かります。

プランナは「理想的なコストモデル」の中で最適解を探しているに過ぎません。そのモデルを支える土台(物理的なストレージの特性や、データの分布状況)が現実と乖離していれば、プランナを責めるのは筋違いというものです。

もしプランナが期待しない計画を立てるなら、それはプランナがあなたのハードウェアの強みを知らないからかもしれません。まずは`random_page_cost`を見直し、プランナと対話することから始めてみてください。

データベースは、あなたが与えたパラメータの分だけ、誠実に答えてくれるはずです。それが、PostgreSQLという深遠なシステムを使いこなす楽しさなのですから。

コメント

タイトルとURLをコピーしました