「PostgreSQLのクエリがなぜその実行計画を選んだのか、なんとなく雰囲気で眺めていない?」
もしあなたが、`EXPLAIN ANALYZE`の結果を見て「ふーん、Seq Scanか……遅いな」と溜息をついているだけなら、それは非常にもったいない。PostgreSQLには、プランナという優秀な(しかし時々ひねくれた)相棒がいて、彼がどうやって「最適」を導き出しているのかを知れば、チューニングの世界がガラリと変わるからだ。
今日は、プランナが裏側で計算している「コスト」の正体と、それを制御するレバーについて、現場の知見を交えて話そうと思う。
—
コストモデルの核心:プランナはどうやって「安さ」を決めるのか
PostgreSQLのプランナは、クエリを実行する際、あらゆる実行計画(インデックスを使うか、フルスキャンするか、ハッシュ結合かなど)の「コスト」を数値化して比較している。このコスト計算の根底にあるのが、設定ファイル(`postgresql.conf`)に潜んでいるパラメータ群だ。
特に重要なのが、ディスクアクセスの重みを決めるこれらだ。
- `seq_page_cost` (デフォルト: 1.0): シーケンシャルスキャンでページを1つ読み込むコスト。
- `random_page_cost` (デフォルト: 4.0): ランダムアクセスでページを1つ読み込むコスト。
ここで直感的に理解してほしいのは、「PostgreSQLは、ランダムアクセスをシーケンシャルアクセスの4倍もコストがかかる(=遅い)ものとして扱っている」という点だ。
なぜ「4」なのか?
昔のHDD時代なら、ヘッドのシーク時間がかかるため「ランダムはシーケンシャルの数倍遅い」という定説は正しかった。しかし、今はNVMeのSSDが当たり前の時代だ。ランダムアクセスとシーケンシャルアクセスの速度差は、以前ほど大きくない。
つまり、デフォルトの「4」という数値は、最新のハードウェアでは「ランダムアクセスを過小評価(必要以上に高いコストとして計算)している」可能性が高いということ。これが原因で、インデックスを使わずにわざわざ重いシーケンシャルスキャンを選択するような、非効率な判断をプランナが下すことがよくあるんだ。
—
実践:いつパラメータを調整すべきか
最近、僕が担当した案件で、数百万行のテーブルに対してインデックスが効かないケースがあった。クエリの実行計画を見ると、明らかにインデックススキャンの方が速いのに、プランナは頑なにシーケンシャルスキャンを選んでいた。
こういう時こそ、`random_page_cost`の出番だ。
手順:調整のステップ
1. 現状のコストを確認する
まずは今のコスト設定を確認しよう。
SHOW seq_page_cost;
SHOW random_page_cost;
2. ハードウェアに合わせて調整する
もし高性能なSSDを使っているなら、ここを思い切って下げてみる。
— セッション単位で試すのが鉄則
SET random_page_cost = 1.1;
— その状態でEXPLAINを叩いてみる
EXPLAIN ANALYZE SELECT …;
これだけで、プランナが「あ、インデックスを使った方が実は安いじゃん!」と方針転換することがある。ただし、絶対に注意してほしいのは、いきなり本番環境の全体設定を変えないことだ。
一部のクエリは速くなっても、別のクエリのプランが最悪な方向に転ぶ(レグレッション)リスクがある。まずはセッション単位で検証し、影響範囲を慎重に見極めるのがプロの作法だ。
—
現場からのアドバイス:魔法の杖ではない
勘違いしないでほしいのは、「`random_page_cost`を下げればすべて解決!」というわけではないということ。
- `effective_cache_size`の確認: OSがキャッシュとして使えるメモリ量をプランナに教える設定だ。これが小さすぎると、メモリに乗っているはずのデータまでディスクアクセスとして計算されてしまう。
- 統計情報の鮮度: `ANALYZE`を忘れていないか? プランナに渡す「地図」が古ければ、コスト計算がどれだけ正確でも、辿り着く先は迷宮だ。
まとめ:プランナと対話しよう
データベースエンジニアの仕事は、単にクエリを書くだけではない。プランナという「思考するエンジン」に、正しいハードウェアの特性を教え、最適なルートを走れるように環境を整えることだ。
まずは、自分の環境で `EXPLAIN` のコスト値を見ながら、試しに `random_page_cost` を少しだけいじってみてほしい。数字が変わるたびに、プランナがどう「考えを変えるか」を観察する。そのプロセスこそが、君を一段上のエンジニアへと引き上げてくれるはずだ。
また何か詰まったら、いつでも聞きに来てくれ。エンジニア同士、一緒に深掘りしていこうぜ。
コメント