← 返回题目列表

Oracle 全局临时表 GTT 是什么?ON COMMIT DELETE ROWS 和 PRESERVE ROWS 有什么区别?

中等 第 23 / 32 题 更新于 2026/07/30
Oracle临时表GTT

简化版

Oracle 全局临时表的表结构是全局持久的,但数据是会话或事务私有的。ON COMMIT DELETE ROWS 表示提交后清空当前事务数据,ON COMMIT PRESERVE ROWS 表示数据保留到会话结束。

详细版

GTT 常用于批处理、报表中间结果、复杂过程拆分。多个会话看到同一张临时表结构,但各自的数据互相隔离。

示例:

CREATE GLOBAL TEMPORARY TABLE tmp_order_ids (
  order_id NUMBER
) ON COMMIT DELETE ROWS;

它不是普通表,也不是每次自动创建的表。使用时要注意提交时机、索引、统计信息、连接池复用和临时表空间压力。

完整版教学

一、GTT 的“全局”和“临时”分别指什么

“全局”指表定义对数据库可见,创建一次后对象结构一直存在;“临时”指表里的数据是临时的,并且对会话或事务隔离。

这和很多人理解的“临时表就是临时创建一张表”不同。Oracle GTT 不是每次用完就 drop 表结构。

表结构:全局共享
表数据:会话/事务私有

二、两种 ON COMMIT 模式

ON COMMIT DELETE ROWS 在事务提交时清空当前会话在表里的数据;ON COMMIT PRESERVE ROWS 则保留到会话结束。

CREATE GLOBAL TEMPORARY TABLE tmp_a(id NUMBER)
ON COMMIT DELETE ROWS;

CREATE GLOBAL TEMPORARY TABLE tmp_b(id NUMBER)
ON COMMIT PRESERVE ROWS;

前者适合事务内中间数据,后者适合同一会话内多步骤处理。

三、为什么连接池场景要小心

应用连接池会复用数据库会话。如果使用 PRESERVE ROWS,数据可能保留到会话结束,而连接池里的会话并不一定随请求结束而关闭。

这就可能出现请求 A 写入临时数据,请求 B 复用同一连接时看到残留数据的风险。虽然通常会通过清理避免,但设计时必须意识到会话生命周期。

因此 Web 应用里更常用 ON COMMIT DELETE ROWS,或每次使用前显式清理。

四、GTT 的性能和空间

GTT 数据通常使用临时段,减少对普通业务表的影响。它适合大批量中间结果,而不是把小逻辑都拆到临时表里。

如果一次任务写入 500 万行临时数据,临时表空间也会承压。还要考虑临时表上的索引维护成本。

场景是否适合 GTT原因
批量中间结果适合简化 SQL 和过程
请求级小变量不适合过度设计
跨请求状态不适合会话复用风险
报表预聚合适合中间集合清晰

五、统计信息和执行计划

GTT 也可能涉及执行计划。不同会话写入数据量差异很大时,统计信息不准确可能导致计划不稳定。

例如有的任务写 100 行,有的任务写 100 万行,同一 SQL 的最优计划不同。需要结合 Oracle 版本、动态采样和统计策略处理。

这也是 GTT 面试题容易深入的地方:它不是只会创建表,还涉及执行计划和临时空间管理。

六、常见误区与追问

  • 误区:GTT 的表结构也是临时的。 表结构是持久对象,临时的是会话或事务数据。
  • 误区:PRESERVE ROWS 在请求结束就清空。 它保留到会话结束,连接池复用时要小心。
  • 误区:GTT 不占空间。 大量数据会占用临时表空间,并可能维护索引。
  • 追问:两种 ON COMMIT 怎么选? 事务内中间结果用 DELETE ROWS,会话多步骤用 PRESERVE ROWS。
  • 追问:多个会话会互相看到数据吗? 不会,数据是会话私有的。

七、加强记忆

记忆钩子:GTT 像公司共用白板模板,白板框架大家都看得到,但每个会议室写的内容只在自己房间里。

回答这题要同时讲结构持久、数据私有、提交清理模式、连接池和临时空间。这样才不是只背 CREATE GLOBAL TEMPORARY TABLE