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 表領域が肥大化する 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 |
TEMP が大きいこと自体は異常ではない
大量データの ORDER BY やハッシュ結合を行えば TEMP の使用は正常な動作です。問題なのは「処理が終わっても TEMP が解放されない」「想定以上に TEMP を使う SQL がある」ケースです。まず犯人を特定し、SQL チューニングか PGA 拡大で対処します。
大量データの ORDER BY やハッシュ結合を行えば TEMP の使用は正常な動作です。問題なのは「処理が終わっても TEMP が解放されない」「想定以上に TEMP を使う SQL がある」ケースです。まず犯人を特定し、SQL チューニングか PGA 拡大で対処します。
TEMP の使用状況を確認する
DBA_TEMP_FREE_SPACE(全体の使用状況)
SQL(TEMP 表領域の使用率)
-- 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 使用量)
SQL(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;
SQL(TEMP 使用量のユーザー別集計)
-- ユーザー別の 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;
SQL(V$TEMPSEG_USAGE: V$SORT_USAGE の別名)
-- 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 = ハッシュ結合
segtype でどの処理が TEMP を使っているかわかる
・SORT: ORDER BY / GROUP BY / DISTINCT でのソート
・HASH: ハッシュ結合(大テーブル JOIN)
・DATA: CTAS / INSERT SELECT の一時データ
segtype が SORT なら PGA 拡大やインデックス追加、HASH ならデータ量の削減が有効です。
・SORT: ORDER BY / GROUP BY / DISTINCT でのソート
・HASH: ハッシュ結合(大テーブル JOIN)
・DATA: CTAS / INSERT SELECT の一時データ
segtype が SORT なら PGA 拡大やインデックス追加、HASH ならデータ量の削減が有効です。
TEMP を大量消費しているセッションを KILL する
SQL(犯人セッションの特定と 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 の内容を確認
闇雲に KILL すると業務に影響します。sql_id から SQL の内容を確認し、不要な SQL(テスト中 / 放置されたセッション等)であることを確認してから KILL してください。業務上必要な SQL なら、完了を待つか PGA チューニングで対処します。
闇雲に KILL すると業務に影響します。sql_id から SQL の内容を確認し、不要な SQL(テスト中 / 放置されたセッション等)であることを確認してから KILL してください。業務上必要な SQL なら、完了を待つか PGA チューニングで対処します。
TEMPFILE の縮小と再作成
TEMP 表領域が肥大化した後、TEMPFILE は自動的には縮小しません。手動で RESIZE するか、TEMPFILE を再作成する必要があります。
TEMPFILE のリサイズ(縮小)
SQL(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 + 再作成(確実な方法)
SQL(TEMPFILE の再作成)
-- (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 表領域自体を再作成(最も確実)
SQL(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 表領域の再作成は全セッションが旧 TEMP を使い終わってから
旧 TEMP を使用中のセッションがある間は DROP できません。デフォルト TEMP を新しい表領域に変更した後、全セッションが切断されるのを待つか、業務時間外に実施してください。
旧 TEMP を使用中のセッションがある間は DROP できません。デフォルト TEMP を新しい表領域に変更した後、全セッションが切断されるのを待つか、業務時間外に実施してください。
PGA チューニング(根本対策)
TEMP の使用はPGA(メモリ上の作業領域)に収まらない処理が発生した結果です。PGA を拡大すればメモリ内で処理が完了し、TEMP への書き出し(ディスクソート)が減少します。
SQL(PGA の現在設定と使用状況)
-- 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 の拡大を検討
SQL(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 を拡大すると TEMP の使用が劇的に減る
PGA cache hit percentage が 80% 以下の場合、多くのソートがディスク(TEMP)に書き出されています。PGA_AGGREGATE_TARGET を拡大すればメモリ内処理の割合が増え、TEMP の消費が大幅に削減されます。
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 がボトルネックになる場合に有効です。
SQL(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 を大量消費している犯人を特定して対処
SQL
-- (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 を縮小
SQL
-- (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 の改善
SQL
-- (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): 定期監視スクリプト
SQL(TEMP 使用率が 80% 超でアラート)
-- 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;
-- 結果があればアラート(メール通知等に組み込む)
よくある質問
QTEMP 表領域は自動的に縮小しますか?
A縮小しません。AUTOEXTEND ON で拡張された TEMPFILE は、処理完了後も大きいままです。手動で RESIZE するか、TEMPFILE を DROP + 再作成してください。
QDB を再起動すれば TEMP は縮小しますか?
ADB 再起動で TEMP の使用中データは解放されますが、TEMPFILE 自体のサイズは変わりません。ファイルサイズを縮小するには RESIZE または再作成が必要です。
QV$SORT_USAGE が 0 件なのに TEMP が大きいままです
AV$SORT_USAGE は現在使用中のセッションのみ表示します。過去の処理で TEMPFILE が拡張されたまま残っているだけです。RESIZE または TEMPFILE 再作成で縮小してください。
QTEMP 表領域の AUTOEXTEND は ON にすべきですか?
AON にすることを推奨します。AUTOEXTEND OFF だと大量ソート時に ORA-01652 が発生します。ただし MAXSIZE を設定して無制限拡張を防いでください。
QTEMP 表領域をバックアップする必要がありますか?
A不要です。TEMP 表領域は一時データのみを格納するため、RMAN / Data Pump のバックアップ対象外です。破損した場合は TEMPFILE を DROP + 再作成するだけで復旧できます。
QPGA_AGGREGATE_TARGET をいくつに設定すべきですか?
A一般的には SGA の 20%〜50% が目安です。V$PGASTAT の cache hit percentage が 80% 以下なら拡大を検討してください。大量のソートやハッシュ結合を行う環境では SGA と同等以上に設定することもあります。
まとめ
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)完全ガイド」も併せて参照してください。

