タイトル: セグメント
SEOタイトル: Oracle セグメント完全ガイド(Table / Index / Extent / ASSM / PCTFREE)
| この記事の要点 |
|
セグメントの位置づけ
Oracle の物理構造と論理構造の関係:
論理構造 (Logical Structure)
Database
└── Tablespace(論理的なグルーピング)
└── Segment(特定オブジェクトの領域全体)★ 本記事のテーマ
└── Extent(連続した Block の集まり)
└── Block(最小 I/O 単位、通常 8KB)
物理構造 (Physical Structure)
Database
└── Datafile (.dbf)
└── OS File System Block
1 セグメント = 1 オブジェクト(基本的に)。例えば EMPLOYEES テーブルには EMPLOYEES セグメントが割り当てられ、その下に複数の Extent、さらに Block が並びます。
セグメントの種類
| 種類 | 用途 | 例 |
|---|---|---|
| Table Segment | 通常テーブルの行データ | EMPLOYEES |
| Index Segment | B-Tree インデックスのデータ | EMP_PK |
| Cluster Segment | クラスタ表の共通領域 | INDEX / HASH CLUSTER |
| Temporary Segment | ORDER BY / GROUP BY / HASH JOIN 等の中間結果 | TEMP テーブルスペース |
| Rollback / Undo Segment | 更新前イメージ(UNDO データ) | UNDOTBS1 |
| LOB Segment | CLOB / BLOB 本体(大容量カラム) | LOB$_xxx |
| Partition Segment | パーティション表 / 索引の各パーティション | EMP_P_2024_01 |
セグメントを確認する
-- 自分が所有するセグメント一覧
SELECT segment_name, segment_type, tablespace_name,
bytes / 1024 / 1024 AS size_mb,
extents, blocks
FROM user_segments
ORDER BY bytes DESC;
-- 全 DB のセグメント(DBA 権限)
SELECT owner, segment_name, segment_type, tablespace_name,
bytes / 1024 / 1024 AS size_mb
FROM dba_segments
WHERE tablespace_name = 'USERS'
ORDER BY bytes DESC;
-- 特定テーブルが使う Extent
SELECT segment_name, extent_id, blocks, bytes
FROM user_extents
WHERE segment_name = 'EMPLOYEES'
ORDER BY extent_id;
-- セグメントの未使用領域(HWM 下の Free Block)
SELECT segment_name, blocks AS total_blocks,
(blocks - blocks * (1 - PCT_FREE/100)) AS free_estimate
FROM user_segments s, user_tables t
WHERE s.segment_name = t.table_name;
STORAGE 句
セグメント作成時に Extent サイズや拡張ルールを指定できます。Locally Managed Tablespace では多くが無視されますが、知っておく価値はあります。
CREATE TABLE big_log (
id NUMBER PRIMARY KEY,
body CLOB
)
TABLESPACE app_data
PCTFREE 10 -- 行追加用に 10% 予約
PCTUSED 40 -- 使用率 40% を切ったらフリーリスト復帰
INITRANS 4 -- 初期トランザクションスロット数
STORAGE (
INITIAL 64K -- 最初の Extent サイズ
NEXT 1M -- 次の Extent サイズ
PCTINCREASE 0 -- Extent サイズの自動拡大率(旧)
MINEXTENTS 1
MAXEXTENTS UNLIMITED
BUFFER_POOL DEFAULT -- バッファプール指定
);
PCTFREE と PCTUSED
ブロック内の領域管理パラメータです。UPDATE で行サイズが増えるかどうかで選びます。
| 用途 | PCTFREE | PCTUSED |
|---|---|---|
| 更新が少ない (INSERT only) | 10 (デフォルト) | 40 |
| UPDATE で行が膨らむ (例: status カラム更新) | 20〜30 | 40 |
| UPDATE で大きく膨らむ (CLOB 追記) | 40〜50 | 30 |
| INSERT only ログ系(最大充填) | 0〜1 | 99 |
Row Migration / Chaining
PCTFREE が小さすぎると、UPDATE で行サイズが増えたときに同じブロックに収まらず別ブロックに移動(Row Migration)し、後続の SELECT が 2 ブロックを読む羽目に。
-- Row Migration の検出
ANALYZE TABLE employees COMPUTE STATISTICS;
SELECT table_name, chain_cnt
FROM user_tables
WHERE chain_cnt > 0;
-- 解消: 再構築
ALTER TABLE employees MOVE;
-- インデックスは UNUSABLE になるので再構築
ALTER INDEX emp_pk REBUILD;
ASSM (Automatic Segment Space Management)
Oracle 9i 以降の標準のフリースペース管理方式。旧来のフリーリスト方式に比べ、並列 INSERT のホットブロック競合を減らします。
-- ASSM が有効か確認
SELECT tablespace_name, segment_space_management
FROM dba_tablespaces;
-- segment_space_management = AUTO → ASSM
-- 新規 Tablespace を ASSM で作成
CREATE TABLESPACE app_data
DATAFILE '/u01/oradata/app_data01.dbf' SIZE 100M
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO; -- ★
-- ASSM 配下では PCTUSED / FREELISTS / FREELIST GROUPS は無視される
-- PCTFREE のみ有効
Segment Advisor
未使用領域 (HWM の下の空き) や Row Migration を検出するアドバイザ。
-- セグメントアドバイザ実行
DECLARE
task_id NUMBER;
BEGIN
DBMS_ADVISOR.CREATE_TASK('Segment Advisor', task_id, 'my_task');
DBMS_ADVISOR.CREATE_OBJECT('my_task', 'TABLE', 'HR', 'EMPLOYEES',
NULL, NULL, NULL);
DBMS_ADVISOR.EXECUTE_TASK('my_task');
END;
/
-- 結果確認
SELECT message, more_info
FROM user_advisor_findings
WHERE task_name = 'my_task';
-- 推奨アクション: ALTER TABLE ... SHRINK SPACE
ALTER TABLE employees ENABLE ROW MOVEMENT;
ALTER TABLE employees SHRINK SPACE COMPACT;
ALTER TABLE employees SHRINK SPACE;
ALTER TABLE employees DISABLE ROW MOVEMENT;
Temporary Segment と Undo Segment
通常テーブルとは扱いが違う 2 つの特殊セグメントです。
Temporary Segment:
- ORDER BY / GROUP BY / HASH JOIN / SUBQUERY などで中間結果を保持
- TEMP テーブルスペースに作られる
- セッション終了で開放
- 監視: V$SORT_USAGE / V$TEMPSEG_USAGE
- 不足: ORA-01652 unable to extend temp segment
Undo Segment:
- UPDATE / DELETE 前の旧データを保持(ROLLBACK と Read Consistency のため)
- UNDO テーブルスペースに作られる
- UNDO_RETENTION で保持時間制御
- 不足: ORA-01555 snapshot too old / ORA-30036 unable to extend undo
セグメントの削除と縮小
-- セグメント削除 (テーブル削除)
DROP TABLE old_table; -- セグメントも消える(10g+ はゴミ箱経由)
DROP TABLE old_table PURGE; -- ゴミ箱を経由せず即削除
-- 空のセグメントを残してデータだけ消す
TRUNCATE TABLE big_log; -- 高速、Extent は MINEXTENTS まで残る
TRUNCATE TABLE big_log DROP STORAGE; -- Extent も解放
-- セグメントの SHRINK
ALTER TABLE t ENABLE ROW MOVEMENT;
ALTER TABLE t SHRINK SPACE;
ALTER TABLE t DISABLE ROW MOVEMENT;
FAQ
Q: テーブルが思ったよりサイズが大きい
A: HWM 下に未使用領域がある可能性。Segment Advisor で確認し、SHRINK で縮小。Row Migration が多いなら MOVE で再構築。
Q: パーティションテーブルのセグメントは?
A: パーティションごとに 1 セグメント。DBA_SEGMENTS の partition_name で識別できます。
Q: LOB セグメントが肥大化する
A: 旧バージョンの SecureFile LOB は削除しても自動解放されないことが。ALTER TABLE ... MODIFY LOB ... (SHRINK SPACE) で縮小。