You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL如何创建事务级唯一的TEMP TABLE?

问题描述

我希望在存储函数中实现查询物化,最初尝试使用MATERIALIZED CTE:

WITH cte2 AS MATERIALIZED (
      SELECT
        arg_date,
        RANK() over(ORDER BY cte1.arg_date DESC) AS DATE_RANK
      FROM cte1
   )

但这样做并没有提升函数性能。随后我改用TEMP TABLE实现:

CREATE OR REPLACE FUNCTION test_f
-- 部分代码省略
AS $function$
-- 部分代码省略
begin
-- 部分代码省略
CREATE TEMP TABLE cte2 ON COMMIT DROP as
   with cte1 AS (
        SELECT 
            arg_date::date AS arg_date
        FROM UNNEST(date_array) AS arg_date
   )
    SELECT
        cte1.arg_date,
        date_part('year', cte1.arg_date) AS ARG_YEAR,
        RANK() over(ORDER BY cte1.arg_date DESC) AS DATE_RANK
      FROM cte1
   ;
-- 部分代码省略
end;
-- 部分代码省略
$function$

改用TEMP TABLE后,函数性能提升了3倍!

现在我需要确认以下几个问题:

  • 该TEMP TABLE cte2每次调用存储函数时是否是唯一的?
  • PostgreSQL文档提到"PostgreSQL instead requires each session to issue its own CREATE TEMPORARY TABLE command.",且ON COMMIT DROP会在事务结束时删除TEMP TABLE。但每次事务开始时是否会创建唯一的TEMP TABLE实例?
  • 每个实例是否仅当前事务可见?
  • 该特性是默认生效还是可显式指定?
问题解答
  • 每次调用存储函数时,TEMP TABLE cte2是唯一的:PostgreSQL的临时表是会话隔离的,结合ON COMMIT DROP的特性,每次事务执行到CREATE TEMP TABLE语句时,都会创建全新的临时表实例——即便同名,只要前一个实例已被销毁(事务结束自动删除),新的调用就会生成独立的实例,不会产生冲突。
  • 每次事务开始时创建的TEMP TABLE实例是唯一的:临时表本身属于会话级隔离资源,加上ON COMMIT DROP会在事务结束时自动销毁表,所以每次事务触发函数执行时,都会生成仅属于当前事务的全新临时表实例,与其他事务的实例完全独立。
  • 每个临时表实例仅当前事务可见:这是PostgreSQL临时表的默认行为,临时表的可见范围被限定在创建它的会话内,而ON COMMIT DROP进一步把生命周期缩限到当前事务,其他事务(哪怕是同一会话内的并行事务)都无法访问这个临时表实例。
  • 该特性默认生效,无需显式指定:会话隔离、ON COMMIT DROP的事务级自动销毁都是PostgreSQL临时表的内置行为,只要使用CREATE TEMP TABLE并指定ON COMMIT DROP,这些特性就会自动启用,不需要额外配置。

内容的提问来源于stack exchange,提问作者Иван Размахнин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:15:39