KINGBASE 支援全域性臨時表
阿新 • • 發佈:2021-06-16
Postgresql 支援會話級別的臨時表,表的存續期只在建立臨時表的會話存活期間,會話退出後,臨時表自動刪除,表結構及資料也無法跨會話共享。KINGBASE除了支援PG原生的臨時表機制外,還支援類似oracle 的臨時表機制,也就是全域性臨時表。全域性臨時表支援表結構共享,避免使用者每次了都需要建立臨時表的操作。以下以例子的形式,介紹PG 臨時表與全域性臨時表的機制與差異。
一、PG 支援的臨時表
會話A:建立臨時表
test=# create temporary table temp_t1(id integer); CREATE TABLE test=# insert into temp_t1 values(1); INSERT 0 1 test=# \d List of relations Schema | Name | Type | Owner -----------+---------------------+-------+-------- pg_temp_4 | temp_t1 | table | system test=# select * from temp_t1; id ---- 1
會話B:
test=# select * from pg_temp_4.temp_t1; ERROR: cannot access temporary tables of other sessions
PG 臨時表機制總結:
- 建立語法上,臨時表可以選擇global or local,但實際都是local的(PG 後續語法不再支援 global),其它會話不能訪問(實際是空表可以訪問,有資料情況下就會報錯)。
- ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP }
- PRESERVE ROWS 表示臨時表的資料在事務結束後保留。預設使用的是PRESERVE ROWS。
- DELETE ROWS 表示臨時表的資料在事務結束後truncate掉。
- DROP 表示臨時表在事務結束後刪除。
- 當會話第一次建立臨時表時,會自動建立 SYS_TEMP_XXX 模式,該會話的所有臨時表都放在該模式下。如果表裡有可能產生toast儲存的欄位,也會同時建立pg_toast_temp_XXX模式。
- 臨時表在會話結束後會自動刪除(或者在事務結束後刪除on commit drop),也就是說每個會話需要使用臨時表的話需要重新建立。
- 如果有臨時表和非臨時表重名了, 那麼預設是使用臨時表的,因為臨時表模式在search_path 引數值裡是排在最前面的。如果要使用非臨時表,需要帶上schema,如schema.table。
- 臨時表上建立的索引也是臨時的。
- 臨時表的統計資訊不會被autovacuum daemon自動收集,所以如果有複雜查詢的話,最好在有DML後執行analyze。
二、全域性臨時表
PG 建臨時表時也可以用 create global temporary table,但實際建立的都是local 級別的。KINGBASE 如果用create global temporary table,實際意義上建立的是全域性的臨時表,臨時表的機制與oracle相似。
A會話:建立臨時表
test=# create global temporary table g_temp_t1(id integer) on commit preserve rows; CREATE TABLE test=# insert into g_temp_t1 values(1); INSERT 0 1 test=# select * from g_temp_t1; id ---- 1 (1 row) test=# \d List of relations Schema | Name | Type | Owner -----------+---------------------+-------+-------- pg_temp_4 | temp_t1 | table | system public | g_temp_t1 | table | system
B會話:可以訪問A會話建立的臨時表
test=# select * from g_temp_t1; id ---- (0 rows) test=# insert into g_temp_t1 values(2); INSERT 0 1 test=# select * from g_temp_t1; id ---- 2
A會話:會話退出後,表結構還在,但A會話插入的資料沒有了。
test=# select * from g_temp_t1; id ---- 1 (1 row) test=# \q [kingbase@dbhost03 ~]$ ksql -d test -U system ksql (V8.0) Type "help" for help. test=# \d List of relations Schema | Name | Type | Owner --------+---------------------+-------+-------- public | g_temp_t1 | table | system public | sys_stat_statements | view | system test=# select * from g_temp_t1; id ---- (0 rows)
KINGBASE 全域性臨時表總結:
- 與oracle一樣,預設是 on commit delete rows
- 臨時表資料只對當前會話或事務可見。每個會話只能檢視和修改自己的資料。
三、普通表、臨時表、全域性臨時表字典資訊差異
test=# select relnamespace::regnamespace, relname,relpersistence,relkind,reltablespace from pg_class where relname in ('t1','temp_t1','g_temp_t1'); relnamespace | relname | relpersistence | relkind | reltablespace --------------+-----------+----------------+---------+--------------- public | t1 | p | r | 0 public | g_temp_t1 | s | r | 0 pg_temp_5 | temp_t1 | t | r | 0
以下幾點需要注意:
- relkind 都為 r ,都是relation。
- relpersistence 不同,全域性臨時表為 s ,普通臨時表為 t
- relnamespace 不同,普通臨時表是建立在 pg_temp_xxx 模式下
- 不管是全域性臨時表,還是普通臨時表,預設都是unlogged 方式
四、效能比較
test=# create table t1(id integer,name varchar(200)); CREATE TABLE test=# create temporary table temp_t1(id integer,name varchar(200)); CREATE TABLE test=# create global temporary table g_temp_t1(id integer,name varchar(200)); CREATE TABLE BEGIN for i in 1..200000 loop insert into g_temp_t1 values(i,repeat('a',200)); end loop; END; / ANONYMOUS BLOCK Time: 1684.636 ms (00:01.685) BEGIN for i in 1..200000 loop insert into temp_t1 values(i,repeat('a',200)); end loop; END; / ANONYMOUS BLOCK Time: 741.746 ms BEGIN for i in 1..200000 loop insert into t1 values(i,repeat('a',200)); end loop; END; / ANONYMOUS BLOCK Time: 944.549 ms test=# insert into temp_t1 select generate_series(1,500000),repeat('a',200); INSERT 0 500000 Time: 484.780 ms
test=# insert into g_temp_t1 select generate_series(1,500000),repeat('a',200); INSERT 0 500000 Time: 2606.722 ms (00:02.607)
test=# insert into t1 select generate_series(1,500000),repeat('a',200); INSERT 0 500000 Time: 1856.685 ms (00:01.857)
通過觀察日誌,可以看到本地臨時表、全域性臨時表基本不產生redo日誌。但從實際執行效率看,全域性臨時表的效率是最差的,甚至不如普通的表。但這不妨礙全域性臨時表的使用,不產生Redo就是最好的優點。
五、全域性臨時表實現機制
根據全域性臨時表的relfilenode,我們查找了相關的表,發現數據庫目錄下有如下檔案:
-rw------- 1 kingbase kingbase 8192 Jun 16 15:45 t5_19820 -rw------- 1 kingbase kingbase 8192 Jun 16 15:47 t4_19820
每個檔案實際對應一個事務,事務提交後,對應檔案也就刪除。