Temporary Space(一時表領域)とは

Temporary Space = 一時的な作業用ディスク領域。

  • 主にソートやハッシュ結合の作業域として使われる。
  • PGA(セッション専用メモリ)で処理しきれない場合に、あふれた分がここへ書き出される(Spill to Disk)。
  • トランザクションのコミット/ロールバックの対象外で、REDOが原則生成されない(製品差はある)。
  • 「使い終わったらすぐ捨てる前提」の領域。
PGA(ソート作業)でメモリで足りる ⇒ 高速 ✔ / 足りない ⇒ 一時表領域(Disk)にあふれ、ディスクI/Oで急に遅くなる。

何に使われるのか

  • ORDER BY: インデックスが効かない並び替えで巨大ソート発生
  • GROUP BY / DISTINCT: 重複排除や集計のための作業領域
  • UNION(≠ UNION ALL): 重複排除のためのソート
  • HASH JOIN: 片側を一時域でハッシュ化し結合
  • ウィンドウ関数(OVER): PARTITION/ORDER単位でソート
  • 大きな中間結果セット: サブクエリやCTEの結果が大きい時
  • グローバル一時テーブル: 明示的に CREATE GLOBAL TEMPORARY TABLE
  • インデックス作成(CREATE INDEX): B-Treeの構築過程でソート

通常表領域との違い

一時はI/Oを多く出す可能性が高い ⇒ 業務データと違う物理ディスクに配置するのがセオリー

設定とサイジング

サイジングの考え方

  • 「同時に走る最大の大型SQL × その作業量」を試算。
  • 夜間バッチ等の最ピーク時を基準にする。
  • 自動拡張(オートエクステンド)は有効推奨だが、上限なしにすると暴走したSQLでディスク枯渇。

配置の考え方

  • USERS / INDEX / TEMPは別物理ディスクが理想。
  • SSDのような高速I/Oが一時で特に効く。
  • 複数の一時ファイルでI/Oを分散。
-- 一時表領域の作成例 (汎用)
CREATE TEMPORARY TABLESPACE temp1
  TEMPFILE '/data/temp1_01.dbf'
  SIZE 4G AUTOEXTEND ON
  NEXT 256M MAXSIZE 32G;

-- ユーザに割り当て
ALTER USER app_user
  TEMPORARY TABLESPACE temp1;

-- 現状の使用率を確認
SELECT tablespace_name,
       used_blocks, total_blocks
  FROM v$sort_segment;

開発者として気をつけるSQL

  • 不要なORDER BY: アプリ側でソート可能なら付けない。ページネーション目的は別途検討。
  • DISTINCTの濫用: 本当に重複しているのか?を疑う。JOINの設計ミスで重複している例が多い。
  • UNIONの代わりにUNION ALL: 重複が起きないことが分かっているならALLを使う(ソート不要)。
  • 大きなIN句 / EXISTS: 巨大なリストはハッシュ結合になりやすく一時を消費。
  • 巨大なGROUP BY: 集計キーの粒度を上げ、件数を抑える。サブクエリで先に絞る。
  • LIMITのないトップN: サーバ側ですべてソートしてしまう。LIMIT/ROWNUMを付ける。
実行計画に「SORT (Disk)」や「SPILL」が出てきたら、ほぼ確実に一時表領域を使っている。