発展関連トピック

統計情報とオプティマイザ

定義

統計情報とは、テーブルやカラムの行数・値の分布・NULL率などをオプティマイザが参照する要約データであり、これが古いと実行計画が最適でなくなる。

インデックスを使うかどうかは統計情報が決める

DBの中では「クエリオプティマイザ」がSQLを見て、複数の実行計画候補の中からコスト最小のものを選びます。 このコスト見積りは統計情報(各カラムの値の分布、行数、NULL率など)に基づきます。

統計情報がオプティマイザの判断を決める
検索する status:
オプティマイザが持っている分布
= 古い分布。実際とはずれている
pending33% · 330K 行
shipped33% · 330K 行
cancelled34% · 340K 行
なぜ古くなる?

大量INSERT/DELETE 直後や、データ分布が変化した直後は、DBが把握している分布と実際がずれる。 統計情報を更新するコマンドで最新化する必要がある。

オプティマイザの見積り
WHERE status = 'shipped'
推定該当行数
330,000/ 1,000,000
閾値 20% (=200,000行) との比較で選択
選ばれたアクセス方法
Seq Scan

「対象が多い」と見積もったので全表を順に読む方が速いと判断。

オプティマイザは「対象行の割合が閾値(ここでは20%)以下ならインデックス、それより多ければフルスキャン」と判断する。 統計情報が古いと 誤った 割合で判断し、最適でないプランを選ぶ。

インデックスを使わない判断もある

テーブルの多くの行が該当するクエリでは、インデックス経由でランダムアクセスを繰り返すよりもフルスキャンの方が速い。 オプティマイザはこれを見積りコストで判断します。「インデックスを貼ったのに使われない」の原因のほとんどは、この見積りで「使わない方が速い」と判断されているか、統計情報が古くて誤った判断が下されているかのどちらかです。

統計情報が古いとどうなるか

  • 大量INSERT直後: 実際にはインデックスが効かない量なのにインデックスを選んでしまう
  • 大量DELETE直後: インデックスが有効なのに、統計上「多くの行が該当する」と誤認して使わない
  • データ分布の変化: 元は偏っていたstatusが均等になったのに古い分布で判断してしまう

こうした場合は、統計情報を更新するコマンドを実行して最新の分布に合わせます(コマンド名はRDBMSごとに異なる)。

MySQL の統計情報

MySQL の InnoDB は、統計情報を mysql.innodb_table_statsmysql.innodb_index_stats の 2 テーブルに永続化する。行数見積り、 インデックスごとのカーディナリティ、リーフページ数などが並ぶ。

更新のトリガーは 2 つ。

  • 自動: innodb_stats_auto_recalc が ON (デフォルト) の場合、 テーブルの行数が約 10% 変化したタイミングでバックグラウンドスレッドが再計算する。
  • 手動: ANALYZE TABLE table_name; を実行すると即時に統計を採り直す。 バルクロード直後・大量削除直後・想定と実行計画がズレたときはこれを打つ。

サンプリング精度は innodb_stats_persistent_sample_pages (デフォルト 20 ページ) で調整可能。 巨大テーブルで見積り誤差が大きいときは増やす。 なお MySQL 8.0 からは ヒストグラム ( ANALYZE TABLE ... UPDATE HISTOGRAM ON col;) が使えるようになり、値の偏ったカラム (例: status に 90% が同じ値) の見積り精度が上がる。

PostgreSQL の統計情報

PostgreSQL の統計情報はシステムカタログ pg_statistic に格納される。 直接読むのは面倒なので、通常は pg_stats ビュー越しに参照する (行数・NULL 率・最頻値 most_common_vals・ヒストグラム境界 histogram_boundsなどが人間可読な形で並ぶ)。

更新のトリガーは 2 つ。

  • 自動: autovacuum ワーカーが VACUUM とセットで ANALYZE も回す。autovacuum_analyze_scale_factor (デフォルト 0.1) とautovacuum_analyze_threshold (デフォルト 50) で発火条件が決まる。
  • 手動: ANALYZE table_name; または VACUUM ANALYZE table_name;。 後者は VACUUM も同時に実行する。バルクロード後は必ず手で打つのが安全。

サンプリング粒度は default_statistics_target (デフォルト 100) で決まり、 列単位に ALTER TABLE ... ALTER COLUMN col SET STATISTICS 1000; で上書きできる。 偏りが大きいカラムはターゲット値を上げると most_common_vals の候補数と ヒストグラム境界数が増え、見積り精度が改善する。

EXPLAIN ANALYZE で「見積り行数」と「実際の行数」が大きくズレていたら、 まず ANALYZE を疑うのが定石。

よくある疑問

Q.統計情報はいつ更新される?
A.多くのRDBMSは自動更新の仕組みを持っていますが、大量のバルクロードやデータ分布が急変した直後は手動で統計情報の更新コマンドを実行した方が安全です。
Q.カーディナリティとは?
A.そのカラムに含まれる異なる値の数のこと。カーディナリティが高いほどインデックスが効きやすく、低い(例: is_deleted のような真偽値)と部分インデックスの方が有効なことが多い。
Q.ヒストグラムは何のため?
A.値の分布を段階的に表現したもの。データが偏っている場合(例: 特定のstatusに9割集中)、単純な平均だけでは判断できないため、ヒストグラムを見て「どの値なら少ないか」を推定します。
Q.MySQL の統計情報はどこに保存されている?
A.InnoDB では mysql.innodb_table_stats / mysql.innodb_index_stats に永続化されています。ANALYZE TABLE を実行するか、テーブルの一定割合が変更されると自動更新されます (innodb_stats_auto_recalc)。
Q.PostgreSQL の統計情報はどこに保存されている?
A.pg_statistic (システムカタログ) に保存され、pg_stats ビュー経由で参照できます。ANALYZE か autovacuum の一部として自動更新されます。

関連トピック

もっと学びたい方へ(おすすめ書籍)

[改訂3版]内部構造から学ぶPostgreSQL
勝俣智成 ほか

PostgreSQLの内部構造・ストレージ・インデックス機構を丁寧に解説。設計と運用計画の鉄則が学べる。

Amazon で見る →
情報処理教科書 データベーススペシャリスト 2025年版
三好康之

IPAデータベーススペシャリスト試験の総合対策書。インデックス関連は本サイトと合わせて学ぶと理解が深まる。

Amazon で見る →
SQL実践入門 ── 高速でわかりやすいクエリの書き方
ミック

「なぜこの書き方が速いのか」を実行計画から説明する一冊。条件分岐・集約・結合・更新のそれぞれで、良い書き方と悪い書き方を対比しながら読める。

Amazon で見る →
おすすめ
達人に学ぶDB設計徹底指南書 第2版
ミック

テーブル設計と正規化、パフォーマンス考慮のインデックス設計まで実務レベルで学べる定番書。第2版ではクラウド対応も強化。

Amazon で見る →
おすすめ
楽々ERDレッスン (CodeZine BOOKS)
羽生章洋

ER 図をどう「使える設計」に落とすか、実務の判断まで踏み込んだ入門書。エンティティの切り出しから多対多の扱いまで具体例が豊富。

Amazon で見る →
おすすめ
スッキリわかるSQL入門 第4版 ドリル256問付き!
中山清喬/飯田理恵子

ドリル 256 問を実際に打ちながら進める SQL の入門書。付属のブラウザ環境で演習できるので、SELECT から結合・集約までを環境構築で止まらずに通せる。

Amazon で見る →
達人に学ぶSQL徹底指南書 第2版
ミック

SQLの本質的な使い方と、インデックスが効くクエリの書き方を学べる。ウィンドウ関数など現代SQLも網羅。

Amazon で見る →
SQLアンチパターン 第2版
Bill Karwin

実務でやりがちなSQL・DB設計のアンチパターンとその回避策を体系的に学べる。

Amazon で見る →
理論から学ぶデータベース実践入門
奥野幹也

リレーショナルモデルの理論から、インデックス設計を含む実務で使えるSQLまで解説。

Amazon で見る →

本セクションはAmazonアソシエイトのリンクを含みます。

オンライン個別指導

もっと深くDBを学びたい方へ。

たいてっくが、SQL・データベース設計・パフォーマンスチューニング・IPAデータベーススペシャリスト対策まで、1対1で学習をサポートします。まずは無料相談から。

無料相談を予約する →
受講者の声 (DB・SQL コース)
menta レビュー原文を見る →
  • 教え方も上手で、お人柄も良いメンターです。DB周りの知識はもちろん、何より、しっかり教えてあげようという姿勢がとてもありがたかったです。データベース、SQLの学習を考えている方にはおススメです。
    H 様DB・SQL コース受講
  • 体系的に知識を教えてくださり、実際の業務でも大変役立っております。特に短い時間で効率よく知識の習得や、練習をできているのは期待以上でした。
    M 様DB・SQL コース受講
  • 大変充実したコンテンツでわかりやすいご説明をありがとうございました。基本的な質問にも丁寧にご説明いただき、また業務のご相談にも乗って頂き大変有意義な時間でした。
    K 様DB・SQL コース受講