暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

openGauss行存储的空间回收

openGauss小助手 2021-10-25
744

通过上述章节所介绍的行存储的多版本管理机制,可以发现由于更新和删除并不实际在页面中删除页面本身,数据库长时间运行后,会有大量的历史版本残存在存储空间中,造成了空间的膨胀。为了解决这一问题,存储引擎内部需要定期的对历史数据进行清理,以保证数据库的健康运行。

行存储对于存储空间的清理存在于多个层面、有多种方式。其中在页面一级的机制,成为heap_page_prune。顾名思义,就是在页面内部进行空间的清理。这种清理模式能够比较好的解决更新多版本带来的同一个数据记录关联的长长的历史版本堆叠、标记删除的记录以及无效的记录。这种pruning的手段在对页面进行读取的过程中由页面的空闲空间阈值触发,仅改动heap页面本身,不对索引页面进行改动。因此heap_page_prune是一种较为轻量化的清理方式。举例如下:

如有一个记录a,被前后更新导致同时有6个历史版本,保存于两个不同的页面中,如图9-16所示。

图9-16 记录a的6个历史版本

page页面级别的自我清理效果为图9-17所示。

图9-17 page页面级别的自我清理

可以看到,清理过程中分别对page1和page2中的内容进行了回收,但是由于之前的跨页面导致的两个索引entry指向不同页面,却被保留了下来。

在页面级别的清理之外,还有表级别、数据库级别的整体清理,这个机制称之为Vacuum操作。Vacuum操作在整个数据库级别进行废旧元组的清理,同时也会清理索引。Vacuum操作可以由数据库用户对数据库或数据库内对象主动调起,同时数据库后台也会有工作线程在满足阈值时或者定期进行数据库自动的Vacuum。如图9-18所示。

图9-18 Vacuum操作

Vacuum自身除了清理空间外,也顺带圣诞了更新统计信息的功能,以便优化器能更准确的进行代价估算。

Vacuum在过程中,还会对整个数据库级别都可见的元组进行freeze操作。举例来说,当一个元组被插入并提交,而后续没有更新操作,数据库系统上也不再有早于这个提交的事务时间点、需要对这条元组做可见性判断的事务,此时认为此元组就可以被任何人看见了,那么其相关的事务ID就可以被转化为一个特殊的事务ID——Freeze Xid,以表示这种状态。当Vacuum清理整个系统时,系统中最小活跃事务之前的提交日志(Clog),也同上面说到的,不在被需要,因此Vacuum操作也会对这部分Clog日志进行清理和回收。

当然,Vacuum本身是一个相对高成本的操作,因此,每个表文件会有一个对应的可见性映射(visibility map),来记录这个表数据文件中对应的页面是否已经处于全部可见状态,这种情况下Vacuum在执行过程中就可以跳过这部分页面,节省开销。由于一般系统中存储的绝大部分数据都不与当前活跃事务相关,因此此优化可以大大提升Vacuum的效率。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论