Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6270827
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: Mysql/postgreSQL

2013-08-20 11:05:58

原文地址:PostgreSQL存储空间回收 作者:skykiker

1.概述 

随着数据库的运行,存储空间里会产生一些无用的数据,需要进行清理。
产生这些无用数据的原因有:
? 行被删除
? 插入行的事务终止
? 由更新产生的旧的行版本

需要回收的存储空间主要包括以下几个方面:
? 行版本(占用空间最大)
? 行版本指针(占用空间最小)
? 索引项

 

2.回收方法

2.1 表的单页清理

通过SELECT,UPDATE和DELETE访问表时,会触发表的单页清理。清理对象仅限于被废弃的行版本(对任何事务都不可见)。同时标记行版本指针为Dead状态。下次执行vacuum时,会回收不用的索引项和行版本指针。

删除前: 



删除后:


*)行版本指针共有4个状态,存储在lp_flags域:
Unused
Normal
Redirect
Dead

2.2 vacuum


通过vacuum或autovacuum清理时,被废弃的行版本,行版本指针和索引项都会得到清理。普通的vacuum不会释放存储空间给OS,除非在表文件的末尾有连续的空页。vacuum full会将整个数据重写一遍,仅保留有用的数据。vacuum full时要锁住整个表,会影响其它并发作业。

vacuum后:



3.更新的优化

满足以下条件时,采用称之为HOT(heap-only tuples)更新的技术提高性能。
1)新旧行版本存储在同一个页上
2)更新不涉及被索引列值的变更
通过行版本头部的ctid或者行版本指针的lp_flags(Redirect)+lp_off让旧版本指向新版本,形成一个HOT更新链。这样在更新时就可以重用原来的索引项,避免删除和追加索引项。索引项仍然指向旧的行版本指针,然后通过HOT更新链找到对应的新版本。
使用ctid或lp_flags(Redirect)+lp_off形成HOT更新链的区别在于:前者保留了旧的行版本,而后者用于旧的行版本已被回收的情况。当旧的行版本对某些活动事务仍然可见时,是不能被回收的。HOT更新时对于处于HOT更新链中间位置的行版本指针是可以被立即回收的(头指针被索引使用,尾指针指向最新的行版本,所以要保留)。

初始状态:只有一个版本


第一次更新:通过旧行版本头部的ctid指向新行班本


第二次更新:V1的行版本空间被再利用。并且通过Redirect将索引使用的第一个行版本指针引向保留下来的最老的行版本。


第三次更新:


最终由于其他操作触发废弃的行版本被回收:


4.性能提示


为了能让HOT更新充分发挥作用,需要尽量减少不必要的索引,并合理设置表的存储参数fillfactor。
fillfactor控制插入时页存储空间的使用率,取值范围为10%~100%,缺省值为100,即不为HOT更新保留空间。
对于频繁更新非索引列的表,应该将fillfactor适当设小。

5.参考


阅读(705) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~