Greenplum vacuum ao表和heap表的区别

less than 1 minute read

背景

在Greenplum中删除、更新数据记录时,会产生新的tuple版本,老的版本通过行头部标记:为已删除以及被哪个事务删除的。

因此频繁的更新后,或者批量的删除数据后,需要回收那些旧的版本。

通过vacuum、vacuum full、alter table redistribute命令,可以回收垃圾。

《如何检测、清理Greenplum垃圾 - 阿里云HybridDB for PG最佳实践》

但是回收AO表与回收HEAP表有些许不一样的地方,因为它们的存储方式有差异。

vacuum ao表

ao表为追加存储,当删除、更新记录时,有一个BITMAP对象来存储对应的记录是否被删除。

每个AO表的每个数据文件对应一条BITMAP信息,每个BIT位对应这个数据文件的一行。

使用vacuum回收AO表的垃圾时,实际上是这样操作的:

1、扫描bitmap,如果发现这个数据文件中被标记为删除的BIT总数大于某个阈值,则收缩这个文件。(每个数据文件默认1GB)

2、收缩这个文件时,因为会导致记录的物理位置编号,所以需要变更对应的索引(可能导致索引膨胀)。

vacuum ao表时,允许INSERT,COPY写入数据,但是不允许UPDATE和INSERT操作。(GPDB中UPDATE和DELETE是锁全表的,另一方面引入了update和delete后AO表收缩会变得更加复杂。)

3、VACUUM对应的索引,索引VACUUM时,只有仅仅包含左右链接的页(即没有实际引用的页)可以拆除复用。并且索引文件大小不会变化。

索引结构可以参考

《深入浅出PostgreSQL B-Tree索引结构》

只有重建索引才能收缩索引大小。

使用alter table redistribute命令,本质上也是需要重建索引的。

vacuum heap表

vacuum heap表,扫描所有数据文件,同时抹除BLOCK内dead tuple的item和tuple占用的空间,同时抹除对应索引ITEM。物理文件大小不会变化,(除了最后一个文件的末尾的没有任何有效记录的块。)

其他因素

vacuum 能回收的垃圾,不能被其他事务依赖。目前PG是这样来判断的,垃圾版本大于当前集群中最老事务的快照号的,都不能被回收。

《PostgreSQL垃圾回收代码分析 - why postgresql cann’t reclaim tuple is HEAPTUPLE_RECENTLY_DEAD》

小结

1、Greenplum ao表使用vacuum可以回收部分垃圾(并收缩文件大小)(当某些数据文件垃圾记录超过一定设定比例时),VACUUM时堵塞UPDATE和DELETE,但是不堵塞INSERT。收缩文件大小,可能导致索引膨胀。

2、HEAP表vacuum可以回收垃圾,但是不收缩文件。

如果有维护窗口,还是建议使用这种方法来回收空间。

《如何检测、清理Greenplum垃圾 - 阿里云HybridDB for PG最佳实践》

Flag Counter

digoal’s 大量PostgreSQL文章入口