【実務・中級編】 コストモデルパラメータ – PostgreSQL

「PostgreSQLのプランナに何を信じさせるか?」――コストモデルパラメータと仲良くなる話

こんにちは。最近、若手エンジニアから「クエリがどうしても遅いんです。EXPLAINを見てるんですけど、インデックスが使われていないみたいで……」という相談をよく受けます。

PostgreSQLを使っていると、誰しも一度は突き当たる壁ですよね。「なんでPostgreSQLは、わざわざ遅いフルスキャン(Seq Scan)を選ぶんだ!」と画面の前で叫びたくなる気持ち、痛いほど分かります。

でもね、プランナは意地悪でやっているわけじゃない。彼らは彼らなりに、「データベースの物理的な特性」という前提知識に基づいて、最も速いルートを計算しているだけなんです。

今日は、その前提知識を左右する「コストモデルパラメータ」について、現場の知見を交えてお話しします。

—

プランナの頭の中にある「計算式」

PostgreSQLのプランナは、クエリを実行する前に「このルートならコストはこれくらい、あっちのルートならこれくらい」と計算をします。その計算に使われるのが、`postgresql.conf` にある、あの怪しげなパラメータたちです。

特に重要なのがこのあたり。

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

これ、実は「PostgreSQLのデフォルト値は、かなり保守的(HDD時代を想定)に設定されている」ということを意識しておく必要があります。

なぜ「4.0」なのか?

昔の機械式HDDは、ヘッドが物理的に移動するランダムアクセスが非常に遅かった。だから「ランダムアクセスはシーケンシャルアクセスの4倍時間がかかる」という前提でコスト計算をしていたわけです。

でも、今はどうでしょう? 多くの現場では爆速のSSDやNVMeが載っていますよね。SSDなら、ランダムアクセスもシーケンシャルアクセスも、コスト差はほとんどありません。

—

現場でよくある「インデックスが使われない」現象

SSD環境なのに、`random_page_cost` が「4.0」のままになっていると、プランナはこう考えます。

  • 「インデックスを使うとランダムアクセスが発生する。コストが高いから、いっそテーブル全体をシーケンシャルに読み込んだほうが速いんじゃないか?」

結果、本来はインデックスを引いたほうが速いケースでも、わざわざフルスキャンを選んでしまう。これが「インデックスが効かない!」と悩む原因の多くを占めています。

具体的な改善のアクション

もし皆さんの環境がフルSSDなら、まずはこれを試してみてください。

— セッション単位で試して、実行計画が変わるか確認する
SET random_page_cost = 1.1;

— EXPLAIN ANALYZE で実行計画を確認
EXPLAIN ANALYZE SELECT FROM users WHERE status = ‘active’;

`random_page_cost` を「1.1」や「1.0」程度まで下げてみて、実行計画が `Index Scan` に変わればしめたもの。劇的にクエリが速くなる瞬間です。

—

注意点:闇雲に触るのは禁物

ここまで読んで「よし、全サーバで設定を変えよう!」と思ったあなた、ちょっと待ってください。

コストパラメータは「データベース全体」の性格を定義するものです。特定のクエリだけを速くするためにむやみに触ると、別のクエリが逆に遅くなるという副作用が必ずついて回ります。

  • まずは「特定のセッション」で検証する: 上記の通り、`SET` コマンドで影響をシミュレーションしてください。
  • ハードウェアの特性を理解する: クラウドのストレージ(AWS EBSなど)の種類によっても、I/Oの挙動は微妙に違います。
  • 統計情報の更新を忘れない: 実はパラメータのせいではなく、単に `ANALYZE` が古くてプランナが騙されているだけ、というケースも非常に多いです。まずは `ANALYZE` して、それでもダメならパラメータ、というのが鉄則です。

—

最後に:パラメータは「設定」ではなく「対話」

データベースのチューニングは、機械的な作業ではありません。
PostgreSQLという「優秀だけどちょっと古い知識を持ったプランナ」に対して、「今のハードウェアはこんなに速いんだよ」「今はこういうデータの偏りがあるんだよ」と、設定値を通じて教えてあげる対話のようなものです。

教科書通りの設定値を盲信するのではなく、今の環境、今のデータ量に合わせて、少しずつチューニングしていく。そんな「職人気質」な視点を持つと、PostgreSQLとの付き合いがもっと楽しくなるはずですよ。

もし現場で「どうしてもプランナが言うことを聞かない!」という難問にぶつかったら、また相談してください。一緒に実行計画という名の「ラブレター」を読み解きましょう。

それでは、良いクエリライフを!

コメント

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