首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 全域暫存表 (GTT) 完全指南:定義、特性、動態創建與實戰陷阱

     編輯:Oracle 資料庫相關知識

前言:為何需要「只在當下存在」的表?

複雜報表、多階段 ETL、Session 級快取、避免鎖競爭——全域暫存表 (Global Temporary Table, GTT) 為這些場景提供了「資料隨 Session/Transaction 生滅、定義永久保留」的獨特機制。本文系統闡述 GTT 兩種模式、DDL 特性、動態創建模式、統計資訊管理、效能優勢與常見誤區。

核心語法:兩種生命週期模式

-- 1. Transaction-Specific (預設): ON COMMIT DELETE ROWS
CREATE GLOBAL TEMPORARY TABLE gtt_txn (
    id          NUMBER,
    process_id  VARCHAR2(50),
    payload     CLOB
) ON COMMIT DELETE ROWS;

-- 2. Session-Specific: ON COMMIT PRESERVE ROWS
CREATE GLOBAL TEMPORARY TABLE gtt_sess (
    session_id  NUMBER,
    step_name   VARCHAR2(100),
    result_json VARCHAR2(4000)
) ON COMMIT PRESERVE ROWS;

關鍵特性對比表

特性ON COMMIT DELETE ROWS (交易級)ON COMMIT PRESERVE ROWS (會話級)
資料可見性僅當前交易可見整個 Session 可見
資料清除時機COMMIT / ROLLBACK 瞬間截斷DISCONNECT Session 結束時截斷
適用場景單一交易多步驟中繼結果、避免中間表鎖跨交易、多步驟報表、Session 級快取、購物車
鎖行為無鎖競爭 (私有資料)無鎖競爭 (私有資料)
統計資訊12c+ 自動 Session 級統計12c+ 自動 Session 級統計
索引/約束支援 (定義時建立),同樣 Session 私有支援
外鍵參考❌ 不可被永久表參考❌ 不可被永久表參考
分區/LOB✅ 支援 (11g+)✅ 支援

動態創建模式:運行時按需建表

場景:報表參數動態決定欄位、多租戶隔離、避免永久物件膨脹。

CREATE OR REPLACE PROCEDURE create_dyn_gtt (
    p_table_name  IN VARCHAR2,
    p_cols        IN SYS.ODCIVARCHAR2LIST,  -- 欄位定義清單
    p_preserve    IN BOOLEAN DEFAULT FALSE  -- TRUE=Session, FALSE=Transaction
) AS
    v_sql VARCHAR2(4000);
    v_cnt NUMBER;
BEGIN
    -- 檢查是否已存在 (同 Session 內不可重複創建同名 GTT)
    SELECT COUNT(*) INTO v_cnt FROM user_tables WHERE table_name = UPPER(p_table_name);
    IF v_cnt = 0 THEN
        v_sql := 'CREATE GLOBAL TEMPORARY TABLE ' || p_table_name || ' (';
        FOR i IN 1..p_cols.COUNT LOOP
            v_sql := v_sql || p_cols(i) || ',';
        END LOOP;
        v_sql := RTRIM(v_sql, ',') || ') ON COMMIT ' || CASE WHEN p_preserve THEN 'PRESERVE ROWS' ELSE 'DELETE ROWS' END;
        EXECUTE IMMEDIATE v_sql;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        -- ORA-00955: name already used by existing object (跨 Session 並發創建)
        IF SQLCODE != -955 THEN RAISE; END IF;
END;
/

關鍵點:

  • GTT 定義在資料字典中永久存在,不可在同一 Session 重複 CREATE (ORA-00955),需先檢查 USER_TABLES。
  • 動態 DDL 會隱性提交 (Implicit Commit),謹慎用於交易中間。
  • 12c+ 支援 PRIVATE TEMPORARY TABLE (ORA$PTT_*),定義也在 Session 級私有,更適合極度動態場景。

統計資訊管理:12c 前後的分水嶺

版本統計機制DBA 操作
11g 及之前共享統計 (字典級),所有 Session 共用一組DBMS_STATS.GATHER_TABLE_STATS 收集後鎖定 (LOCK_TABLE_STATS) 防自動任務覆蓋
12c+Session 級私有統計 (Global Temporary Table Statistics)自動收集、自動維護、Session 隔離,無需人工干預

11g 避坑:若不同 Session 資料量差異巨大 (Session A 10 行, Session B 100 萬行),共享統計會導致其中一方計劃極差。解法:鎖定統計 + 動態採樣 (OPTIMIZER_DYNAMIC_SAMPLING=4) 或 Hint DYNAMIC_SAMPLING。

效能優勢:為何比永久中間表快?

  1. 零 Redo 生成:DML 不產生 Redo Log (僅 Undo),極大減少 Log File Sync 等待、Redo 傳輸頻寬 (Data Guard/GoldenGate)。
  2. 零鎖競爭:資料完全 Session 隔離,無 Row Lock、TM Lock、TX Lock 競爭。
  3. 高水位線 (HWM) 重置:TRUNCATE (隱性於 Commit/Disconnect) 瞬間重置 HWM,後續全掃描極快。
  4. Temp 表空間優化:資料儲存於 Temp 表空間,採用本地管理、統一大小 Extent,分配極快。

實戰陷阱與避雷指南

陷阱癥狀根因解法
連接池復用導致資料殘留Session 級 GTT 資料洩漏給下一個業務請求連接池不斷連,Session 不結束,ON COMMIT PRESERVE ROWS 不清理1) 用 ON COMMIT DELETE ROWS 2) 業務結束時顯式 DELETE FROM gtt 3) 連接池驗證查詢執行清理
統計資訊導致計劃翻車同一 SQL,Session A 走索引快,Session B 走全掃慢11g 共享統計不反映 Session 實際資料量升級 12c+;或鎖定統計 + 動態採樣;或 Hint 指定存取路徑
大量 GTT 併發導致 Temp 表空間爆滿ORA-01652: unable to extend temp segment並發 Session 各自佔用 Temp 空間,總和超限監控 Temp 使用率、增加 Temp 檔案、優化 SQL 減少中間結果集、考慮分批提交
跨資料庫連結 使用 GTTORA-02066: missing or invalid NETWORK LINKGTT 定義不可跨 DB Link 參考遠端也建同名 GTT,或改用永久表 + 定期清理
匯出/遷移遺漏 GTT 定義目標庫缺少 GTT,應用報錯EXP/IMP 預設不導出 GTT 資料 (資料本身不導),但定義需 ROWS=N 導出Data Pump INCLUDE=TABLE:\"LIKE 'GTT_%'\" 導出定義

進階用法:GTT + 管線函數 + 並行查詢

-- 1. GTT 儲存並行 Worker 產生的中間結果
CREATE GLOBAL TEMPORARY TABLE gtt_parallel_stage (
    worker_id   NUMBER,
    chunk_id    NUMBER,
    agg_result  NUMBER
) ON COMMIT PRESERVE ROWS;

-- 2. 並行管線函數寫入 GTT
CREATE OR REPLACE FUNCTION process_chunk(p_chunk_id NUMBER) RETURN SYS_REFCURSOR PIPELINED PARALLEL_ENABLE (PARTITION p_chunk_id BY ANY) IS
BEGIN
    -- 複雜計算...
    INSERT INTO gtt_parallel_stage VALUES (DBMS_DEBUG_JDWP.CURRENT_SESSION_ID, p_chunk_id, v_result);
    PIPE ROW(v_result);
END;

-- 3. 主查詢匯總 GTT
SELECT SUM(agg_result) FROM gtt_parallel_stage;

此模式將並行計算中間結果物質化於 GTT,避免多次重算,且無 Redo/鎖開銷。

總結

GTT 是 Oracle 解決「臨時中間結果物質化」的原生利器:定義永久、資料私有、零 Redo、零鎖、HWM 秒重置。掌握兩種模式 (Transaction/Session)、統計資訊演進 (12c+ Session 級)、動態創建限制、Temp 空間容量規劃、連接池清理策略,即可在複雜報表、ETL、高併發業務中釋放永久表的鎖與 Redo 壓力,實現極致效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved