【実務・中級編】 コスト見積もりパラメータ – PostgreSQL

なぜPostgreSQLのプランナは「間違った道」を選ぶのか?コスト定数チューニングの勘所

現場でPostgreSQLをいじっていると、たまに遭遇するんですよね。「いや、そこはインデックス使ってくれよ!なぜフルスキャンなんだ!」と叫びたくなるようなクエリプラン。

`EXPLAIN ANALYZE`を叩いて、「コスト」という数字が並んでいるのを見ても、「これって結局、何基準で計算されているの?」と疑問に思ったことはありませんか?

今日は、PostgreSQLのオプティマイザが「どのルートが最速か」を判断するための頭脳である、コスト見積もりパラメータについて深掘りしてみましょう。ここを理解すると、DBエンジニアとしての「勘」が一段階鋭くなりますよ。

—

コスト見積もりの正体

PostgreSQLのプランナは、クエリを実行する前に「いくつかの実行計画」をシミュレーションし、最もコストが低いものを選びます。そのコスト計算のベースになっているのが、`postgresql.conf`にあるこれらの定数です。

  • `seq_page_cost` (デフォルト: 1.0)
  • `random_page_cost` (デフォルト: 4.0)
  • `cpu_tuple_cost` (デフォルト: 0.01)

これらは「相対的な重み付け」です。例えば`random_page_cost`が4.0ということは、「ランダムアクセスはシーケンシャルアクセスの4倍のコスト(時間がかかる)」とプランナが想定していることを意味します。

なぜデフォルト値ではダメなことがあるのか?

ここが一番のポイントです。PostgreSQLのデフォルト値は、実は「HDD(回転する磁気ディスク)」を前提に設計されています。

HDDの場合、ランダムアクセス(シーク)は物理的にヘッドを動かす必要があるため、シーケンシャルアクセスより圧倒的に遅い。だから`random_page_cost`が4.0と高めに設定されています。

しかし、現代のインフラはどうでしょう? そう、SSDやNVMeですよね。
物理的なヘッド移動がないSSDでは、ランダムアクセスとシーケンシャルアクセスの速度差は、HDDほど大きくありません。

このギャップを放置すると、プランナは「ランダムアクセスは高いから、インデックスを引くよりテーブル全体をスキャンした方がマシだな」と誤認し、インデックスを無視し始めます。これが「なぜインデックスが使われないのか?」の代表的な原因の一つです。

—

実践:どう調整すべきか?

現場でよくあるのは、SSD環境なのに`random_page_cost`が高いままになっているケース。まずはこれを疑いましょう。

1. SSD環境なら値を下げる

SSDを使っているなら、`random_page_cost`を1.1〜2.0くらいまで下げてみるのが定石です。

— セッション単位で試すならこれでOK
SET random_page_cost = 1.1;

— EXPLAINでどう変わるか見てみる
EXPLAIN SELECT FROM users WHERE status = ‘active’;

これだけで、今までフルスキャン(Seq Scan)を選んでいたプランナが、インデックススキャン(Index Scan)を選んでくれるようになることが多々あります。

2. `cpu_tuple_cost` の微調整

`cpu_tuple_cost`は、1行を処理するコストです。大規模なテーブルを結合(JOIN)するクエリで、プランナがNested Loopを嫌ってHash Joinばかり選ぶようなら、ここを少し小さくするとバランスが変わることがあります。ただし、ここはかなり繊細なパラメータなので、むやみにいじると他のクエリが遅くなるリスクがあります。

—

注意:設定は「全体」に影響する

ここで一つ、先輩として釘を刺しておきます。これらのパラメータはグローバル設定です。

特定のクエリを速くするために`random_page_cost`を下げたら、他のクエリの実行計画まで変わり、全体としてパフォーマンスが落ちる……なんてことはザラにあります。

  • まずは検証環境で試すこと。
  • 特定のクエリだけが問題なら、パラメータをいじる前にインデックスの見直しや統計情報の更新(ANALYZE)を優先すること。
  • それでもダメな時の「最後の手段」としてパラメータチューニングを使うこと。

これ鉄則です。

—

最後に

コストパラメータのチューニングは、いわば「プランナの価値観を今のハードウェアに合わせる作業」です。

「なぜこのプランナはこう動くのか?」と疑問を持ち、コスト定数に思いを馳せるようになれば、あなたも立派なデータベースエンジニアです。まずは現在の環境のディスク性能を想像して、`SHOW random_page_cost;` を叩くところから始めてみてください。

もし、設定を変えて劇的に速くなった時は、その感動を忘れないでくださいね。それがチューニングの醍醐味ですから。

それでは、また次回の記事でお会いしましょう!

コメント

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