【Oracle】DBA_FREE_SPACE で表領域の空き容量を調べる方法|列の意味・断片化検出・空きエクステント分析まで解説

【Oracle】DBA_FREE_SPACE で表領域の空き容量を調べる方法|列の意味・断片化検出・空きエクステント分析まで解説 Oracle

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 データファイルの相対ファイル番号
DBA_FREE_SPACE は「空きエクステント単位」で行が返る
空き容量の合計を求めるには SUM(BYTES) で集計する必要があります。また、合計の空きが十分でも連続した空きが不足している場合(断片化)は、テーブルの EXTEND(拡張)に失敗することがあります。

空き容量を集計する SQL

表領域ごとの空き容量

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 して使用率を算出

SQL(使用率の算出: 最も実用的なクエリ)
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;

データファイル別の空き容量

SQL(ファイル単位の空き容量)
-- データファイルごとの空き容量
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 が発生することがあります。

断片化の指標: 空きエクステント数

SQL(断片化の確認)
-- 表領域ごとの空きエクステント数と平均サイズ
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

最大連続空き領域の確認

SQL(最大連続空き: ORA-01653 対策)
-- テーブル拡張に必要な最低限の連続空きがあるか確認
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 以上あるか確認
空き合計が十分でも ORA-01653 が出る原因
空き容量は合計で 500MB あっても、最大連続空きが 0.5MB しかなければ 1MB のエクステントを確保できません。この場合は断片化が原因です。COALESCE やデータの再配置で連続空きを確保する必要があります。

断片化の解消

ALTER TABLESPACE COALESCE

SQL(COALESCE: 隣接する空きエクステントを結合)
-- 隣接する空きエクステントを結合して連続空き領域を拡大
ALTER TABLESPACE users COALESCE;

-- COALESCE 前後の比較
-- 実行前: free_extent_count=150, max_free=2MB
-- 実行後: free_extent_count=10,  max_free=200MB
COALESCE は「隣接する」空きエクステントのみ結合
物理的に隣り合った空きエクステントだけを結合します。テーブルデータに挟まれた空きは結合できません。それでも断片化が解消しない場合は、テーブルの MOVE + SHRINK SPACE で根本的にデータを再配置する必要があります。

テーブルの MOVE + SHRINK SPACE

SQL(テーブル移動で断片化を根本解消)
-- テーブルを同じ表領域内で再配置(連続領域に再格納)
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 として表示
SQL(TEMP 表領域の空き容量)
-- 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;
SQL(UNDO 表領域のステータス別集計)
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)
SQL(DBA 権限がない場合)
-- DBA ロールがなくても自分の表領域の空きを確認
SELECT tablespace_name,
       ROUND(SUM(bytes)/1024/1024, 1) AS free_mb
FROM user_free_space
GROUP BY tablespace_name;

実務パターン集

パターン(1): 空き容量が少ない表領域を検出

SQL
-- 空き 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): 断片化が激しい表領域を検出

SQL
-- 空きエクステント数が 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): 日次監視スクリプト

SQL(日次監視用: 空き 80% 超 or 空き 500MB 未満)
-- アラート対象の表領域を検出
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): 空きエクステントの詳細一覧

SQL(個々の空きエクステントを確認)
-- 特定の表領域の空きエクステントを確認(断片化調査)
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)場合は断片化が深刻

よくある質問

QDBA_FREE_SPACE に特定の表領域が表示されません
A2 つの原因が考えられます。(1) TEMP 表領域は DBA_FREE_SPACE に含まれません。DBA_TEMP_FREE_SPACE を使ってください。(2) 表領域の空きが完全にゼロの場合、DBA_FREE_SPACE にその表領域の行が存在しません。DBA_DATA_FILES と LEFT JOIN すれば空き 0 として表示されます。
Q空き容量は十分なのに ORA-01653 が出ます
A断片化が原因です。空きの合計が十分でも、連続した空きエクステントが小さいと大きなエクステントを確保できません。DBA_FREE_SPACE の MAX(BYTES) で最大連続空きを確認し、COALESCE やテーブル MOVE で断片化を解消してください。
QDBA_FREE_SPACE と DBA_TABLESPACE_USAGE_METRICS はどう違いますか?
ADBA_FREE_SPACE は空きエクステント単位の詳細を返すビューで、断片化の分析に適しています。DBA_TABLESPACE_USAGE_METRICS はAUTOEXTEND を考慮した使用率を 1 行で返す簡易ビューです。空き容量の概要確認には USAGE_METRICS、断片化調査には FREE_SPACE を使います。
QCOALESCE で断片化は完全に解消しますか?
ACOALESCE は隣接する空きエクステントのみを結合します。データに挟まれた空きは結合できません。完全に解消するには ALTER TABLE MOVE でテーブルを再配置するか、SHRINK SPACE で行を前方に移動してください。
QDBA_FREE_SPACE への SELECT 権限がありません
ADBA_FREE_SPACE は DBA ロールまたは SELECT ANY DICTIONARY 権限が必要です。権限がない場合は USER_FREE_SPACE で自分のデフォルト表領域の空きを確認できます。
QUNDO 表領域の空きを DBA_FREE_SPACE で確認できますか?
A確認はできますが不正確です。UNDO エクステントには ACTIVE / UNEXPIRED / EXPIRED のステータスがあり、EXPIRED は実質的に再利用可能ですが DBA_FREE_SPACE には含まれません。正確な UNDO の空き状況は 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)完全ガイド」も併せて参照してください。