Db2 Buffer Pool の内部構造を徹底解説:Page Stealing アルゴリズム、Prefetch、Page Cleaner まで

はじめに

この記事では、IBM Db2のBuffer Poolの内部構造を解説します。

InnoDB編PostgreSQL編Oracle編SQL Server編に続く第5弾・最終回です。5つの主要RDBMSのBuffer管理を比較するシリーズの締めくくりとして、Db2ならではの特徴を中心に解説します。

Db2はLUW(Linux/UNIX/Windows)版とz/OS版で実装が異なりますが、この記事ではLUW版を中心に、z/OS版の特徴にも触れます。

Db2 Buffer Poolの基本

Db2のBuffer Poolは他のDBMSと同じく、ディスク上のデータページをメモリにキャッシュする仕組みです。

-- デフォルトBuffer Pool
-- データベース作成時に IBMDEFAULTBP が自動作成される

-- Buffer Poolの作成
CREATE BUFFERPOOL my_bp
    SIZE 50000        -- ページ数
    PAGESIZE 8K;      -- 4K, 8K, 16K, 32K から選択

-- Buffer Poolの変更(オンラインで即時反映)
ALTER BUFFERPOOL my_bp SIZE 100000;

-- Buffer Poolの情報確認
SELECT * FROM SYSCAT.BUFFERPOOLS;

Db2固有の特徴:ページサイズとBuffer Poolの紐づけ

Db2ではテーブルスペースとBuffer Poolのページサイズが一致している必要があります。4K、8K、16K、32Kの4種類があり、ページサイズごとにBuffer Poolを用意します:

名前 ページサイズ 用途
IBMDEFAULTBP 4K デフォルト
IBMSYSTEMBP4K 4K システム用
IBMSYSTEMBP8K 8K システム用
IBMSYSTEMBP16K 16K システム用
IBMSYSTEMBP32K 32K システム用
MY_BP_8K 8K ユーザー定義
MY_BP_32K 32K ユーザー定義

テーブルスペース(8K) → MY_BP_8K にのみ割り当て可能 テーブルスペース(32K)→ MY_BP_32K にのみ割り当て可能

これはOracleのKeep/Recycle Poolに似ていますが、Db2の方がより柔軟です。ワークロードの特性に応じて、テーブルごとに最適なBuffer Poolを割り当てられます。

Page Stealing アルゴリズム:3つの選択肢

Db2の最大の特徴は、ページ置換アルゴリズムを選択できることです。他のDBMSでは置換アルゴリズムは固定ですが、Db2(特にz/OS版)では3つから選べます:

PGSTEAL(LRU):デフォルト

ALTER BUFFERPOOL my_bp PGSTEAL LRU;

最も一般的な選択肢です。最近使われていないページから優先的に追い出します。InnoDBのLRU Listに近い動作です。

ただし、LRUチェインの維持コストとラッチ競合が発生します。

PGSTEAL(FIFO):先入れ先出し

ALTER BUFFERPOOL my_bp PGSTEAL FIFO;

最も古くBuffer Poolに入ったページから追い出します。アクセス頻度は考慮しません。

LRUチェインの維持が不要なため、ラッチ競合が少なくなります。Buffer Poolが十分に大きく、ほぼすべてのデータがメモリに載る場合に有効です。

PGSTEAL(NONE):追い出しなし

ALTER BUFFERPOOL my_bp PGSTEAL NONE;

オブジェクトがオープンされると全ページをBuffer Poolにプリロードし、可能な限りメモリに常駐させます。サイズが安定していて頻繁にアクセスされるテーブル向けです。

OracleのKeep Poolに近い概念ですが、Db2の方がより積極的(プリロードまでする)です。

5つのDBMSの置換アルゴリズム比較

DBMS アルゴリズム 選択可能? スキャン耐性
InnoDB LRU(New/Old Sublist) Old Sublist分割
PostgreSQL Clock Sweep Ring Buffer
Oracle LRU + Touch Count Direct Path Read
SQL Server Clock(参照ビット) 参照ビットリセット
Db2 LRU / FIFO / NONE アルゴリズム選択 + Prefetch

Prefetch(先読み)とPage Cleaner

Prefetch:I/Oの先読み

Db2のPrefetchは、InnoDBのRead-Aheadに相当します。テーブルスキャンやインデックススキャン時に、次に必要になるページを先回りして読み込みます:

-- Prefetch関連の設定
-- テーブルスペースレベルで設定
CREATE TABLESPACE my_ts
    PAGESIZE 8K
    PREFETCHSIZE 32    -- 一度に先読みするページ数
    BUFFERPOOL my_bp;

-- Prefetchの統計確認
SELECT
    bp_name,
    pool_data_p_reads,      -- 物理読み取り
    pool_async_data_reads,  -- 非同期(Prefetch)読み取り
    pool_data_l_reads       -- 論理読み取り(Buffer Poolヒット)
FROM SYSIBMADM.BP_READ_IO;

pool_async_data_reads / pool_data_p_readsの比率が高いほど、Prefetchが効果的に機能しています。

Page Cleaner:ダーティページの書き出し

Db2のPage Cleanerは、InnoDBのpage cleaner、PostgreSQLのBGWriter、OracleのDBWnに相当します:

-- Page Cleanerの数を設定
-- データベース構成パラメータ
db2 UPDATE DB CFG FOR mydb USING NUM_IOCLEANERS 4;

Page Cleanerは以下のタイミングで起動します:

  1. ダーティページ率が閾値(chngpgs_thresh)を超えた
    • デフォルト60%
  2. LSN Gap が大きくなりすぎた
    • ログの再利用のためにチェックポイントを進める必要
    • InnoDBのアクティブRedo量による圧力と同じ概念
  3. Freeページが不足した
-- Page Cleanerの活動を監視
SELECT
    bp_name,
    pool_async_data_writes,   -- Page Cleanerによる非同期書き出し
    pool_data_writes,         -- 全書き出し
    pool_drty_pg_steal_clns   -- ダーティページの追い出し(同期書き出し)
FROM SYSIBMADM.BP_WRITE_IO;

pool_drty_pg_steal_clnsが高い場合、Page Cleanerが間に合っていないサインです。NUM_IOCLEANERSの増加やchngpgs_threshの引き下げを検討します。

Buffer Poolの監視

スナップショットによる監視

-- Buffer Poolのヒット率
SELECT
    bp_name,
    pool_data_l_reads AS logical_reads,
    pool_data_p_reads AS physical_reads,
    CASE WHEN pool_data_l_reads > 0
         THEN DECIMAL((1.0 - FLOAT(pool_data_p_reads) / pool_data_l_reads) * 100, 5, 2)
         ELSE 0
    END AS hit_ratio_pct
FROM SYSIBMADM.SNAPBP;

MON_GET_BUFFERPOOL テーブル関数

-- より詳細なBuffer Pool統計(Db2 10.5+)
SELECT
    bp_name,
    pool_data_lbp_pages_found,   -- ローカルBuffer Poolでのヒット
    pool_data_gbp_p_reads,       -- グループBuffer Poolからの読み取り(pureScale)
    pool_async_data_reads,
    pool_async_data_writes
FROM TABLE(MON_GET_BUFFERPOOL(NULL, -2)) AS t;

まとめ:5つのDBMSの総比較

シリーズ全体の締めくくりとして、5つのDBMSのBuffer管理を一覧で比較します。

テーマ InnoDB PostgreSQL Oracle SQL Server Db2
置換アルゴリズム LRU(New/Old) Clock Sweep LRU + Touch Count Clock LRU/FIFO/NONE選択可
スキャン耐性 Old Sublist Ring Buffer Direct Path Read 参照ビット アルゴリズム選択
ダーティ管理 Flush List なし Checkpoint Queue なし(走査) LSN Gap監視
書き出しプロセス page cleaner BGWriter + Checkpointer DBWn + CKPT Lazy Writer + Checkpoint Page Cleaner
プール分割 インスタンス分割 単一 Default/Keep/Recycle 単一 ページサイズ別
ソースコード ✅ 公開 ✅ 公開 ❌ 非公開 ❌ 非公開 ❌ 非公開
可観測性 SHOW STATUS pg_buffercache XBH, VLATCH DMV スナップショット, MON_GET

5つのDBMSを通して見えてくるのは、Buffer管理という同じ問題に対して、各DBMSが独自の解を持っていることです。しかし根底にある設計目標は共通しています:ディスクI/Oを最小化し、同時実行性能を維持すること

このシリーズが、データベースの内部構造を理解する一助になれば幸いです。

参考

コメントする