RUNSTATS は、表と索引の統計(行数、ページ数、列の値の偏りなど)を集めてシステムカタログに書き込む Db2 のコマンドです。オプティマイザーはこの統計を見て、索引を使うか、どの順で結合するかを決めます。統計が実際のデータとずれていると、遅いアクセスパスが選ばれます。この記事の出力は Db2 12.1.4 で採りました。
まず見る(結論)
- 基本形:
db2 "RUNSTATS ON TABLE スキーマ.表 WITH DISTRIBUTION AND INDEXES ALL" - 流れたかは
SYSCAT.TABLESのSTATS_TIMEで見る。CARDが-1なら一度も集めていない - 大きな表は
TABLESAMPLE BERNOULLI(10)で抜き取って集められる。行数は推定値になる - 大量の投入・削除や REORG の後に流す(REORG の記事)
コマンドの書き方
| やりたいこと | コマンド |
|---|---|
| 表と全索引(通常はこれ) | RUNSTATS ON TABLE スキーマ.表 WITH DISTRIBUTION AND INDEXES ALL |
| 表だけ | RUNSTATS ON TABLE スキーマ.表 |
| 行を10%抜き取る | ... AND INDEXES ALL TABLESAMPLE BERNOULLI(10) |
| ページを10%抜き取る | ... TABLESAMPLE SYSTEM(10) |
| SQL から実行する | CALL SYSPROC.ADMIN_CMD('RUNSTATS ON TABLE スキーマ.表 AND INDEXES ALL') |
WITH DISTRIBUTION を付けると、列ごとに「どの値が何行あるか」(頻度統計)と値の分布(分位統計)も集めます。区分コードのように特定の値に行が偏る列があるなら付けます。
統計が更新されたかを確かめる
5万行を入れた直後の表です。
SELECT TABNAME, CARD, NPAGES, FPAGES, OVERFLOW, STATS_TIME
FROM SYSCAT.TABLES WHERE TABNAME = 'FSV_REORG';
TABNAME CARD NPAGES FPAGES OVERFLOW STATS_TIME
------------ ------ -------- -------- -------- --------------------------
FSV_REORG -1 -1 -1 -1 - ← 実行前
FSV_REORG 50000 747 747 0 2026-10-24-16.30.05.625221 ← 実行後
索引は SYSCAT.INDEXES(NLEAF・NLEVELS・CLUSTERRATIO・STATS_TIME)、頻度統計は SYSCAT.COLDIST に入ります。区分列 KBN を5行に1行ずつ 'A'・'B'、残りを 'C' にした表では、WITH DISTRIBUTION を付けて流すと COLDIST にこう記録されました。
SELECT COLNAME, TYPE, SEQNO, COLVALUE, VALCOUNT
FROM SYSCAT.COLDIST
WHERE TABNAME = 'FSV_REORG' AND COLNAME = 'KBN' AND TYPE = 'F' AND VALCOUNT > 0;
COLNAME TYPE SEQNO COLVALUE VALCOUNT
-------- ---- ------ ---------- --------
KBN F 1 'C' 30000
KBN F 2 'A' 10000
KBN F 3 'B' 10000
SQL が遅くなったときに最初に見るのは STATS_TIME です。大量に行を入れた日より前の日時なら、統計は投入前のデータのままです。
サンプリングすると行数は推定値になる
同じ5万行の表に TABLESAMPLE BERNOULLI(10) と TABLESAMPLE SYSTEM(10) を続けて流したところ、CARD は 50049 になりました。件数を正確に知りたいときは SELECT COUNT(*) を使います。
BERNOULLI は全ページを読んで行単位で抜き取ります。SYSTEM はページ単位で抜き取るので読む量が少なく速い一方、データの並びに偏りがあると統計も偏ります。
エラーになる場合
| メッセージ | 原因 |
|---|---|
SQL2306N The table or index "DB2INST1.NO_SUCH_TABLE" does not exist. |
表名かスキーマの誤り。スキーマを省いて別ユーザーで接続している場合も出る |
SQL20288N ... Object type: "View". Reason code: "1". |
ビューを指定した。統計を集められるのは表(と統計ビュー) |
自動 RUNSTATS
DB CFG の AUTO_RUNSTATS が ON なら、Db2 が必要と判断した表に RUNSTATS を流します。
$ db2 get db cfg for sample | grep -i auto_
Automatic maintenance (AUTO_MAINT) = ON
Automatic table maintenance (AUTO_TBL_MAINT) = ON
Automatic runstats (AUTO_RUNSTATS) = ON
Real-time statistics (AUTO_STMT_STATS) = ON
Automatic reorganization (AUTO_REORG) = OFF
自動 RUNSTATS はいつ流れるかを選べません。大量投入の直後に流れるとは限らないので、バッチで大量に入れた後は手で流すほうが確実です。
RUNSTATS を流すタイミング(実機ログつきの詳解)
REORGCHK で実行要否を測る手順、自動 RUNSTATS が業務のピークに流れて実行計画が変わる問題、AUTO_REORG の性質は、Zenn のフル記事にまとめています。
関連: Db2のREORGとは
「とりあえず週次で全テーブルREORG」がなぜ問題を招くのか――“なぜ実行するのか”を自分で判断できるようになるための考え方を、本書 第10章「RUNSTATS・REORGを意図して制御する」で詳説しています。
現場で引ける Db2 の教科書
現場で引ける!Db2実践エンジニア・バイブル
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集。