「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との付き合いがもっと楽しくなるはずですよ。
もし現場で「どうしてもプランナが言うことを聞かない!」という難問にぶつかったら、また相談してください。一緒に実行計画という名の「ラブレター」を読み解きましょう。
それでは、良いクエリライフを!
コメント