DBA_FREE_SPACE は Oracle の表領域内の空きエクステント(未使用領域)を確認するためのデータディクショナリビューです。容量不足の事前検知や断片化の調査に使います。
本記事では、DBA_FREE_SPACE の列の意味、空き容量の集計 SQL、使用率の算出、空きエクステントの断片化検出、TEMP / UNDO 表領域の代替ビューまで解説します。
・DBA_FREE_SPACE の全列の意味
・表領域ごとの空き容量を集計する SQL
・DBA_DATA_FILES と JOIN して使用率を算出する方法
・空きエクステントの断片化を検出する SQL
・最大連続空き領域を確認する SQL(ORA-01653 対策)
・TEMP / UNDO 表領域の空き容量を確認する代替ビュー
・COALESCE / SHRINK SPACE による断片化解消
DBA_FREE_SPACE とは
DBA_FREE_SPACE は表領域内の各空きエクステントを 1 行として返すビューです。1 つの表領域に空きが 3 か所あれば 3 行が返ります。
全列の意味
| 列名 | データ型 | 説明 |
|---|---|---|
| TABLESPACE_NAME | VARCHAR2 | 表領域名 |
| FILE_ID | NUMBER | データファイルの ID(DBA_DATA_FILES と結合に使用) |
| BLOCK_ID | NUMBER | 空きエクステントの開始ブロック番号 |
| BYTES | NUMBER | 空きエクステントのサイズ(バイト) |
| BLOCKS | NUMBER | 空きエクステントのサイズ(ブロック数) |
| RELATIVE_FNO | NUMBER | データファイルの相対ファイル番号 |
空き容量の合計を求めるには
SUM(BYTES) で集計する必要があります。また、合計の空きが十分でも連続した空きが不足している場合(断片化)は、テーブルの EXTEND(拡張)に失敗することがあります。空き容量を集計する SQL
表領域ごとの空き容量
-- 表領域ごとの空き容量合計
SELECT tablespace_name,
COUNT(*) AS free_extents,
ROUND(SUM(bytes)/1024/1024, 1) AS free_mb
FROM dba_free_space
GROUP BY tablespace_name
ORDER BY free_mb;
DBA_DATA_FILES と JOIN して使用率を算出
SELECT
df.tablespace_name,
ROUND(df.total_mb, 1) AS total_mb,
ROUND(df.total_mb - NVL(fs.free_mb, 0), 1) AS used_mb,
ROUND(NVL(fs.free_mb, 0), 1) AS free_mb,
ROUND((df.total_mb - NVL(fs.free_mb, 0)) / df.total_mb * 100, 1) AS used_pct
FROM
(SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb
FROM dba_data_files GROUP BY tablespace_name) df
LEFT JOIN
(SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb
FROM dba_free_space GROUP BY tablespace_name) fs
ON df.tablespace_name = fs.tablespace_name
ORDER BY used_pct DESC;
データファイル別の空き容量
-- データファイルごとの空き容量
SELECT df.tablespace_name, df.file_name,
ROUND(df.bytes/1024/1024) AS file_mb,
ROUND(NVL(fs.free_bytes, 0)/1024/1024, 1) AS free_mb,
ROUND((df.bytes - NVL(fs.free_bytes, 0)) / df.bytes * 100, 1) AS used_pct
FROM dba_data_files df
LEFT JOIN (
SELECT file_id, SUM(bytes) AS free_bytes
FROM dba_free_space GROUP BY file_id
) fs ON df.file_id = fs.file_id
ORDER BY df.tablespace_name, df.file_name;
AUTOEXTEND 考慮の使用率や TEMP / UNDO の確認は「表領域の使用状況を確認する SQL まとめ」で詳しく解説しています。
空きエクステントの断片化を検出する
合計の空きが十分でも、空きが細かく分散(断片化)していると大きなエクステントを確保できず ORA-01653 が発生することがあります。
断片化の指標: 空きエクステント数
-- 表領域ごとの空きエクステント数と平均サイズ
SELECT tablespace_name,
COUNT(*) AS free_extent_count,
ROUND(SUM(bytes)/1024/1024, 1) AS total_free_mb,
ROUND(AVG(bytes)/1024/1024, 2) AS avg_free_mb,
ROUND(MAX(bytes)/1024/1024, 1) AS max_free_mb,
ROUND(MIN(bytes)/1024/1024, 2) AS min_free_mb
FROM dba_free_space
GROUP BY tablespace_name
ORDER BY free_extent_count DESC;
| 指標 | 正常 | 断片化の疑い |
|---|---|---|
| 空きエクステント数 | 少ない(1〜10 程度) | 多い(100 以上) |
| 最大空きエクステント | 空き合計に近い | 合計の 10% 以下 |
| 平均空きエクステント | 大きい | 数 KB〜数百 KB |
最大連続空き領域の確認
-- テーブル拡張に必要な最低限の連続空きがあるか確認
SELECT tablespace_name,
ROUND(MAX(bytes)/1024/1024, 1) AS max_contiguous_free_mb
FROM dba_free_space
GROUP BY tablespace_name
ORDER BY max_contiguous_free_mb;
-- ORA-01653 で「128 ブロック必要」と言われた場合
-- 128 * 8192(8KB ブロック)= 1MB の連続空きが必要
-- max_contiguous_free_mb が 1MB 以上あるか確認
空き容量は合計で 500MB あっても、最大連続空きが 0.5MB しかなければ 1MB のエクステントを確保できません。この場合は断片化が原因です。COALESCE やデータの再配置で連続空きを確保する必要があります。
断片化の解消
ALTER TABLESPACE COALESCE
-- 隣接する空きエクステントを結合して連続空き領域を拡大 ALTER TABLESPACE users COALESCE; -- COALESCE 前後の比較 -- 実行前: free_extent_count=150, max_free=2MB -- 実行後: free_extent_count=10, max_free=200MB
物理的に隣り合った空きエクステントだけを結合します。テーブルデータに挟まれた空きは結合できません。それでも断片化が解消しない場合は、テーブルの MOVE + SHRINK SPACE で根本的にデータを再配置する必要があります。
テーブルの MOVE + SHRINK SPACE
-- テーブルを同じ表領域内で再配置(連続領域に再格納) ALTER TABLE hr.employees MOVE; -- MOVE 後はインデックスの再構築が必須 ALTER INDEX hr.idx_emp_dept REBUILD; -- SHRINK SPACE: 行移動ありの圧縮(12c 以降推奨) ALTER TABLE hr.employees ENABLE ROW MOVEMENT; ALTER TABLE hr.employees SHRINK SPACE CASCADE; -- CASCADE: テーブル + 全インデックスを同時に圧縮
| 方法 | 動作 | インデックス再構築 | DML 中の実行 |
|---|---|---|---|
| COALESCE | 隣接する空きエクステントを結合 | 不要 | 可能(高速) |
| ALTER TABLE MOVE | テーブルを連続領域に再配置 | 必要(UNUSABLE になる) | 不可(テーブルロック) |
| SHRINK SPACE | 行を前方に移動して末尾を解放 | CASCADE で自動 | 可能(オンライン) |
DBA_FREE_SPACE の制限事項
| 制限 | 説明 | 代替ビュー |
|---|---|---|
| TEMP 表領域が表示されない | TEMP 表領域は一時ファイルを使用するため DBA_FREE_SPACE に含まれない | DBA_TEMP_FREE_SPACE / V$SORT_USAGE |
| UNDO 表領域の空きが不正確 | UNDO エクステントには ACTIVE/UNEXPIRED/EXPIRED の状態があり、単純な空き計算では不正確 | DBA_UNDO_EXTENTS(STATUS 別に集計) |
| 完全に使い切った表領域は 0 行 | 空きが全くない場合 DBA_FREE_SPACE にその表領域の行が存在しない | LEFT JOIN で DBA_DATA_FILES と結合すると 0 として表示 |
-- DBA_TEMP_FREE_SPACE(11g 以降)
SELECT tablespace_name,
ROUND(tablespace_size/1024/1024) AS total_mb,
ROUND(free_space/1024/1024) AS free_mb
FROM dba_temp_free_space;
SELECT tablespace_name, status,
ROUND(SUM(bytes)/1024/1024, 1) AS mb
FROM dba_undo_extents
GROUP BY tablespace_name, status
ORDER BY tablespace_name, status;
-- EXPIRED = 再利用可能(実質的な空き)
権限による使い分け(USER / ALL / DBA)
| ビュー | 参照範囲 | 必要な権限 |
|---|---|---|
| USER_FREE_SPACE | 自分のデフォルト表領域のみ | なし(全ユーザーが使用可能) |
| DBA_FREE_SPACE | 全表領域 | DBA ロール(または SELECT ANY DICTIONARY) |
-- DBA ロールがなくても自分の表領域の空きを確認
SELECT tablespace_name,
ROUND(SUM(bytes)/1024/1024, 1) AS free_mb
FROM user_free_space
GROUP BY tablespace_name;
実務パターン集
パターン(1): 空き容量が少ない表領域を検出
-- 空き 500MB 未満の表領域を検出
SELECT df.tablespace_name,
ROUND(NVL(fs.free_mb, 0), 1) AS free_mb,
ROUND((df.total_mb - NVL(fs.free_mb, 0)) / df.total_mb * 100, 1) AS used_pct
FROM (SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb
FROM dba_data_files GROUP BY tablespace_name) df
LEFT JOIN (SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb
FROM dba_free_space GROUP BY tablespace_name) fs
ON df.tablespace_name = fs.tablespace_name
WHERE NVL(fs.free_mb, 0) < 500
ORDER BY free_mb;
パターン(2): 断片化が激しい表領域を検出
-- 空きエクステント数が 50 以上 = 断片化の疑い
SELECT tablespace_name,
COUNT(*) AS free_extents,
ROUND(SUM(bytes)/1024/1024, 1) AS total_free_mb,
ROUND(MAX(bytes)/1024/1024, 1) AS max_contiguous_mb
FROM dba_free_space
GROUP BY tablespace_name
HAVING COUNT(*) >= 50
ORDER BY free_extents DESC;
-- 断片化が激しい場合は COALESCE を実行
-- ALTER TABLESPACE 表領域名 COALESCE;
パターン(3): 日次監視スクリプト
-- アラート対象の表領域を検出
SELECT tablespace_name, used_pct, free_mb
FROM (
SELECT df.tablespace_name,
ROUND((df.total_mb - NVL(fs.free_mb, 0)) / df.total_mb * 100, 1) AS used_pct,
ROUND(NVL(fs.free_mb, 0), 1) AS free_mb
FROM (SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb
FROM dba_data_files GROUP BY tablespace_name) df
LEFT JOIN (SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb
FROM dba_free_space GROUP BY tablespace_name) fs
ON df.tablespace_name = fs.tablespace_name
)
WHERE used_pct >= 80 OR free_mb < 500
ORDER BY used_pct DESC;
パターン(4): 空きエクステントの詳細一覧
-- 特定の表領域の空きエクステントを確認(断片化調査)
SELECT file_id, block_id,
ROUND(bytes/1024/1024, 2) AS free_mb,
blocks
FROM dba_free_space
WHERE tablespace_name = 'USERS'
ORDER BY bytes DESC;
-- 上位 5 件が十分大きければ断片化は問題なし
-- 全件が小さい(数 KB)場合は断片化が深刻
よくある質問
USER_FREE_SPACE で自分のデフォルト表領域の空きを確認できます。DBA_UNDO_EXTENTS を使ってください。まとめ
DBA_FREE_SPACE を使った空き容量確認の要点をまとめます。
| やりたいこと | SQL / ビュー |
|---|---|
| 表領域ごとの空き容量 | SELECT tablespace_name, SUM(bytes) FROM dba_free_space GROUP BY … |
| 使用率の算出 | dba_data_files と dba_free_space を LEFT JOIN |
| データファイル別の空き | dba_data_files と dba_free_space を file_id で JOIN |
| 最大連続空き領域 | SELECT MAX(bytes) FROM dba_free_space GROUP BY tablespace_name |
| 断片化の検出 | COUNT(*) が多い + MAX(bytes) が小さい = 断片化 |
| 断片化の解消 | ALTER TABLESPACE ts COALESCE / ALTER TABLE t SHRINK SPACE CASCADE |
| TEMP 表領域の空き | DBA_TEMP_FREE_SPACE |
| UNDO 表領域の状況 | DBA_UNDO_EXTENTS(STATUS 別集計) |
AUTOEXTEND 考慮の使用率や閾値アラートは「表領域の使用状況を確認する SQL まとめ」、データファイルの追加は「データファイルを追加・変更する方法」、表領域の管理全般は「表領域(Tablespace)完全ガイド」も併せて参照してください。

