🧹

Db2の「とりあえず週次で全REORG」をやめる ― REORGCHKでいつやるかを判断する

に公開

「毎週日曜の深夜、全テーブルに REORGRUNSTATS を流している」——Db2の現場でよく見る運用です。定期的にやっておけば安心と考えがちですが、この「とりあえず全部・定期的に」という方針が、かえって性能問題を引き起こすことがあります。

この記事では、REORGRUNSTATS が何をしているのかを整理したうえで、「いつ・どのテーブルに実行すべきか」を自分で判断できるようになることを目標にします。判断の中心になるのが REORGCHK です。

そもそもREORGは何を直しているのか

テーブルは INSERTUPDATEDELETE を繰り返すと物理的に断片化します。断片化は主に3種類です。

種類 何が起きるか 影響
オーバーフロー行 VARCHAR の更新で行が元ページに収まらず別ページへ移動、元位置にポインタだけ残る 1行の読み取りに2回のI/O
ページの低密度化 DELETE 多発でページ内に空きが増える 同じ件数を読むのに多くのページI/O
空ページの滞留 DELETE で空になったページが残り続ける スキャンで空ページを読み飛ばすコスト

REORG はデータを物理的に再配置して、これらを解消します。断片化していないテーブルをREORGしても得るものはなく、後述のロックや実行時間といったコストだけが残ります。

REORGCHK:やるべきかを「測ってから」決める

断片化しているかは REORGCHK で測れます。

# 全テーブルを現在の統計で診断(統計は更新しない)
db2 "REORGCHK CURRENT STATISTICS ON TABLE ALL"

# 特定テーブルを診断(同時にRUNSTATSも実行)
db2 "REORGCHK UPDATE STATISTICS ON TABLE <スキーマ>.<テーブル>"

実機で流すと、こういうヘッダと表が出ます。

F1: 100 * OVERFLOW / CARD < 5
F2: 100 * (data page の有効スペース使用率) > 70
F3: 100 * (必須ページ数 / 合計ページ数) > 80

SCHEMA.NAME     CARD    OV    NP    FP  ...  F1  F2  F3  REORG

見るのは右端の REORGです。F1/F2/F3 それぞれの閾値を外れると、その位置に * が立ちます。

REORG列 意味
--- 3条件とも問題なし → REORG不要
*-- F1(オーバーフロー行)が閾値超過
-*- F2(スペース効率)が閾値超過
*** 全条件で要REORG

落とし穴1:自動RUNSTATSが業務ピークに走って計画が変わる

自動RUNSTATSは「統計が古い」とDb2が判断したタイミングで走ります。それが業務時間中でも、です。現在の設定を確認します。

db2 "GET DB CFG FOR <DB名>" | grep -iE "AUTO_RUNSTATS|AUTO_REORG|AUTO_STMT_STATS"

実機の既定はこうなっていました。

 自動 RUNSTATS          (AUTO_RUNSTATS) = ON
 リアルタイム統計    (AUTO_STMT_STATS) = ON
 自動再編成               (AUTO_REORG) = OFF

デフォルトで自動RUNSTATSはONです。何もしなければ、Db2が勝手なタイミングで統計を更新し、計画が変わり得る状態です。手動管理に切り替えるなら次のようにします。

db2 "UPDATE DB CFG FOR <DB名> USING AUTO_RUNSTATS OFF"

手動に切り替えたら、テーブルの性質でタイミングを決めます。

テーブル種別 RUNSTATSのタイミング
日次バッチで大量 INSERT/DELETE バッチ完了直後
参照系メイン・更新少 週次または月次
安定したマスター データ変更時のみ

自動RUNSTATSを手動に切り替える判断基準と、実行計画が変わった事例は本の第10章で扱っています。

落とし穴2:REORG直後のバッチがかえって遅い

REORGは正しく効いているのに、直後の初回スキャンだけは「整ったばかりで温まっていない」状態になります。だからREORGはバッチの直前ではなく、直後か業務の合間に置きます。

推奨スケジュール例(夜間)

22:00 夜間バッチ開始
02:00 夜間バッチ完了
02:15 REORG 実行(先に物理を整える)
04:30 RUNSTATS 実行(整った状態をカタログへ反映)
05:00 REBIND / パッケージキャッシュのフラッシュ
06:00 早朝バッチ開始

順番が大事です。REORG → RUNSTATS → 再バインド の順にすることで、「整った物理」と「最新の統計」と「その統計を使う新しい計画」が揃います。

この順番で流しても遅いままなら、原因は統計の鮮度ではありません。パターン別の切り分けは別記事にまとめています。

https://zenn.dev/firese/articles/db2-sql-slow-statistics

インプレース vs オフライン

REORGには2モードあります。メンテナンス枠の有無で選びます。

モード 特徴 向くケース
オフライン(既定) 実行中はテーブルロック。短時間で完了 深夜メンテ枠がある
インプレース 業務中に実行可。完了まで時間がかかる 24時間稼働で枠がない
# オフライン(テーブルロックあり)
db2 "REORG TABLE <スキーマ>.<テーブル>"

# インプレース(オンライン実行、非同期)
db2 "REORG TABLE <スキーマ>.<テーブル> INPLACE START"

# インプレースの進捗確認
db2pd -db <DB> -reorg

# インプレースの停止
db2 "REORG TABLE <スキーマ>.<テーブル> INPLACE STOP"

# テーブルREORGの後は索引の再編成も
db2 "REORG INDEXES ALL FOR TABLE <スキーマ>.<テーブル>"

AUTO_REORGを使うなら性質を理解して

Db2には REORGCHK の結果に基づく自動REORG(AUTO_REORG)もあります。

db2 "GET DB CFG FOR <DB名>" | grep -i auto_reorg
db2 "UPDATE DB CFG FOR <DB名> USING AUTO_REORG ON"

ただし AUTO_REORG はインプレースREORGとして実行されます。前述のとおりインプレースは時間がかかるため、大きなテーブルを多数抱えるシステムでは自動REORGが長時間走り続けることがあります。業務特性を見て、自動か手動かを選んでください。

REORGには容量の副作用もあります。USE 句を付けないREORGは同じ表スペース内にコピーを作るため、表は縮んでも表スペースの割り当ては増えます。空きを取り戻す目的で流すなら USE は必須です。

https://zenn.dev/firese/articles/db2-tablespace-reclaim-hwm

まとめ

項目 着眼点
REORGCHK --- はREORG不要。F3だけの * は改善限定的。測ってから決める
自動RUNSTATS 既定でON。実行タイミングを制御できず計画変更リスク
REORGの順番 REORG → RUNSTATS → 再バインド。バッチ直前は避ける
インプレース 業務中可だが長時間・非同期。完了まで見届ける
索引REORG テーブルREORG後に忘れず実行

📕 もっと深く:Db2運用を12章で体系化した本を書きました

この記事で扱ったRUNSTATS・REORGの制御は、Db2運用の一領域にすぎません。

Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ——そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にしました。実機で検証した内容と、Db2の設計上そうなる理由をまとめました。

アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG(本記事の深掘り版)/MON_GET監視/現場の難題集まで、全12章+運用シェルスクリプト集です。

https://zenn.dev/firese/books/db2-practical-bible

現場で「これはハマった」というREORG/統計まわりのネタがあれば、コメントで教えてください。

Discussion