【実務・中級編】 コスト定数設定 – PostgreSQL

その「遅いクエリ」、PostgreSQLの脳内補正がズレてるのかも?:コスト定数チューニングの話

現場でバリバリやってると、たまに遭遇するじゃないですか。「なぜかPostgreSQLがインデックスを使ってくれない」とか「明らかにフルスキャンの方が速いのに、インデックススキャンを強行して自爆してる」みたいなケース。

「クエリが悪いのか?」と思ってEXPLAIN ANALYZEを叩いても、インデックスは効いているし、統計情報も最新。それなのに、なぜかプランナが変な選択をする。

そんなとき、多くのエンジニアが最後に辿り着く「禁断の扉」が、今回お話しするコスト定数(Cost Constants)の設定です。

—

そもそも、プランナはどうやって実行計画を決めてるの?

PostgreSQLのプランナは、超優秀な数学者みたいなものです。彼らは「このクエリを実行するには、どれくらいのコスト(時間やリソース)がかかるか?」を計算して、最もコストが低いルートを導き出します。

その計算式で使われているのが、`postgresql.conf` にある一連のコスト定数たちです。

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

このデフォルト値を見て気づきませんか?「ランダムアクセスはシーケンシャルアクセスの4倍のコストがかかる」という前提で計算されているんです。これはHDD全盛期の考え方ですよね。

「SSD環境なのにHDDの常識」で動かしてない?

これが現代のインフラ環境における最大の落とし穴です。

最近の環境は、ほぼ間違いなく高速なSSDやNVMeですよね。SSDにおいて、データをランダムに読み込むコストは、シーケンシャルな読み込みとほとんど変わりません。

にもかかわらず、PostgreSQLはデフォルトの `random_page_cost = 4.0` を信じ切っている。つまり、「ランダムアクセスはめちゃくちゃ重いから、なるべくシーケンシャルスキャン(全件走査)を選ぼう」というバイアスが強くかかってしまっているんです。

結果、メモリに乗るような小さなデータセットならインデックスを引いた方が速いのに、プランナが「フルスキャンの方が安上がりですよ」と勘違いして、無駄にI/Oを発生させる……という悲劇が起こります。

実践:どうチューニングすべきか?

SSD環境であれば、まず最初に試すべきは `random_page_cost` の引き下げです。

1. 現在の設定を確認する

まずは今の設定値を見てみましょう。

SHOW seq_page_cost;
SHOW random_page_cost;

2. SSD向けに調整する(まずはここから)

多くの現場では、以下のように設定することで劇的にプランが改善することがあります。

— postgresql.conf または ALTER SYSTEM で設定
random_page_cost = 1.1;

なぜ「1.0」ではなく「1.1」なのか? 完全なイコールにすると、プランナが迷いすぎて、本来ならシーケンシャルの方が有利な場面でもインデックスを選んでしまうリスクがあるからです。少しだけランダムの方を重くしておくのが、経験上の「安全圏」ですね。

—

注意:安易に触ってはいけない「沼」

ここまで読んだあなたは「じゃあ全部数値をいじれば最強じゃん!」と思うかもしれません。ですが、ここで一つ、先輩からの忠告を。

「コスト定数は、魔法の杖ではありません」

特に以下の点には注意してください。

  • 統計情報が先です: プランナが間違える理由の9割は、コスト定数以前に「統計情報が古い」ことです。まずは `ANALYZE` を徹底してください。
  • クエリごとに設定を変えない: これをやり始めると、運用が地獄になります。基本はクラスタ全体で最適化し、どうしても特定のクエリだけどうにもならない場合は、そのクエリ内でのヒント句(pg_hint_plan)を検討すべきです。
  • 必ず計測する: 設定を変えるときは、必ず「変更前」と「変更後」の実行計画(EXPLAIN ANALYZE)を比較してください。想定外のクエリが改悪されることは日常茶飯事です。

最後に:データベースは「対話」

コスト定数の調整は、いわばPostgreSQLという名の「優秀だけど頑固な部下」の価値観を、今の現場環境に合わせて書き換えてあげる作業です。

「うちはSSDだから、もっとランダムアクセスを信じていいんだよ!」と教えてあげるだけで、PostgreSQLは驚くほど賢い選択をしてくれるようになります。

もし今、実行計画に納得がいかないクエリがあるなら、ぜひ一度この「価値観のチューニング」を試してみてください。意外なほどあっさりと、パフォーマンス不足が解消されるかもしれませんよ。

それでは、良いチューニングライフを!

コメント

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