PostgreSQL tuple move收缩机制

pg中删除表中记录后,通过vacuum命令可以回收那些dead tulpe占用的空间。那么vacuum具体是怎么回收空间的呢?空间回收之后会影响原先表上索引的正常使用吗?
要弄清楚这些问题,我们那首先要知道在pg中heap page内部的空间分配是什么样的。lp内容即为对应tuple在当前页的OFFSET,lp的位置固定长度固定(固定page head后面就是lp),lp固定方便tuple的搜索(例如ctid的第二个部分就是lp信息)。
lp从page head开始分配,tuple从page tail开始分配,lp指向对应tuple的开始位置。
在这里插入图片描述
例子:
1、创建测试表

bill@bill=>create table c (id int, info text);  
CREATE TABLE

2、安装pageinspect插件

bill@bill=>create extension pageinspect ;
CREATE EXTENSION

3、插入数据

bill@bill=>insert into c select id, repeat(md5(random()::text), 16) from generate_series(1,20) t(id);  
INSERT 0 20

4、查看变长字段大小
每列变长字段大小516字节

bill@bill=>select pg_column_size(repeat(md5(random()::text), 16));  
 pg_column_size 
----------------
            516
(1 row)

5、查看第一页
lp已分配到80字节处
lp offset已分配到576字节处。
剩余只有不到496字节的空间。

bill@bill=>SELECT * FROM page_header(get_raw_page('c', 0));  
     lsn     | checksum | flags | lower | upper | special | pagesize | version | prune_xid 
-------------+----------+-------+-------+-------+---------+----------+---------+-----------
 19/1621C910 |        0 |     0 |    80 |   576 |    8192 |     8192 |       4 |         0
(1 row)

6、查看每一条记录tuple在page内部的offset

bill@bill=>select lp,lp_off from heap_page_items(get_raw_page('c', 0));  
 lp | lp_off 
----+--------
  1 |   7648
  2 |   7104
  3 |   6560
  4 |   6016
  5 |   5472
  6 |   4928
  7 |   4384
  8 |   3840
  9 |   3296
 10 |   2752
 11 |   2208
 12 |   1664
 13 |   1120
 14 |    576
(14 rows)

7、删除13条记录

bill@bill=>delete from c where ctid not in ('(0,1)','(0,3)','(0,5)','(0,7)','(0,9)','(0,11)','(0,13)');
DELETE 13

8、查看lp信息和lp offset信息,现在还没有垃圾回收掉。

bill@bill=>select lp,lp_off from heap_page_items(get_raw_page('c', 0));                                
 lp | lp_off 
----+--------
  1 |   7648
  2 |   7104
  3 |   6560
  4 |   6016
  5 |   5472
  6 |   4928
  7 |   4384
  8 |   3840
  9 |   3296
 10 |   2752
 11 |   2208
 12 |   1664
 13 |   1120
 14 |    576
(14 rows)

9、vacuum回收

bill@bill=>vacuum VERBOSE c;
INFO:  vacuuming "bill.c"
INFO:  "c": removed 13 row versions in 2 pages
INFO:  "c": found 13 removable, 7 nonremovable row versions in 2 out of 2 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 12076871
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO:  "c": truncated 2 to 1 pages
DETAIL:  CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
INFO:  vacuuming "pg_toast.pg_toast_226382"
INFO:  index "pg_toast_226382_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO:  "pg_toast_226382": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 12076872
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM

10、再次查看lp信息和lp offset信息
垃圾回收后,lp信息都还在,但是,请注意lp里面存储的offset发生了变化,被回收的tuple,发生了MOVE,变紧凑了,并没有出现空洞。
被删除的tuple对应的lp, offset全部变成了0。

bill@bill=>select lp,lp_off from heap_page_items(get_raw_page('c', 0));  
 lp | lp_off 
----+--------
  1 |   7648
  2 |      0
  3 |   7104
  4 |      0
  5 |   6560
  6 |      0
  7 |   6016
  8 |      0
  9 |   5472
 10 |      0
 11 |   4928
 12 |      0
 13 |   4384
 14 |      0
(14 rows)

11、插入一条新记录后查看
2号lp被用起来了,OFFSET到了2312字节。

扫描二维码关注公众号,回复: 11017906 查看本文章
bill@bill=>insert into c select 100, repeat(md5(random()::text), 60);
INSERT 0 1
bill@bill=>select lp,lp_off from heap_page_items(get_raw_page('c', 0));  
 lp | lp_off 
----+--------
  1 |   7648
  2 |   2432
  3 |   7104
  4 |      0
  5 |   6560
  6 |      0
  7 |   6016
  8 |      0
  9 |   5472
 10 |      0
 11 |   4928
 12 |      0
 13 |   4384
 14 |      0
(14 rows)

总结:
1、垃圾回收时,lp本身不变,这样索引可以保持不变。
2、页内move row , 只是lp offset 变化, 好处是PAGE内部不会膨胀,提高空间利用率。

发布了159 篇原创文章 · 获赞 92 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/105663848