Mogdb支持全局临时表和本地临时表,创建临时表时可以在TEMP或TEMPORARY前指定GLOBAL或LOCAL关键字。如果指定GLOBAL关键字,MogDB会创建全局临时表,否则MogDB会创建本地临时表。
  • 全局临时表
    全局临时表的元数据对所有会话可见,会话结束后元数据继续存在。
    全局临时表有两种模式:
    一种是基于会话级别的(ON COMMIT PRESERVE ROWS),当会话结束时自动清空用户数据;
    一种是基于事务级别的(ON COMMIT DELETE ROWS),当执行commit或rollback时自动清空用户数据。
    表时如果没有指定ON COMMIT选项,则缺省为会话级别。
  • 本地临时表
    本地临时表只在当前会话可见,本会话结束后会自动删除。因此,在除当前会话连接的数据库节点故障时,仍然可以在当前会话上创建和使用临时表。由于临时表只在当前会话创建,对于涉及对临时表操作的DDL语句,会产生DDL失败的报错。因此,建议DDL语句中不要对临时表进行操作。TEMP和TEMPORARY等价。


语法

CreateTable ::= CREATE [ [ GLOBAL | LOCAL ] [ TEMPORARY | TEMP ] | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name 
    ({ column_name data_type [ CHARACTER SET | CHARSET charset ] [ compress_mode ] [ COLLATE collation ] [ column_constraint [ ... ] ]
        | table_constraint
        | LIKE source_table [ like_option [...] ] }
        [, ... ])
    [ AUTO_INCREMENT [ = ] value ]
    [ [DEFAULT] CHARACTER SET | CHARSET [ = ] default_charset ] [ [DEFAULT] COLLATE [ = ] default_collation ]
    [ WITH ( {storage_parameter = value} [, ... ] ) ]
    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
    [ COMPRESS | NOCOMPRESS ]
    [ TABLESPACE tablespace_name ]
    [ COMMENT =? 'text' ];

会话一

CREATE GLOBAL TEMPORARY TABLE global_temp_table (
    id INT,
    name VARCHAR(50)
) ON COMMIT PRESERVE ROWS;

CREATE TEMPORARY TABLE local_temp_table (
    id INT,
    name VARCHAR(50)
) ON COMMIT PRESERVE ROWS;

auxdb=#  SELECT table_name FROM information_schema.tables WHERE table_name = 'global_temp_table';
    table_name     
-------------------
 global_temp_table
(1 row)

auxdb=#  SELECT table_name FROM information_schema.tables WHERE table_name = 'local_temp_table';
    table_name    
------------------
 local_temp_table
(1 row)

会话二

auxdb=# SELECT table_name FROM information_schema.tables WHERE table_name = 'global_temp_table';
    table_name     
-------------------
 global_temp_table
(1 row)

auxdb=# SELECT table_name FROM information_schema.tables WHERE table_name = 'local_temp_table';
 table_name 
------------
(0 rows)

其他注意事项:

  • 本地临时表通过每个会话独立的以pg_temp开头的schema来保证只对当前会话可见,因此,不建议用户在日常操作中手动删除以pg_temp,pg_toast_temp开头的schema。
  • 如果建表时不指定TEMPORARY/TEMP关键字,而指定表的schema为当前会话的pg_temp_开头的schema,则此表会被创建为临时表。
  • ALTER/DROP全局临时表和索引,如果其它会话正在使用它,禁止操作(ALTER INDEX index_name REBUILD除外)。
  • 全局临时表的DDL只会影响当前会话的用户数据和索引。例如truncate、reindex、analyze只对当前会话有效。
  • 全局临时表功能可以通过设置GUC参数max_active_global_temporary_table控制是否启用。如果max_active_global_temporary_table=0,关闭全局临时表功能。
  • 临时表只对当前会话可见,因此不支持与\parallel on并行执行一起使用。
  • 临时表不支持主备切换。
  • 全局临时表不响应自动清理,在长链接场景使用时尽量使用on commit delete rows的全局临时表,或定期手动执行vacuum,否则可能导致clog日志不回收。


一、临时表

2.1、会话级临时表

会话级临时表中数据的生命周期为整个会话。语法如下

CREATE TEMPORARY | TEMP TABLE ...

TEMP与TEMPORARY等价

auxdb=# create temp table temp_ta(id int , name varchar(20));
CREATE TABLE
auxdb=# 
auxdb=# insert into temp_ta values (1,'A');
INSERT 0 1
auxdb=# insert into temp_ta values (2,'B');
INSERT 0 1
auxdb=# insert into temp_ta values (3,'C');
INSERT 0 1
auxdb=# 
auxdb=# select * from temp_ta;
 id | name 
----+------
  1 | A
  2 | B
  3 | C
(3 rows)

auxdb=# \q
[sysomm@db1 ~]$ gsql -r 
gsql ((MogDB 5.0.1 build ae6d2ada) compiled at 2023-08-16 09:07:43 commit 0 last mr 1804 )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.

MogDB=# \c auxdb
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "auxdb" as user "sysomm".
auxdb=# select * from temp_ta;
ERROR:  relation "temp_ta" does not exist on dn_6001
LINE 1: select * from temp_ta;
                      ^

多个会话允许创建同名临时表,如下会话一创建完临时表的同时打开新的会话,会话二创建同名临时表,运行结果如下

auxdb=# create  temp table temp_ta(id int , name varchar(20));
CREATE TABLE
auxdb=# 
auxdb=# insert into temp_ta values (1,'A');
INSERT 0 1
auxdb=# insert into temp_ta values (2,'B');
INSERT 0 1
auxdb=# insert into temp_ta values (3,'C');
INSERT 0 1
auxdb=# 
auxdb=# select * from temp_ta;
 id | name 
----+------
  1 | A
  2 | B
  3 | C
(3 rows)

auxdb=# 
auxdb=# 
auxdb=# explain verbose select * from temp_ta;
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Seq Scan on pg_temp_dn_6001_1_2_46920789591808.temp_ta  (cost=0.00..18.88 rows=888 width=62)
   Output: id, name
(2 rows)

auxdb=# create  temp table temp_ta(id int , name varchar(20));
CREATE TABLE
auxdb=# 
auxdb=# insert into temp_ta values (1,'AB');
INSERT 0 1
auxdb=# insert into temp_ta values (2,'BB');
INSERT 0 1
auxdb=# insert into temp_ta values (3,'CB');
INSERT 0 1
auxdb=# 
auxdb=# select * from temp_ta;
 id | name 
----+------
  1 | AB
  2 | BB
  3 | CB
(3 rows)

auxdb=# 
auxdb=# explain verbose select * from temp_ta;
                                          QUERY PLAN                                           
-----------------------------------------------------------------------------------------------
 Seq Scan on pg_temp_dn_6001_1_10_46920990131968.temp_ta  (cost=0.00..18.88 rows=888 width=62)
   Output: id, name
(2 rows)

两者最主要的区别在于,temp_ta的schema不一致!

会话一为pg_temp_dn_6001_1_2_46920789591808.temp_ta

会话二为pg_temp_dn_6001_1_10_46920990131968.temp_ta


2.2、事务级临时表

语法如下

CREATE TEMPORARY | TEMP TABLE ... ON COMMIT ...

在ON COMMIT后面有三个选项分别是

DELETE ROWS:数据仅存在事务周期中,事务提交后,临时表中的数据就清除掉了。

PERSERVE ROWS:(默认)创建会话级临时表的选项,可以不写。

2.2.1、ON COMMIT DELETE ROWS

auxdb=# create  temp table temp_ta(id int , name varchar(20)) ON COMMIT DELETE ROWS;
verbose select * from temp_ta;CREATE TABLE
auxdb=# 
auxdb=# begin;
BEGIN
auxdb=# insert into temp_ta values (1,'A');
INSERT 0 1
auxdb=# insert into temp_ta values (2,'B');
INSERT 0 1
auxdb=# insert into temp_ta values (3,'C');
INSERT 0 1
auxdb=# 
auxdb=# select * from temp_ta;
 id | name 
----+------
  1 | A
  2 | B
  3 | C
(3 rows)

auxdb=# 
auxdb=# end;
COMMIT
auxdb=# 
auxdb=# select * from temp_ta;
 id | name 
----+------
(0 rows)

auxdb=# 
auxdb=# explain verbose select * from temp_ta;
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Seq Scan on pg_temp_dn_6001_1_4_46920948127488.temp_ta  (cost=0.00..18.88 rows=888 width=62)
   Output: id, name
(2 rows)