2.

Oracle データベース論理構造完全ガイド (Tablespace/Segment/Extent/Block)

編集
この記事の要点
  • Oracle 論理構造は Tablespace → Segment → Extent → Block の 4 階層
  • Data Block はディスク I/O の最小単位(デフォルト 8KBDB_BLOCK_SIZE で決定)
  • Extent は連続した複数 Block、Segment は 1 オブジェクト(Table/Index 等)が使う全 Extent の集合
  • Tablespace 管理方式は Local Managed (LMT) が標準、Dictionary Managed (DMT) は非推奨
  • PCTFREE / PCTUSED / Row Migration / Row Chaining は Block レベルのチューニング論点

Oracle 論理構造の全体像

Oracle データベースは「物理構造(データファイル・REDO ログ・制御ファイル等の OS ファイル)」と「論理構造(Oracle が内部的に管理する論理単位)」に分かれます。論理構造は次の 4 階層で構成されます。

階層役割対応する物理
Tablespace論理的なストレージ領域。1 つ以上のデータファイルから構成1 つ以上のデータファイル (.dbf)
Segment1 つのオブジェクト (Table / Index / Cluster 等) が使う領域1 つの Tablespace 内に存在
Extent連続した複数の Block。Segment 拡張の単位1 つのデータファイル内で連続
Data BlockI/O の最小単位。OS ブロックの倍数(通常 8KB)OS ブロック数個分

Data Block (データブロック)

Oracle が読み書きする最小単位です。デフォルトは 8KB、初期化パラメータ DB_BLOCK_SIZE で決まり、データベース作成後の変更は不可(個別 Tablespace は DB_nK_CACHE_SIZE で別サイズ可)。

-- ブロックサイズ確認
SHOW PARAMETER db_block_size;

SELECT value FROM v$parameter WHERE name = 'db_block_size';
-- 8192 (= 8KB)

-- Tablespace 別のブロックサイズ
SELECT tablespace_name, block_size FROM dba_tablespaces;

Block の内部構造

領域内容
Block Headerブロックアドレス、Segment 種類、トランザクション情報 (ITL)
Table Directoryこのブロックに含まれる Table 情報(Cluster 使用時)
Row Directoryこのブロック内の各行のオフセット情報
Free Space未使用領域(UPDATE による行サイズ増加に備える)
Row Data実際の行データ

Extent (エクステント)

Segment を拡張する単位で、連続した複数の Blockの集まりです。テーブルにデータが追加されて現在の Extent が満杯になると、新しい Extent を割り当てて Segment を拡張します。

-- Segment ごとの Extent 数とサイズ
SELECT segment_name, segment_type, extents, bytes/1024/1024 AS mb
FROM   dba_segments
WHERE  owner = 'SCOTT'
ORDER  BY bytes DESC;

-- Extent の詳細(どのデータファイルのどこに配置されているか)
SELECT segment_name, extent_id, file_id, block_id, blocks, bytes
FROM   dba_extents
WHERE  segment_name = 'EMP'
ORDER  BY extent_id;

Extent サイズの管理方式

方式特徴推奨
Locally Managed Tablespace (LMT)Tablespace 内のビットマップで Extent を管理。高速・断片化耐性◎★ 標準(10g 以降デフォルト)
Dictionary Managed Tablespace (DMT)データディクショナリ (SYSTEM 表領域) で管理。古い方式非推奨(互換性以外で使わない)
LMT - AUTOALLOCATEOracle が自動でサイズを決定(64KB → 1MB → 8MB → 64MB …)★ 推奨デフォルト
LMT - UNIFORM全 Extent を固定サイズ(例: 1M)にするパーティション表で有効

Segment (セグメント)

Segment は「1 つのオブジェクトが消費する全 Extent の集合」です。Segment の種類は次のとおり。

Segment 種類内容
Table Segment通常のヒープテーブル
Index SegmentB-Tree / Bitmap などの索引
Cluster SegmentIndex Cluster / Hash Cluster
LOB SegmentBLOB / CLOB 等の大型データ本体
LOB IndexLOB のためのインデックス
Temporary SegmentORDER BY / GROUP BY / Hash Join 等で一時的に使用
Rollback / UNDO SegmentUNDO 表領域内の取り消し情報
Partition Segmentパーティション化されたテーブル / 索引の各パーティション

Tablespace (表領域)

論理構造の最上位。1 つ以上のデータファイルから構成され、ユーザはオブジェクト作成時にどの Tablespace に置くかを指定します。

-- 表領域一覧と種類
SELECT tablespace_name, contents, status, extent_management, allocation_type
FROM   dba_tablespaces;

-- 表領域作成 (Locally Managed + AUTOALLOCATE)
CREATE TABLESPACE app_data
DATAFILE '/u01/app/oracle/oradata/ORCL/app_data01.dbf' SIZE 100M
AUTOEXTEND ON NEXT 10M MAXSIZE 10G
EXTENT MANAGEMENT LOCAL AUTOALLOCATE
SEGMENT SPACE MANAGEMENT AUTO;   -- ASSM

-- テーブルを指定 Tablespace に作成
CREATE TABLE emp (
    emp_id NUMBER PRIMARY KEY,
    name   VARCHAR2(100)
) TABLESPACE app_data
  PCTFREE 10 PCTUSED 40;

PCTFREE / PCTUSED と Row Migration

Block 内の領域管理を制御するパラメータです。UPDATE で行サイズが増えたとき、空き領域がないと「Row Migration」「Row Chaining」が発生し、性能が低下します。

パラメータ意味デフォルト
PCTFREEINSERT 用に確保しておく空き領域の % (UPDATE で行が伸びる余地)10
PCTUSED削除でこの % を下回ると INSERT 候補に戻すしきい値40 (ASSM では無視)
Row MigrationUPDATE で増えた行が現在 Block に入りきらず、別 Block に移動。ROWID は元 Block に残り 2 回 I/O避けたい
Row Chaining1 行が 1 Block に収まらず、複数 Block にまたがる(大型 VARCHAR2 / LOB)BLOCK SIZE 拡大で対処

ASSM (Automatic Segment Space Management)

Oracle 9i 以降のビットマップ方式の Segment 空間管理。Free List 方式 (MSSM) よりも RAC 環境で競合が少なく、PCTUSED 不要。9i 以降は ASSM が標準

-- ASSM か MSSM か確認
SELECT tablespace_name, segment_space_management
FROM   dba_tablespaces;
-- AUTO  → ASSM (推奨)
-- MANUAL → MSSM (FREELIST 方式)

確認に使う代表的なディクショナリビュー

ビュー用途
DBA_TABLESPACES表領域一覧、管理方式
DBA_DATA_FILESデータファイルと表領域の対応
DBA_SEGMENTSSegment 一覧、サイズ、Extent 数
DBA_EXTENTSExtent 単位の配置情報
DBA_FREE_SPACE表領域の空き Extent
USER_TS_QUOTASユーザに割り当てられた表領域クォータ
V$DATAFILEデータファイル状態(動的)

サイズ確認の実用 SQL

-- 表領域使用率
SELECT df.tablespace_name,
       ROUND(df.bytes/1024/1024, 1) AS total_mb,
       ROUND((df.bytes - NVL(fs.bytes,0))/1024/1024, 1) AS used_mb,
       ROUND((1 - NVL(fs.bytes,0)/df.bytes)*100, 1) AS pct_used
FROM   (SELECT tablespace_name, SUM(bytes) bytes FROM dba_data_files GROUP BY tablespace_name) df
LEFT JOIN (SELECT tablespace_name, SUM(bytes) bytes FROM dba_free_space GROUP BY tablespace_name) fs
  ON df.tablespace_name = fs.tablespace_name
ORDER BY pct_used DESC;

-- Segment トップ 10
SELECT owner, segment_name, segment_type, bytes/1024/1024 AS mb
FROM   dba_segments
ORDER  BY bytes DESC
FETCH  FIRST 10 ROWS ONLY;

-- Row Migration / Chaining 検出
ANALYZE TABLE scott.emp COMPUTE STATISTICS;
SELECT table_name, num_rows, chain_cnt FROM user_tables WHERE chain_cnt > 0;

FAQ

Q: Block サイズを後から変更できる?
A: データベース全体の DB_BLOCK_SIZE は作成後変更不可。ただし個別の Tablespace なら DB_nK_CACHE_SIZE パラメータと組合せて別サイズを使えます。

Q: Extent が増えすぎると遅い?
A: 数百〜数千程度なら問題ありません。極端に多い場合(数万〜)はフルスキャン時のオーバーヘッドが見えてきます。LMT AUTOALLOCATE なら Oracle が自動で増分を拡大するので通常問題化しません。

Q: Row Migration が見つかったらどうする?
A: 該当テーブルを ALTER TABLE ... MOVE で再構築し、必要なら PCTFREE を増やします。索引は無効化されるので ALTER INDEX ... REBUILD も忘れずに。

編集
Post Share
子ページ
  1. 表領域
  2. セグメント
  3. エクステント
  4. データブロック
同階層のページ
  1. 物理構造
  2. 論理構造

最近更新/作成されたページ