1.什么是表膨胀
表膨胀是指表的数据和索引所占文件系统的空间,在有效数据量并未发生大的变化的情况下,不断增大。久而久之,关系文件被大量空洞填满,浪费了大量的磁盘空间。甚至某些特殊场景下。一个表中只有一条简单的数据,但是表对应的物理文件可能已经达到M级甚至G级。
2.表膨胀危害
·空间持续上涨,到达某一个点后,需要执行一个高额代价的vacuum full(或者custer等可以重组表的命令),但vacuum full又是AccessExclusiveLock,最高级别的锁,会阻塞一切访问,意味着在完成清理重组之前,都无法访问该表。
·扫描的效率变低,即使所有记录都是dead状态,PostgreSQL的顺序扫描也会扫描对象所有的老版本,直到执行vacuum将dead的记录删除。
3.为什么会表膨胀
postgresql mvcc :写新数据时,旧数据不删除,而是把新数据插入,将旧数据标记为无效,PostgreSQL就是使用的这种实现方法,新老数据存放在一起,在被清理之前,会一直占据着空间,所以会导致膨胀。
4.表膨胀产生的原因
vacuumlazy.c 中的函数TransactionldPrecedes
用于判断两个事务的大小,xmax就是删除、更新时的事务ID,oldestXmin是活动事务中最小的事务ID。 这个函数的逻辑是,如果 oldestXmin< xmax,则返回 HEAPTUPLE RECENTLY DEAD,意味着保留此Tuple,不去进行删除。最关键的就是长事务。
如果系统中含有很久之前开启而未提交的事务,并且这个事务由于执行过更新,创建了事务ID,那么计算出来的OldestXmin会非常小,vacuum做上述这个判断时,结果通常为true,即返回HEAPTUPLE RECENTLY DEAD,这样就会保留此tuple(旧版本),导致回收无法完成,表膨胀由此发
typedef enum 元组的状态:
HEAPTUPLE_DEAD /* 元组是死的和可删除的 /
HEAPTUPLE_LIVE, / 元组处于活动状态 (已提交,没删除)/
HEAPTUPLE_RECENTLY_DEAD / 死元组,但是不能删除 */
HEAPTUPLE_INSERT_IN_PROGRESS /插入xact仍在进行中/
HEAPTUPLE_DELETE_IN_PROGRESS /*正在删除xact *
5.表膨胀的优化建议
·一定要开启autovacuum。
·提高系统的IO能力,越高越好。
·设置idle in transaction session timeout参数,控制长事务的存活时间
·对于大表,建议使用分区,可以加快vacuum的速度。
·应用程序设计时,避免使用大批量的更新,删除操作,可以切分为多个事务进行。
6.普通的vacuum
·清除UPDATE或DELETE操作后留下的"死元组"
·跟踪表块中可用空间,更新free space map
·更新visibility map,index only scan以及后续vacuum都会利用到
·"冻结"表中的行,防止事务ID回卷
·配合ANALYZE,定期更新统计信息
7.vacuum full
vacuum full会对表进行重组,也就意味着表的oid会变,所以不能我们在日常操作中,要定位表的oid的时候,不能通过pg class的oid来找,得通过pgclass的relfilenode来找,这样才精确。而且,vacuum full最大会占据原来磁盘空间的两倍。
vacuum full或者cluster等可以重组表的方式,不过都是8级锁,access exclusive lock,会阻塞一切访问,重组表,意味着表在磁盘上的物理位置会发生改变,同时最多会使用两倍表空间的存储大小。
标签:事务,full,postgresql,删除,HEAPTUPLE,vacuum,膨胀,优化 From: https://blog.51cto.com/u_11103985/8441175