【実務・中級編】 統計情報の収集と管理 – PostgreSQL

「なぜかこのクエリだけ、急に遅くなったんだよね……」

現場でそんなぼやきを聞くと、たいてい犯人は決まっています。そう、「統計情報の鮮度」です。

PostgreSQLのオプティマイザは、非常に賢い数学者ですが、彼が判断を下すための「材料」が古かったらどうでしょう? どんなに優秀なプランナでも、間違ったデータをもとに計算すれば、最悪の実行計画をひねり出してしまいます。

今日は、PostgreSQLの胃袋とも言える「統計情報」と、それを管理する`ANALYZE`について、教科書には載っていない「現場の勘所」を深掘りしていきましょう。

—

1. なぜ「統計情報」がないとDBは迷子になるのか

PostgreSQLのプランナは、クエリを実行する前に「この検索条件だと、何行くらいデータが返ってくるかな?」と推測します(カーディナリティの推定といいます)。

ここで使われるのが、`pg_statistic`というシステムカタログです。ここには、各カラムのデータが「どんな分布をしているか」という要約が詰まっています。

  • 最頻値(MCV: Most Common Values): よく出現する値とその頻度。
  • ヒストグラム: データがどうバラついているかの境界線。
  • NULLの割合: データ全体の中でどれくらいスカスカか。

これらを元に、「このクエリならインデックスを使ったほうが速いな」「いや、全表スキャンの方がマシだな」と判断しているわけです。もしこの情報が実態とズレていたら……? インデックスがあるのにフルスキャンを選び、数百万件のデータをメモリに読み込んで爆死する、なんて悲劇が起きるわけです。

—

2. ANALYZEの裏側:実は「適当」にやっている?

「じゃあ、常に厳密に統計を取ればいいのでは?」と思うかもしれません。しかし、テーブルが数億行ある場合、全件スキャンして統計を取っていたらDBが止まってしまいます。

そこで`ANALYZE`は、サンプリングという手法を使います。

— ANALYZEは裏でautovacuumがやってくれますが、手動でやるならこれ
ANALYZE VERBOSE public.users;

重要なのは、`default_statistics_target`の設定です。デフォルトでは100になっていますが、これは「ヒストグラムを何個のバケット(区切り)で管理するか」という値です。

もし、特定カラムの値の偏りが激しく、プランナがどうしても見積もりを外すようなら、カラム単位で精度を上げてやるのが実務のテクニックです。

— 「このカラム、値の種類が多すぎてプランナが混乱してるな」と思ったら
ALTER TABLE users ALTER COLUMN email SET STATISTICS 500;
— これを設定した後に再度ANALYZEが必要
ANALYZE users(email);

こうすることで、そのカラムだけより詳細なヒストグラムを作るようになります。これだけで、クエリの実行計画が劇的に改善することは珍しくありません。

—

3. 実務でハマる「統計情報の罠」

現場でよくある失敗談をひとつ。

「バッチ処理で一気にデータを消して、一気にINSERTしたのに、なぜかその直後のクエリが遅い」

これ、`autovacuum`のタイミングと統計情報の更新が噛み合っていない時に起きるんです。`autovacuum`が起動する条件(`autovacuum_vacuum_scale_factor`など)に達するまで、統計情報は古いまま。その間、プランナは「テーブルにはまだデータがたっぷりある」と思い込んで、非効率な計画を選択し続けます。

もし、デプロイや大規模なデータ更新の直後に性能劣化を感じたら、迷わず手動で`ANALYZE`を叩いてください。

— 統計情報の鮮度を確認するコマンド
SELECT relname, last_analyze, last_autoanalyze
FROM pg_stat_user_tables
WHERE relname = ‘users’;

この`last_analyze`を見て、「あ、数日前に更新されてるな」と思ったら、それがクエリ遅延の正体かもしれません。

—

まとめ:統計情報は「DBの視力」

統計情報は、いわばデータベースの「目」です。目がかすんでいれば、プランナは足元が見えず、最短ルートを外して崖から落ちます。

  • 定期的に自動更新されているか?(autovacuumのログをチェック!)
  • 実行計画が不自然なら、まずは統計情報の鮮度を疑う。
  • データの偏りが激しいカラムは、個別に統計精度を調整する。

この3つを頭の片隅に置いておくだけで、トラブルシューティングのスピードが一段階上がりますよ。

データベースは、結局のところ「統計学」の上に成り立っています。この仕組みを理解しておけば、どんなに複雑なクエリにも冷静に対処できるはずです。それでは、また現場でお会いしましょう!

コメント

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