1. 程式人生 > 其它 >KingbaseES Truncate 與 Delete 機制比較

KingbaseES Truncate 與 Delete 機制比較

使用過Oracle的都知道,Truncate操作由於不需要寫redo日誌,因此,在效能上會比delete操作更高效,但在實際使用過程中,有時會發現delete比truncate速度更快。以下介紹下二者的機制,讓大家對二者有清晰的瞭解。

一、大資料量刪除操作

1、資料準備

建立兩張沒有索引的大表:t1 , t2 ,每張表的資料量接近 350W

test=# create table t2 as select * from t1;
SELECT 3461120

2、測試Delete操作

test=# checkpoint;
CHECKPOINT

test=# select pg_current_wal_lsn(); 
 pg_current_wal_lsn 
-------------------- 0/92DB1FC8 (1 row) test=# select relname,relfilenode from sys_class where relname='t1'; relname | relfilenode ---------+------------- t1 | 16575 (1 row) test=# delete from t1; DELETE 3461120 Time: 4771.554 ms (00:04.772) test=# select pg_current_wal_lsn(); pg_current_wal_lsn
-------------------- 0/C87A2EC0 (1 row) test=# select pg_wal_lsn_diff('0/C87A2EC0','0/92DB1FC8'); pg_wal_lsn_diff ----------------- 899616504 (1 row)
test
=# checkpoint; CHECKPOINT
test=# select relname,relfilenode from sys_class where relname='t1'; relname | relfilenode ---------+------------- t1 |
16575 (1 row)

結論:Delete 操作產生了近900M的日誌;資料檔案的relfilenode 不變。

3、測試Truncate操作

test=# checkpoint;
CHECKPOINT

test=# select relname,relfilenode from sys_class where relname='t2';
 relname | relfilenode 
---------+-------------
 t2      |       16581
(1 row)

test=# select pg_current_wal_lsn(); 
 pg_current_wal_lsn 
--------------------
 0/CAA7C678
(1 row)

test=# truncate table t2;
TRUNCATE TABLE
Time: 84.124 ms

test=# select pg_current_wal_lsn(); 
 pg_current_wal_lsn 
--------------------
 0/CAA82D40
(1 row)

Time: 0.327 ms
test=# select relname,relfilenode from sys_class where relname='t2';
 relname | relfilenode 
---------+-------------
 t2      |       16587
(1 row)

Time: 0.491 ms
test=# select pg_wal_lsn_diff('0/CAA82D40','0/CAA7C678');
 pg_wal_lsn_diff 
-----------------
           26312
(1 row)

Time: 1.239 ms

結論:Truncate 操作基本不產生redo;relfilenode 會變化,這是由於truncate操作相當於新建了個檔案。

三、小資料量刪除操作比較

1、比較一:資料未寫回磁碟前,進行truncate

test=# declare
test-#   v_sql text;
test-# begin
test-#   for i in 1..1000 loop
test-#     drop table if exists t1;
test-#     create table t1 as select * from pg_class;
test-#     delete from t1;
test-#   end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 7173.891 ms (00:07.174)

test=# declare
test-#   v_sql text;
test-# begin
test-#   for i in 1..1000 loop
test-#     drop table if exists t1;
test-#     create table t1 as select * from pg_class;
test-#     truncate t1;
test-#   end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 7477.366 ms (00:07.477)

結論:truncate 似乎更慢。從作業系統IO看,二者的IO 相差不大。

可能原因:truncate 在作業系統層面的操作實際刪除舊檔案,新建新檔案。當呼叫作業系統命令刪除舊檔案時,需要將資料先寫回檔案,才能刪除。而本例中,實際從create table 到truncate 時間很短,資料還未寫回檔案。

2、測試二:先建表,在刪除資料

declare
  v_sql text;
begin
  for i in 1..1000 loop
    v_sql = 'drop table if exists t'||i;
    execute immediate v_sql;
    v_sql = 'create table t'||i||' as select * from pg_class';
    execute immediate v_sql;
  end loop;
end;

checkpoint;

declare
  v_sql text;
begin
  for i in 1..1000 loop
    v_sql = 'delete from t'||i;
    execute immediate v_sql;
  end loop;
end;
/
ANONYMOUS BLOCK
Time: 3412.780 ms (00:03.413)

declare
  v_sql text;
begin
  for i in 1..1000 loop
    v_sql = 'truncate t'||i;
    execute immediate v_sql;
  end loop;
end;
/
ANONYMOUS BLOCK
Time: 1268.753 ms (00:01.269)

結論:先建表,再checkpoint ,將資料寫回資料檔案。然後,再比較Delete 和 Truncate 操作,可以看到即使小表,truncate 操作也快很多。

KINGBASE研究院