「またプランナが変な気を起こして、全件スキャンを始めやがった……」
そんな経験、一度や二度じゃないですよね。PostgreSQLのクエリチューニングをしていると、必ずぶつかる壁が「プランナの勘違い」です。特に、重い計算処理や独自の関数をWHERE句やSELECT句にガッツリ詰め込んだクエリで、インデックスを使ってくれない時のあの絶望感。
今日は、そんな時に最後の切り札となる`cpu_operator_cost`について、現場目線で深掘りしてみようと思います。マニュアルには載っていない、僕たちがどう向き合うべきかというお話です。
—
なぜプランナは「間違った」判断をするのか?
PostgreSQLのクエリプランナは、基本的に「コストベース」で動いています。彼らは「データにアクセスするコスト」と「CPUで計算するコスト」を天秤にかけて、一番安上がりなルートを選ぼうとします。
ここで重要になるのが、デフォルトで設定されているコスト係数たちです。
- `seq_page_cost` (デフォルト: 1.0)
- `random_page_cost` (デフォルト: 4.0)
- `cpu_tuple_cost` (デフォルト: 0.01)
- `cpu_operator_cost` (デフォルト: 0.0025)
この `cpu_operator_cost` は、演算子や関数を1回実行するのにかかるコストを示しています。
問題は、「PostgreSQLは、あなたが書いた関数の重さを正確には知らない」という点です。例えば、単純な `a + b` と、数千行の外部テーブルを引くような複雑なストアドプロシージャ。これら両方が、デフォルトでは同じ「0.0025」というコストとして計算されてしまうんです。これじゃあ、プランナも迷いますよね。
—
どんな時に調整すべきか?
正直に言います。`cpu_operator_cost` を安易にいじり回すのは、あまりおすすめしません。これはデータベース全体、あるいはセッション全体の設定なので、副作用が大きすぎるからです。
ただ、以下のようなケースでは検討の価値があります。
- 「計算量が極端に多いクエリ」がボトルネックになっている場合
- インデックスを使えば速いのに、プランナが「計算コストが安い」と勘違いして全件走査(Seq Scan)を選択し続ける場合
例えば、位置情報系の計算や、巨大なJSONBのパースをWHERE句で行うようなクエリですね。
—
実践:どうやって調整するか
全体設定を変える前に、まずは対象のセッションだけで試すのが鉄則です。
— まずは現状のプランを確認
EXPLAIN ANALYZE SELECT FROM heavy_table WHERE ST_Distance(geom, ‘…’) < 100;
-- 試しにコストを上げてみる(デフォルトの10倍~100倍くらいに振ることが多いです)
SET cpu_operator_cost = 0.025;
-- 再度プランを確認
EXPLAIN ANALYZE SELECT FROM heavy_table WHERE ST_Distance(geom, '...') < 100;
このように、計算コストを意図的に高く設定することで、「この演算子は重いから、なるべく実行回数を減らそう(=インデックスを使って絞り込もう)」とプランナに認識させることができます。
---
注意:これは「対症療法」だということを忘れないで
ここが一番伝えたいことですが、`cpu_operator_cost` の調整は、あくまで「プランナへのヒント出し」に過ぎません。
もし可能なら、まずは以下を優先してください。
1. インデックスの工夫: `CREATE INDEX … ON table ((ST_Distance(geom, …)))` のように、計算結果そのものをインデックス化する(関数インデックス)。これが一番確実です。
2. クエリの書き換え: WHERE句で計算を行わず、計算済みのカラムを持つようにテーブルをリファクタリングする。
3. 統計情報の更新: `ANALYZE` が古くて行数が正しく見積もれていないだけ、というケースが実は8割です。
—
最後に
データベースチューニングにおいて、魔法の杖はありません。「コスト係数をいじれば速くなる」というショートカットに頼りすぎると、後で別のクエリで「なぜかインデックスが効かなくなった」という地獄を見ることになります。
`cpu_operator_cost` を触るのは、「どうしてもプランナが納得してくれない時の最後の一手」。そう割り切って使うのが、現場で生き残るエンジニアの作法かなと思います。
明日からのチューニング作業、少しでもこの知識が役に立てば嬉しいです。何か詰まったら、またいつでも聞いてください。一緒にプランナの心の中を覗いてやりましょう。
コメント