GaussDB(DWS) 從8.2.1版本後支持三種形式的臨時表:本地臨時表、Volatile臨時表、全局臨時表。本地臨時表特點:表定義和數據都是會話相關,其他會話看不到本會話創建的本地臨時表。 ...
本文分享自華為雲社區《GaussDB(DWS)臨時表系列 - 本地臨時表》,作者: acydy 。
GaussDB(DWS) 從8.2.1版本後支持三種形式的臨時表:本地臨時表、Volatile臨時表、全局臨時表。本文先介紹DWS的本地臨時表功能。
本地臨時表特點:表定義和數據都是會話相關,其他會話看不到本會話創建的本地臨時表。元數據會持久化到系統表,集群節點異常出錯可以支持RETRY。
語法與使用
CREATE [LOCAL] { TEMPORARY | TEMP } TABLE [ IF NOT EXISTS ] table_name ({ column_name data_type [ compress_mode ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option [...] ] } [, ... ]) [ WITH ( {storage_parameter = value} [, ... ] ) ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS } ]
建表時需要指定TEMP或者TEMPORARY,表示創建本地臨時表。
- ON COMMIT { PRESERVE ROWS | DELETE ROWS }
ON COMMIT選項決定在事務中執行創建臨時表操作,當事務提交時,此臨時表的後續操作。
- PRESERVE ROWS(預設值):提交時不對臨時表做任何操作,臨時表及其表數據保持不變。建議使用此種類型。
- DELETE ROWS:提交時刪除臨時表中數據。
其他部分與普通表相同。
gaussdb=# create temp table tmp1(a int,b int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using round-robin as the distribution mode by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE
臨時表可以與非臨時表同名。如果同名,優先順序臨時表高於非臨時表。
gaussdb=# create temp table tmp1(a int,b int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using round-robin as the distribution mode by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# insert into tmp1 values(1,1); INSERT 0 1 gaussdb=# create table tmp1(a int,b int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using round-robin as the distribution mode by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# select *from tmp1; a | b ---+--- 1 | 1 (1 row) gaussdb=# select *from public.tmp1; a | b ---+--- (0 rows)
視圖:基於臨時表創建的視圖是臨時視圖。
postgres=# create view tmp_v1 as select *from tmp1; NOTICE: view "tmp_v1" will be a temporary view CREATE VIEW
使用場景
-
複雜業務邏輯使用本地臨時表拆分
如果業務SQL語句過於複雜,可以使用本地臨時表將執行的中間結果緩存下來,從而將複雜業務邏輯拆分成多個較簡單語句。簡單語句的統計信息更為準備,且拆分後的業務更易於維護。
-
支持CN節點出現異常。
GaussDB(DWS) 是一款分散式架構的資料庫。有多個Coordinator(CN),關係對等。客戶端可以連接任意一個CN。CN上存有表的元數據信息。在執行DDL時,會在所有DN上進行元數據的同步,保證數據一致性。如果某個CN出現異常,會導致創建表、刪除表等操作執行失敗,進而導致整個作業執行失敗。在這種場景,可以使用本地臨時表。本地臨時表只在當前會話可見。執行本地臨時表的創建、ALTER、刪除等操作時,只會在當前CN進行元數據的修改。這樣可以不受其他CN節點異常的影響,保證業務使用連續性。
原理
臨時表在元數據上與普通表的區別是臨時表由於在其他會話不可見,所以會建在一個只屬於當前會話的schema。本會話第一次創建臨時表時會同時建立這個會話的schema。每一個會話的臨時schema都不同。
會話1:
gaussdb=# create temp table tmp1(a int,b int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using round-robin as the distribution mode by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# \d+ tmp1 Table "pg_temp_coordinator1_65_3_140257888512760.tmp1" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+---------+--------------+------------- a | integer | | plain | | b | integer | | plain | | Has OIDs: no Distribute By: ROUND ROBIN Location Nodes: ALL DATANODES Options: orientation=row, compression=no:
會話2, 查詢不到tmp1表。
gaussdb=# select * from tmp1; ERROR: relation "tmp1" does not exist LINE 1: select * from tmp1; ^
臨時schema的命名規則:pg_temp_Coordinator名_timelineID_全局自增ID_threadID
Coordinator名:CN名稱,隔離不同CN創建的schema。
timelineID:在節點重啟後會增加,用於判斷此schema是否已經無效。
全局自增ID:單個CN上自增ID。同一個CN不用會話自增ID不同。
元數據:本地臨時表的relpersistence標識是’t’。
gaussdb=# select relname, relpersistence from pg_class where relname = 'tmp1'; relname | relpersistence ---------+---------------- tmp1 | t
數據清理:
-
會話正常退出
會話正常退出時, 本地臨時表的表定義和數據都會被刪除。無法再訪問原來的數據。 -
會話異常退出或者當前CN或者某個DN節點異常時。
出現異常時,節點的元數據和數據不會被立即刪除。 GaussDB(DWS)依賴組件gs_clean工具進行本地臨時表的自動定期清理。保證數據再一段周期後得到清理,防止空間持續膨脹。
CN Retry
CN Retry功能開啟時會為臨時表數據記錄日誌,為保證數據一致性,在使用臨時表時不建議切換CN Retry開關狀態,保持使用臨時表的會話中CN Retry開關始終處於打開狀態或者關閉狀態。
在打開CN Retry時,DN節點異常重啟,臨時表的數據可以保證不丟失。DN重啟後,仍可以訪問之前的會話。
如果希望臨時表不記錄日誌:
set max_query_retry_times = 0;
使用約束
- 如果上層應用,使用了連接池機制連接GaussDB(DWS),在使用臨時表時,強烈建議將連接歸還連接池之前,將臨時表主動刪除,避免造成連接未斷開導致的數據異常。或者使用命令
DISCARD TEMP
清理會話的臨時表信息。 - 擴容時忽略本地臨時表。
- 不支持gs_dump 本地臨時表。