「なぜかプランナが罠にハマる…」そんな時は PostgreSQL の「相関統計情報」を疑え!
やあ。PostgreSQLのパフォーマンスチューニングで頭を抱えている君、お疲れ様。
クエリが遅い原因の8割は「実行計画(EXPLAIN)のミス」だよね。特に、複数の条件を組み合わせた時に、PostgreSQLが「おいおい、そんなにデータ戻ってくるわけないだろ!」っていう予測をして、インデックスを使わずにフルスキャンを選択してしまう……あの絶望的な瞬間。
あれ、実は「カラム間の相関」をPostgreSQLが読み取れていないだけのことが多いんだ。今日は、そんな時に魔法のように効く「拡張統計情報(Extended Statistics)」の話をしよう。
—
なぜ PostgreSQL は「嘘」をつくのか?
まず、基本のおさらいだ。PostgreSQLのプランナは、テーブルの統計情報を使って「この条件なら何行ヒットするか」を計算する。
例えば、こんなテーブルがあるとする。
- `prefecture_code`(都道府県コード)
- `city_name`(市区町村名)
ここで君がこんなクエリを投げたとしよう。
SELECT FROM addresses
WHERE prefecture_code = ’13’ AND city_name = ‘世田谷区’;
PostgreSQLの標準的な統計情報は、各カラムを「独立したもの」として扱う。つまり、「`prefecture_code = 13` である確率」と「`city_name = 世田谷区` である確率」をそれぞれ計算して、単純に掛け算してしまうんだ。
でも現実には、`city_name` が『世田谷区』なら、ほぼ確実に `prefecture_code` は『13(東京都)』だよね。この相関関係をプランナは知らないから、実際には数千件しかない結果を「数百万件あるはずだ!」と見積もりミスをして、わざわざ重いシーケンシャルスキャンを選んでしまうわけ。
—
「拡張統計情報」という切り札
そんな時こそ、PostgreSQL 10以降から強化された「拡張統計情報」の出番だ。これを使うと、カラム間の相関関係を明示的に学習させることができる。
使い方は驚くほど簡単。`CREATE STATISTICS` コマンドを打つだけだ。
CREATE STATISTICS stat_pref_city
ON prefecture_code, city_name
FROM addresses;
— 統計情報を更新(ANALYZE必須!)
ANALYZE addresses;
これだけで、PostgreSQLは「この2つのカラムの間には強い相関があるぞ」と認識してくれるようになる。次に `EXPLAIN` を叩いてみてほしい。見積もり行数(rows)が、実際の行数にグッと近づいているはずだ。
—
どんな時に使うべきか?(現場の勘所)
ただ、何でもかんでも統計を作ればいいというわけじゃない。統計情報を増やすと、その分 `ANALYZE` の負荷も上がるし、カタログも肥大化する。僕が現場で「ここは統計を作っておくべき」と判断するのはこんなケースだ。
1. WHERE句で「あるカラムAが決まればカラムBも決まる」関係が頻出する場合
- 都道府県と市区町村、郵便番号と住所、カテゴリIDとサブカテゴリIDなど。
2. 実行計画が不安定で、たまに異常に遅いクエリがある場合
- 特に、結合(JOIN)の順序が日によって変わったりするようなケース。
3. データ量が多い大規模テーブル
- 見積もりが10倍外れるだけで、Nested Loopを避けてハッシュ結合を選んだり、逆にその逆をやったりと、クエリの実行効率が劇的に変わるからね。
—
注意点:魔法じゃない、あくまで「支援」
一つだけ忠告しておこう。拡張統計情報は、あくまで「プランナに正しいヒントを与える」ためのものだ。
もし、カラム間の相関を正してもまだ遅いなら、それはインデックスの設計自体が間違っているか、クエリの書き方が悪い可能性が高い。 統計情報に逃げる前に、まずは `EXPLAIN (ANALYZE, BUFFERS)` を見て、どこで本当に時間がかかっているかを見極める癖をつけてほしい。
「統計情報で解決できるはず」と決めつけて深追いしすぎると、かえって落とし穴にハマる。DBエンジニアとして、常に「事実」と「見積もり」を切り分けて考えるのが、一流への近道だよ。
—
まとめ:今日からできること
1. 今のクエリの実行計画で、`rows` と `actual rows` に大きな乖離がないか確認する。
2. 乖離があるカラム同士が、論理的に相関していないか考える。
3. `CREATE STATISTICS` を試し、`ANALYZE` して実行計画の変化を確認する。
もし「やってみたけど変わらないぞ?」ということがあれば、いつでも相談してくれ。データベースの世界は奥が深い。その分、少しの知識で劇的に速くなる瞬間が最高に面白いんだ。
じゃあ、また現場で会おう。健闘を祈る!
コメント