【実務・中級編】 pg_stats_extビュー – PostgreSQL

なぜ「統計情報」でハマるのか? PostgreSQLの隠れた名機能『pg_stats_ext』を使いこなそう

現場でバリバリPostgreSQLを触っていると、一度は経験するよね。「このSQL、インデックスも張ってあるし条件も単純なのに、なんでこんなに遅いの?」っていう現象。

実行計画(EXPLAIN ANALYZE)を見てみると、案の定「見積もり件数(rows)」と「実際の結果件数」が桁違いにズレている。プランナが「これならフルスキャンの方が速いな」と判断して、インデックスを無視した結果、地獄を見るパターンだ。

実はこれ、「列間の相関」が原因のことがめちゃくちゃ多い。今日は、そんな泥沼から抜け出すための切り札、『pg_stats_ext』について話そうと思う。

—

「列の相関」という罠

例えば、ユーザーテーブルで「都道府県」と「市区町村」の列があるとする。
`WHERE 都道府県 = ‘東京都’ AND 市区町村 = ‘千代田区’` というクエリを投げたとき、PostgreSQLのプランナは普通、こう考えるんだ。

1. 東京都である確率:1/47
2. 千代田区である確率:1/2000
3. だから、両方満たす確率は `1/47 × 1/2000` だ!

……とね。でも、現実には「東京都」かつ「千代田区」というデータは存在するけど、「北海道」かつ「千代田区」なんてデータは存在しないよね。プランナはそれぞれの列を「独立している」と思い込んで計算するから、見積もりが盛大に狂うんだ。

ここで登場するのが拡張統計(Extended Statistics)だよ。

—

pg_stats_ext で何が見えるのか?

拡張統計を作成すると、PostgreSQLは単なる列ごとの統計じゃなくて、列の組み合わせについても「こいつら、実はセットで動いてるぞ」という情報を収集してくれるようになる。

で、その作成した統計情報が今どうなっているのか、正しく機能しているのかを確認するためのシステムビューが `pg_stats_ext` だ。

まずは現状を確認してみよう

以下のクエリを叩いてみてほしい。

SELECT
schemaname,
relname,
extname,
extkind, — どんな統計か(依存関係やリストなど)
extcols — どの列を対象にしているか
FROM pg_stats_ext;

ここで `extkind` に注目してほしい。

  • `d` (Dependencies): 列間の依存関係(さっきの都道府県・市区町村の例)
  • `m` (MCV: Most Common Values): よく出る値の組み合わせ(カテゴリの偏りが激しい場合など)

—

実践:統計情報を育てていく手順

ただビューを見るだけじゃなくて、実際にどう活用するか。手順はシンプルだ。

1. 統計を作る

もし「この組み合わせ、絶対相関してるよな」という列があれば、迷わず作成する。

CREATE STATISTICS stats_pref_city
(dependencies)
ON prefecture, city
FROM users;

2. 統計が有効か確認する

次に `pg_stats_ext_exprs` や `pg_stats_ext` を見て、ちゃんと統計が生成されているか確認する。特に、解析(ANALYZE)が走らないと統計は空っぽのままだから注意してね。

ANALYZE users;

— 統計の内容を覗いてみる
SELECT FROM pg_stats_ext_exprs
WHERE extname = ‘stats_pref_city’;

—

先輩からのアドバイス:使いどころの「勘所」

これ、便利だからといって全列に貼ればいいわけじゃない。統計情報を増やすと、その分 `ANALYZE` のコストも上がるし、管理コストも地味に効いてくる。

僕が現場でよく見る「導入のサイン」はこんな感じだ。

  • 見積もりの乖離が10倍以上ある:

`EXPLAIN ANALYZE` で `rows=10000` なのに `actual rows=10` みたいなやつ。これはもう確定で拡張統計の出番。

  • WHERE句の列が論理的に結びついている:

「カテゴリ」と「サブカテゴリ」、「状態」と「ステータス」など。

  • クエリの実行計画がコロコロ変わって不安定:

統計の精度のせいでプランナが迷っている証拠だ。

まとめ

PostgreSQLのプランナは非常に優秀だけど、データの世界を完璧に理解しているわけじゃない。僕らエンジニアが「このデータにはこういう関係性があるんだよ」とヒントを与えてあげることで、データベースは本来のポテンシャルを発揮してくれる。

`pg_stats_ext` を眺めることは、データベースの「思考のクセ」を理解することに他ならないんだ。

もし次に実行計画で首を傾げることがあったら、ぜひ `pg_stats_ext` を開いてみてくれ。きっとそこに、解決の糸口が隠れているはずだから。

それじゃ、また現場で!

コメント

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