タイトル: データブロック
SEOタイトル: Oracle データブロック 完全ガイド(最小I/O単位 / DB_BLOCK_SIZE / PCTFREE / PCTUSED / 内部構造)
| この記事の要点 |
|
データブロックとは
データブロック(Data Block)は、Oracle がディスクとメモリ間で読み書きする最小単位です。Oracle の論理構造の最下層に位置し、実際の行データはこのブロック内に格納されます。「Oracle ブロック」「論理ブロック」とも呼ばれます。
論理構造の中の位置づけ
| 階層 | 役割 |
|---|---|
| 表領域(Tablespace) | 1 つ以上のデータファイルからなる論理的な格納領域 |
| セグメント(Segment) | テーブル / インデックスなど 1 オブジェクトに割り当てられる領域 |
| エクステント(Extent) | 連続したデータブロックのまとまり |
| データブロック(Data Block) | 物理 I/O の最小単位 |
| 行(Row) | 1 件のレコード(複数行が 1 ブロックに収まることが多い) |
ブロックサイズの決め方
ブロックサイズは初期化パラメータ DB_BLOCK_SIZE で決まり、データベース作成後は変更できません。サポートされる値は 2KB / 4KB / 8KB(標準) / 16KB / 32KB(プラットフォーム依存)です。
-- 現在のブロックサイズ確認
SHOW PARAMETER DB_BLOCK_SIZE;
-- ビューでの確認
SELECT name, value
FROM v$parameter
WHERE name = 'db_block_size';
-- 表領域ごとのブロックサイズ
SELECT tablespace_name, block_size
FROM dba_tablespaces;
サイズの選び方
| サイズ | 向く用途 | 注意 |
|---|---|---|
| 2KB / 4KB | OLTP・小さい行が多い | I/O 回数が増えやすい |
| 8KB | 汎用(OLTP・DWH 混在) | 標準。迷ったらこれ |
| 16KB / 32KB | DWH・大量スキャン中心 | OLTP では無駄が出やすい |
データブロックの内部構造
| 領域 | 内容 |
|---|---|
| ブロックヘッダ | ブロック種別 / アドレス / トランザクションスロット(ITL)など |
| 表ディレクトリ | このブロックに含まれる表の情報 |
| 行ディレクトリ | 各行の位置オフセット |
| 行データ | 実際の行(複数) |
| フリースペース | 未使用領域。更新による拡張・新規行に使う |
行ディレクトリと行データはブロックの両端から中央に向かって伸びる構造で、中央のフリースペースが消費されていきます。
PCTFREE と PCTUSED
ブロック内のフリースペース管理パラメータです。PCTFREE は更新時の拡張用に空けておく割合、PCTUSED は再利用可能と判定する使用率の閾値です。
-- 表作成時に指定
CREATE TABLE orders (
order_id NUMBER,
detail VARCHAR2(2000)
)
PCTFREE 20 -- 20% を更新用に確保
PCTUSED 40; -- 使用率が 40% を切ったら再利用可
-- 既存表の確認
SELECT table_name, pct_free, pct_used
FROM user_tables;
| 状況 | PCTFREE | PCTUSED |
|---|---|---|
| INSERT 中心(更新ほぼ無し) | 低(5〜10) | 高(80〜90) |
| UPDATE 多発(列が伸びる) | 高(20〜30) | 低(40〜50) |
注: ASSM(自動セグメント領域管理)を使う表領域では PCTUSED は無視されます。9i 以降は ASSM が既定で、PCTFREE のみ意識すれば良くなりました。
行移行(Row Migration)と行連鎖(Row Chaining)
| 現象 | 原因 | 対策 |
|---|---|---|
| 行移行 | UPDATE で行が伸び、同じブロックに収まらず別ブロックへ移動 | PCTFREE を増やす / 再構成 |
| 行連鎖 | 1 行が 1 ブロックに収まらない(巨大 VARCHAR2 / LOB) | ブロックサイズを大きくする / 列を分割 |
どちらも 1 行を読むのに複数ブロックを参照する必要があり、性能劣化の原因になります。ANALYZE TABLE ... LIST CHAINED ROWS; や CHAIN_CNT 列で検出できます。
データブロックとバッファキャッシュ
サーバプロセスがディスクから読み込んだデータブロックは、SGA のバッファキャッシュにロードされ、以降は他のセッションも共有して使えます。書き込みはDBWn プロセスが非同期にディスクへ書き出します。
- キャッシュヒット率は
v$sysstatのsession logical reads/physical readsから算出 db_block_buffersは廃止、現在はdb_cache_sizeやmemory_target- 同じデータブロックが何度も参照されると、論理読み込みは増えるが物理 I/O は発生しない
ブロックダンプで内部を覗く
個別のブロック内容は ALTER SYSTEM DUMP DATAFILE ... BLOCK ... でトレースファイルに出力できます。学習用に試す場合は本番では実施しないこと(I/O 負荷とトレース量が大きい)。
-- file# と block# を ROWID から取得
SELECT DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) AS file#,
DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) AS block#,
DBMS_ROWID.ROWID_ROW_NUMBER(rowid) AS row#,
rowid
FROM employees
WHERE rownum <= 5;
-- 指定ブロックをトレースに出力(DBA 権限)
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 123;
SecureFiles LOB と CLOB のブロック格納
巨大データ(CLOB / BLOB)は通常のデータブロックには直接入らず、LOB セグメントに格納され、本体ブロックにはLOB ロケータのみ置かれます。インラインに収まる小さい LOB(4000 バイト未満で ENABLE STORAGE IN ROW 指定時)は行と同じブロックに納まります。
非標準ブロックサイズの併用
1 つの DB で複数のブロックサイズを共存させることもできます。標準サイズの表領域に加えて、特定の表領域だけ別サイズ(例: アーカイブ用 32KB)を使うケースです。専用バッファキャッシュ db_nk_cache_size の設定が必要です。