标签
PostgreSQL , Greenplum , 垃圾回收 , vacuum
背景
在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时,只有仅仅包含左右链接的页(即没有实际引用的页)可以拆除复用。并且索引文件大小不会变化。
索引结构可以参考
只有重建索引才能收缩索引大小。
使用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可以回收垃圾,但是不收缩文件。
如果有维护窗口,还是建议使用这种方法来回收空间。