TEMP 表領域は ORDER BY / GROUP BY / DISTINCT / ハッシュ結合などのソートやハッシュ処理で一時的に使用される作業領域です。PGA(メモリ)に収まらない処理が TEMP に書き出されるため、大量データの処理でTEMP が肥大化し、ディスクを圧迫することがあります。
本記事では、肥大化の原因特定、犯人セッションの検出、TEMPFILE の縮小・再作成、PGA チューニングによる根本対策まで解説します。
・TEMP 表領域が肥大化する 5 つの原因
・V$SORT_USAGE で TEMP を大量消費しているセッション(犯人)を特定
・DBA_TEMP_FREE_SPACE で使用状況を監視
・TEMPFILE の縮小(RESIZE)と再作成
・PGA_AGGREGATE_TARGET のチューニング(根本対策)
・TEMP 表領域グループの活用
・ORA-01652 の緊急対処
TEMP 表領域が肥大化する原因
| 原因 | 発生する SQL | 対策 |
|---|---|---|
| 大量データのソート | ORDER BY / GROUP BY(PGA 不足でディスクソート) | PGA_AGGREGATE_TARGET を拡大 / インデックスで ORDER BY を代替 |
| ハッシュ結合 | 大テーブル同士の JOIN(ハッシュテーブルが PGA に収まらない) | PGA を拡大 / 結合対象のデータ量を WHERE で削減 |
| DISTINCT / UNION | 重複排除のためのソート | UNION ALL で代替可能か検討 / EXISTS で書き換え |
| グローバルテンポラリテーブル | INSERT INTO gtt SELECT … の大量データ | GTT のサイズを見直し / 処理後に TRUNCATE |
| 未クローズのカーソル / セッション | 長時間実行中の SQL がTEMP を占有し続ける | 犯人セッションを特定して KILL |
大量データの ORDER BY やハッシュ結合を行えば TEMP の使用は正常な動作です。問題なのは「処理が終わっても TEMP が解放されない」「想定以上に TEMP を使う SQL がある」ケースです。まず犯人を特定し、SQL チューニングか PGA 拡大で対処します。
TEMP の使用状況を確認する
DBA_TEMP_FREE_SPACE(全体の使用状況)
-- TEMP 表領域の全体使用状況
SELECT tablespace_name,
ROUND(tablespace_size/1024/1024) AS total_mb,
ROUND(allocated_space/1024/1024) AS allocated_mb,
ROUND(free_space/1024/1024) AS free_mb,
ROUND(allocated_space/tablespace_size * 100, 1) AS used_pct
FROM dba_temp_free_space;
V$SORT_USAGE(セッション別の TEMP 使用量)
-- セッション別の TEMP 使用量(降順: 最も使っているセッションが先頭)
SELECT s.sid, s.serial#, s.username, s.program,
s.sql_id,
ROUND(t.blocks * 8192/1024/1024, 1) AS temp_mb,
SUBSTR(q.sql_text, 1, 80) AS sql_text
FROM v$sort_usage t
JOIN v$session s ON t.session_addr = s.saddr
LEFT JOIN v$sql q ON s.sql_id = q.sql_id
ORDER BY t.blocks DESC;
-- ユーザー別の TEMP 消費量合計
SELECT s.username,
COUNT(*) AS session_count,
ROUND(SUM(t.blocks * 8192)/1024/1024, 1) AS total_temp_mb
FROM v$sort_usage t
JOIN v$session s ON t.session_addr = s.saddr
GROUP BY s.username
ORDER BY total_temp_mb DESC;
-- V$TEMPSEG_USAGE = V$SORT_USAGE の別名(同じ内容)
SELECT username, segtype,
ROUND(SUM(blocks * 8192)/1024/1024, 1) AS temp_mb
FROM v$tempseg_usage
GROUP BY username, segtype
ORDER BY temp_mb DESC;
-- segtype: SORT / HASH / DATA / INDEX / LOB_DATA 等
-- SORT = ORDER BY, HASH = ハッシュ結合
・SORT: ORDER BY / GROUP BY / DISTINCT でのソート
・HASH: ハッシュ結合(大テーブル JOIN)
・DATA: CTAS / INSERT SELECT の一時データ
segtype が SORT なら PGA 拡大やインデックス追加、HASH ならデータ量の削減が有効です。
TEMP を大量消費しているセッションを KILL する
-- (1) 犯人を特定
SELECT s.sid, s.serial#, s.username,
ROUND(t.blocks * 8192/1024/1024, 1) AS temp_mb,
s.sql_id
FROM v$sort_usage t
JOIN v$session s ON t.session_addr = s.saddr
ORDER BY t.blocks DESC
FETCH FIRST 5 ROWS ONLY;
-- (2) KILL(SID と SERIAL# を指定)
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
-- KILL 後に TEMP が解放されるまで数秒〜数分かかる場合がある
闇雲に KILL すると業務に影響します。sql_id から SQL の内容を確認し、不要な SQL(テスト中 / 放置されたセッション等)であることを確認してから KILL してください。業務上必要な SQL なら、完了を待つか PGA チューニングで対処します。
TEMPFILE の縮小と再作成
TEMP 表領域が肥大化した後、TEMPFILE は自動的には縮小しません。手動で RESIZE するか、TEMPFILE を再作成する必要があります。
TEMPFILE のリサイズ(縮小)
-- 現在の TEMPFILE サイズを確認 SELECT file_name, ROUND(bytes/1024/1024) AS size_mb, autoextensible FROM dba_temp_files; -- RESIZE で縮小(使用中でないブロック分だけ縮小可能) ALTER DATABASE TEMPFILE '/oracle/oradata/ORCL/temp01.dbf' RESIZE 500M; -- ORA-03297 が出る場合: まだ使用中のブロックがある -- → 全セッションの TEMP 使用が解放されるまで待つか、DB 再起動
TEMPFILE の DROP + 再作成(確実な方法)
-- (1) 既存の TEMPFILE を DROP
ALTER TABLESPACE temp DROP TEMPFILE '/oracle/oradata/ORCL/temp01.dbf';
-- (2) 新しい TEMPFILE を追加(適切なサイズで)
ALTER TABLESPACE temp ADD TEMPFILE '/oracle/oradata/ORCL/temp01.dbf'
SIZE 1G AUTOEXTEND ON NEXT 100M MAXSIZE 5G;
-- ※ TEMP 表領域に TEMPFILE が 1 つしかない場合は DROP できない
-- → 先に別の TEMPFILE を追加してから DROP
TEMP 表領域自体を再作成(最も確実)
-- (1) 新しい TEMP 表領域を作成
CREATE TEMPORARY TABLESPACE temp_new
TEMPFILE '/oracle/oradata/ORCL/temp_new01.dbf'
SIZE 1G AUTOEXTEND ON NEXT 100M MAXSIZE 5G;
-- (2) DB のデフォルト一時表領域を変更
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp_new;
-- (3) 全ユーザーの一時表領域を変更(任意)
-- ALTER USER app_user TEMPORARY TABLESPACE temp_new;
-- (4) 旧 TEMP 表領域を DROP(使用中のセッションがなくなってから)
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;
旧 TEMP を使用中のセッションがある間は DROP できません。デフォルト TEMP を新しい表領域に変更した後、全セッションが切断されるのを待つか、業務時間外に実施してください。
PGA チューニング(根本対策)
TEMP の使用はPGA(メモリ上の作業領域)に収まらない処理が発生した結果です。PGA を拡大すればメモリ内で処理が完了し、TEMP への書き出し(ディスクソート)が減少します。
-- PGA_AGGREGATE_TARGET の確認
SHOW PARAMETER pga_aggregate_target;
-- PGA の使用状況
SELECT name, ROUND(value/1024/1024) AS mb
FROM v$pgastat
WHERE name IN (
'aggregate PGA target parameter',
'aggregate PGA auto target',
'total PGA allocated',
'maximum PGA allocated',
'cache hit percentage'
);
-- cache hit percentage: 100% に近いほどメモリ内で処理完了
-- 低い場合(80% 以下)は PGA の拡大を検討
-- PGA_AGGREGATE_TARGET を 2GB に拡大 ALTER SYSTEM SET pga_aggregate_target = 2G SCOPE=BOTH; -- 個別セッションの作業領域サイズ上限を確認 SHOW PARAMETER workarea_size_policy; -- AUTO(デフォルト推奨)
| PGA パラメータ | 意味 | 推奨 |
|---|---|---|
| PGA_AGGREGATE_TARGET | PGA 全体の目標サイズ | SGA の 20%〜50% 程度。大量ソートが多い場合は増加 |
| WORKAREA_SIZE_POLICY | AUTO / MANUAL | AUTO(Oracle が自動調整) |
PGA cache hit percentage が 80% 以下の場合、多くのソートがディスク(TEMP)に書き出されています。PGA_AGGREGATE_TARGET を拡大すればメモリ内処理の割合が増え、TEMP の消費が大幅に削減されます。
SQL チューニングで TEMP 使用を削減する
| 原因 SQL パターン | チューニング方法 |
|---|---|
| ORDER BY で全件ソート | インデックスで ORDER BY を代替。FETCH FIRST N ROWS ONLY で件数制限 |
| 大テーブル同士の JOIN | WHERE 条件でデータ量を絞ってから JOIN。インデックスの追加 |
| DISTINCT で重複排除 | EXISTS / IN で書き換え可能か検討。重複の原因を JOIN で修正 |
| UNION(重複排除あり) | UNION ALL で代替可能か検討(重複排除不要なら ALL が高速) |
| GROUP BY + HAVING | WHERE で先にフィルタしてから GROUP BY(集計対象を削減) |
TEMP 表領域グループ(負荷分散)
TEMP 表領域グループを使うと、複数の TEMP 表領域を束ねてソート処理を分散できます。大規模なパラレル処理で TEMP がボトルネックになる場合に有効です。
-- グループに属する TEMP 表領域を作成
CREATE TEMPORARY TABLESPACE temp1
TEMPFILE '/oracle/disk1/temp1.dbf' SIZE 2G
TABLESPACE GROUP temp_group;
CREATE TEMPORARY TABLESPACE temp2
TEMPFILE '/oracle/disk2/temp2.dbf' SIZE 2G
TABLESPACE GROUP temp_group;
-- ユーザーにグループを割り当て
ALTER USER app_user TEMPORARY TABLESPACE temp_group;
-- グループの確認
SELECT * FROM dba_tablespace_groups;
ORA-01652 の緊急対処
ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
| 対処 | SQL | 効果 |
|---|---|---|
| TEMPFILE を追加 | ALTER TABLESPACE temp ADD TEMPFILE ‘…’ SIZE 2G AUTOEXTEND ON | 即効 |
| 既存 TEMPFILE を拡大 | ALTER DATABASE TEMPFILE ‘…’ RESIZE 5G | 即効 |
| 犯人セッションを KILL | ALTER SYSTEM KILL SESSION ‘sid,serial#’ | 即効 |
| PGA を拡大 | ALTER SYSTEM SET pga_aggregate_target = 2G SCOPE=BOTH | 中長期 |
| SQL をチューニング | 不要なソートを排除 / データ量を削減 | 根本対策 |
実務パターン集
パターン(1): TEMP を大量消費している犯人を特定して対処
-- (1) 犯人を特定
SELECT s.sid, s.serial#, s.username,
ROUND(SUM(t.blocks)*8192/1024/1024, 1) AS temp_mb,
s.sql_id
FROM v$sort_usage t
JOIN v$session s ON t.session_addr = s.saddr
GROUP BY s.sid, s.serial#, s.username, s.sql_id
ORDER BY temp_mb DESC;
-- (2) SQL の内容を確認
SELECT sql_fulltext FROM v$sql WHERE sql_id = 'abc123def456';
-- (3) 不要なセッションなら KILL
-- ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
パターン(2): 肥大化した TEMP を縮小
-- (1) 現在のサイズを確認 SELECT file_name, ROUND(bytes/1024/1024) AS size_mb FROM dba_temp_files; -- (2) 使用中のセッションがないか確認 SELECT COUNT(*) FROM v$sort_usage; -- (3) 0 件なら RESIZE で縮小 ALTER DATABASE TEMPFILE '/oracle/oradata/ORCL/temp01.dbf' RESIZE 1G;
パターン(3): PGA cache hit percentage の改善
-- (1) 現在の cache hit percentage を確認 SELECT name, value FROM v$pgastat WHERE name = 'cache hit percentage'; -- 80% 以下 = ディスクソートが多い -- (2) PGA を拡大 ALTER SYSTEM SET pga_aggregate_target = 2G SCOPE=BOTH; -- (3) しばらく運用して cache hit percentage が改善したか確認
パターン(4): 定期監視スクリプト
-- TEMP 使用率の監視
SELECT tablespace_name,
ROUND(allocated_space/tablespace_size * 100, 1) AS used_pct
FROM dba_temp_free_space
WHERE allocated_space/tablespace_size * 100 >= 80;
-- 結果があればアラート(メール通知等に組み込む)
よくある質問
まとめ
TEMP 表領域の管理の要点をまとめます。
| やりたいこと | 方法 |
|---|---|
| TEMP の使用状況を確認 | SELECT * FROM dba_temp_free_space |
| TEMP を大量消費しているセッションを特定 | V$SORT_USAGE + V$SESSION を JOIN して blocks DESC |
| 犯人セッションを KILL | ALTER SYSTEM KILL SESSION ‘sid,serial#’ IMMEDIATE |
| TEMPFILE を縮小 | ALTER DATABASE TEMPFILE ‘…’ RESIZE 1G |
| TEMPFILE を再作成 | DROP TEMPFILE → ADD TEMPFILE |
| TEMP 表領域自体を再作成 | CREATE TEMPORARY TABLESPACE → ALTER DATABASE DEFAULT → DROP 旧 |
| 根本対策: PGA を拡大 | ALTER SYSTEM SET pga_aggregate_target = 2G SCOPE=BOTH |
| ORA-01652 の緊急対処 | ADD TEMPFILE / RESIZE / KILL SESSION |
表領域の使用状況確認は「表領域の使用状況を確認する SQL まとめ」、データファイルの追加は「データファイルを追加・変更する方法」、表領域の管理全般は「表領域(Tablespace)完全ガイド」も併せて参照してください。

