PostgreSQL 学习篇— PG 表膨胀

数据库 PostgreSQL
有一种表膨胀情况比较难处理,autovacuum自动清理死元组速度赶不上生成速度。因为update、 insert、delete事务并发太多,这次的vacuum还没来得及清理出之前的可用空间,就有大量update生成新的空间和死元组,导致表不断膨胀。​

PG表膨胀原因

PG特殊的MVCC机制,delete不会真的删除元组,update相当于delete+insert,旧元组本身不能通过DML语句来删除,这样就只有“涨”空间没有“清理”空间,这就是表膨胀。

此时一般需要vacuum来清理死元组,把空间标记为可用,下次写入时可以用到这部分空间;或者vacuum full等方式重写表,让表变得更加紧凑。

场景复现

OS:CentOS 7.6  

db版本:PG 14.2 

表名: cmdb_objects

图片图片

表结构:

图片图片

我先插入两条数据,然后进行循环插入,只有object_type字段数据不同,用于后续做更新操作。

insert into cmdb_objects values ('xgrdb','xgr','test67','index');
insert into cmdb_objects values ('xgrdb','xgr','test67','table');
insert into cmdb_objects select * from cmdb_objects;

现在该表中存在32768条数据,再进行update更新操作:

update cmdb_objects set object_type='view' where object_type='table';

图片图片

更新后该表会存在16384死行,如业务数据量大,且有频繁的更新操作,该表就会产生高水位。可通过pg_stat_all_tables视图来查询该表中存在的死行、活跃行数。

select relname,n_live_tup,n_dead_tup from pg_stat_all_tables where relname='cmdb_objects';

图片图片

处理方式

第一种处理方法vacuum:

把表中的dead tuples进行标记删除,并没有真正的物理删除,表的实际使用空间没有减小,只是将dead tuples的航空件转换为可以使用的状态,vacuum过程中,可以正常访问表数据,不锁表。

图片

你也可以在执行碎片清理时收集统计信息:

vacuum(verbose,analyze) test;

16384死行已被删除(该方式适用于实时更新的,更新数据量不大的表,可以每天进行批量操作)。

第二种处理方法vacuum full:

物理删除表中的dead tuples,释放空间给操作系统;vacuum full过程中,表被锁定,不允许访问。

图片图片

执行前表大小如下:

图片图片

执行vacuum full:

图片图片

执行后表大小:

可以看到该表的使用空间已被物理删除释放。(该方式通过重建表,回收所有碎片空间,适用于经常进行大批量更新数据的表,定制策略进行执行,也可以在维护时间业务表每周执行一次。)

总结一下vacuum 与 vacuum full的区别:

  • Vacuum不会阻塞查询和DML业务;不会立即回收空间,只是把空间标记为可用,降低高水位;如果表的最后一个page没有元组了,这个page会被truncate。
  • Vacuum ful8级锁,阻塞一切;表完全重写,操作系统上对应的文件会被清理和重建;重建索引、FSM(可用空间文件)、VM (page可见性文件);会创建一个副本表,该表使用的磁盘空间最大可能翻至2倍,磁盘空间不足,谨慎执行。

第三种处理方法autovacuum参数控制:

图片图片

autovacuum是postgres里面一个服务端进程,可在一定条件下自动触发执行。

该参数值默认为 on(开启全局自动),主要作用包括:

  • 清理死元组(UPDATE或DELETE操作后留下的),并对表进行分析;
  • 更新可用空间映射(free space map),以跟踪表块中的可用空间;
  • 更新仅索引扫描所需的可见性图(visibility map);
  • 冻结(freeze)表行,以便事务ID计数器可以安全地环绕。

表膨胀的危害:

  • 表占用过大的空间;
  • 进而引起sql性能降低;
  • 表过大会也会导致vacuum清理时间变成长;vacuum full阻塞时间也会变长,不过可以通过pg_repack来代替vacuum full,减少阻塞时间。

以上操作都会增加cpu与io的资源消耗。

补充:有一种表膨胀情况比较难处理,autovacuum自动清理死元组速度赶不上生成速度。因为update、 insert、delete事务并发太多,这次的vacuum还没来得及清理出之前的可用空间,就有大量update生成新的空间和死元组,导致表不断膨胀。

责任编辑:武晓燕 来源: IT那活儿
相关推荐

2024-11-13 08:00:00

PostgreSQ插件开发

2011-08-25 09:56:05

PostgreSQLpg_ident.co

2011-08-23 10:54:16

PostgreSQL表空间用户

2022-12-26 08:07:03

MySQL批量数据

2018-05-23 13:47:28

数据库PostgreSQL查询优化

2011-08-24 13:37:33

PostgreSQLpg_hba.conf

2018-05-25 15:04:57

数据库PostgreSQL查询优化器

2017-08-30 16:59:54

PostgreSQL分区表

2024-05-10 07:51:08

PostgreSQL临时表空间

2021-12-28 16:33:26

接口函数组合

2011-03-24 14:40:29

PostgreSQL数管理

2011-02-24 15:04:00

PostgreSQL数据库psql

2021-08-10 15:44:37

PostgreSQL表分区分区表

2011-05-23 18:01:19

外链

2021-08-03 07:40:46

Synchronize锁膨胀性能

2011-08-23 09:54:31

路由路由表路由器

2021-07-02 09:45:29

MySQL InnoDB数据

2018-04-23 10:16:29

JavaJavaWeb语言

2015-07-16 15:04:07

sail.js

2024-03-04 09:29:57

PostgreSQL数据库RDBMS
点赞
收藏

51CTO技术栈公众号