KingbaseESV8R6 heap table末端垃圾页回收机制

发布时间 2023-06-06 15:38:02作者: KINGBASE研究院

前言

默认情况下,vacuum表不能释放磁盘空间,只是在dead tuple做个标记位,但heap table末端的垃圾页可以被truncate,从磁盘中释放空间。例如表的末尾的100个数据块里面全是垃圾,那么这100个数据块可以truncate阶段,文件也会变小。而位于其他位置的垃圾页,不能回收,因为会影响寻址(ctid)的变化,而末尾全垃圾的页被截断时不影响寻址。但是KingbaseESV8R6开始,这个截断动作可以被控制,如果表的参数vacuum_truncate设置为false,那么末尾的垃圾页不会被回收。

有这样一个例子,一些表还会往里面写入大量数据时,没有必要回收,因为extend block也是有锁的,还有收缩文件需要对表加access exclusive lock,那么会产生锁冲突,这时候可以将vacuum_truncate设置为false。

vacuum_truncate controls whether vacuum tries to truncate off any empty pages at the end of the table. Previously vacuum always  tried to do the truncation. However, the truncation could cause  some problems; for example, ACCESS EXCLUSIVE lock needs to  be taken on the table during the truncation and can cause  the query cancellation on the standby even if hot_standby_feedback  is true. Setting this reloption to false can be helpful to avoid  such problems.  

例子

1、创建两张表,表u1的vacuum_truncate设置为false,表u2使用默认参数。

test=# create table u1(id int,info text) with(vacuum_truncate=false);
CREATE TABLE
test=# create table u2(id int,info text);
CREATE TABLE

2、插入数据,查看表大小

TEST=# insert into u1 select generate_series(1,100000),md5(random()::text);
INSERT 0 100000
TEST=# insert into u2 select generate_series(1,100000),md5(random()::text);
INSERT 0 100000
TEST=# \dt+ u1;
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+--------+---------+-------------
public | u1 | table | system | 6760 kB |
(1 row)

TEST=# \dt+ u2;
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+--------+---------+-------------
public | u2 | table | system | 6760 kB |
(1 row)

3、删除末端数据,对比观察表大小是否变化
可以看到u2表末端的空间被回收了,而u1表大小不变。

TEST=# delete from u2 where id <> 1;
DELETE 99999
TEST=# vacuum u2;
VACUUM
TEST=# \dt+ u2
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+--------+-------+-------------
public | u2 | table | system | 48 kB |
(1 row)

TEST=# delete from u1 where id <> 1;
DELETE 99999
TEST=# vacuum u1;
VACUUM
TEST=# \dt+ u1
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+--------+---------+-------------
public | u1 | table | system | 6768 kB |
(1 row)

启用或禁用真空以尝试截断此表末尾的所有空白页。默认值为true。如果为true,则VACUUM和autovacuum执行截断操作,并将截断页面的磁盘空间留给操作系统。但是,截断需要表上的访问独占锁。这可能会阻塞查询操作。
注意:如果vacuum_truncate为true,在vacuum 时会尝试获取ACCESS EXCLUSIVE lock,如果无法取得 ACCESS EXCLUSIVE lock , 则跳过,不会进行trucate 操作。