不可忽视的PG表膨胀优化

我是一个目录

  • 案例
  • 1. 什么是表膨胀?
  • 2. 表膨胀危害是什么?
  • 3. 表膨胀是怎么产生的?
  • 4. 如何优化膨胀表?


案例

先来看一例公有云服务登录web页面端卡住案例:
故障现象:WEB端登录非常缓慢,需要耗时5~10分钟才能登录,登录成功之后,就不卡了;
排查过程:网络正常,服务器资源正常,数据库层发现慢SQL
一条简单的查询select 居然耗时了150s
故障原因:根据慢SQL定位到功能点是Web端在登录时权限校验用户组织权限表t_pm_user引起的缓慢,查询该表数据量很小,只有1600行,查询表大小,发现表居然有4GB左右;表膨胀率达1526倍。
表中死元组过多,现在就明确了问题就是该表膨胀导致的。经过了解业务发现:客户配置了每小时一次人员增量同步,每次同步都update表,由于同步频率高,导致表膨胀厉害。

解决办法:
vacuum full 表并设置该表的回收阈值,并反馈研发优化这个功能点


1. 什么是表膨胀?

表膨胀是指表的数据和索引所占文件系统的空间,在有效数据量并未发生大的变化的情况下,不断增大。表膨胀不仅浪费了大量的磁盘空间,甚至某些查询场景下,导致表扫描耗时长,影响查询语句效率。就如上述例子中的表t_pm_user,仅有1600多行数据,但是表对应的物理文件已经4GB。

2. 表膨胀危害是什么?

  1. 空间持续上涨,影响查询效率。当dead tuple到达某一个临界点后,需要执行一个高额代价的vacuum full清理膨胀表,但vacuum full又是AccessExclusiveLock,8级锁,会阻塞一切访问,意味着在完成清理重组之前,都无法访问该表。
  2. 扫描的效率变低,即使所有记录都是dead状态,PostgreSQL的顺序扫描也会扫描对象所有的老版本,直到执行vacuum将dead tuple的记录删除;

3. 表膨胀是怎么产生的?

PG数据库的表膨胀是基于MVCC的存储机制:

  • 插入很简单,就是将元组插入到页面的空闲空间中;
    在这里插入图片描述
  • 删除则是将元组标记为旧版本,但是即使这个旧版本对所有事务都不可见了,这个元组占用的空间也不会归还给文件系统。
    在这里插入图片描述
  • UPDATE相当于DELETE + INSERT,等于是占用了两条元组的位置,类似DELETE,旧版本的元组依然占用着物理空间。
    在这里插入图片描述
    很明显,如上图所示,在一通增删改(insert、update、delete)操作之后,页面上的旧版本元组(dead tuple)势必是占有一定比重的,这就导致了物理文件大小明显高于实际的数据量。
    为此,PostgreSQL引入了vacuum的机制,去清理那些不再需要的死元组。
  • autovacuum;
  • vacuum tablename;
  • vacuum full tablename;

普通的vacuum会做大概如下几件事情:

  1. 清除UPDATE或DELETE操作后留下的"死元组"
  2. 跟踪表块中可用空间,更新free space map
  3. 更新visibility map,index only scan以及后续vacuum都会利用到
  4. "冻结"表中的行,防止事务ID回卷
  5. 配合ANALYZE,定期更新统计信息

可以看到,普通的vacuum只是清理死元组,"腾出"空间,在今后有新数据插入时,将优先使用该空间,直到所有被重用的空间用完时,再考虑新增页面。
在这里插入图片描述
如上图所示,普通vacuum只是标记了dead tuple,并未重组页面,导致上图3个页面使用率特别低,每个页面仅存放1个tuple,而且在某些情况下,每个页面的空闲空间又不是固定大小的,所以如果要利用这些空间空间,就需要遍历一遍数据页面来找到它们,这样会造成比较大的I/O开销,表膨胀越大,开销就越大。

因此,PG就引入vacuum full这个操作,vacuum full会对表进行重组,也就意味着表的oid会变,所以不能我们在日常操作中,因此它需要lock table,而且要定位表的oid的时候,不能通过pg_class的oid来找,得通过pg_class的relfilenode来找,这样才精确。而且,vacuum full最大会占据原来磁盘空间的两倍,所以请预留好磁盘空间。
在这里插入图片描述
既然已经了解了PG的膨胀原理,PG数据库也引入了autovacuum,为什么还是会有膨胀表存在呢?有以下几种可能性导致膨胀表不能被清理:

  • autovacuum不给力
  • 服务器IO差
  • 数据库长期存在长事务,数据库中存在长SQL或带XID的长事务。之后产生的死元组都无法被清理
  • autovacuum launcher process 的调度周期太长
  • 存在失效的复制槽,复制槽通常用于逻辑复制、CDC和物理复制等场景下
  • 开发游标未及时关闭,游标未关闭会导致backend_xmin一直持续到事务结束,产生的死元组无法回收;

4. 如何优化膨胀表?

步骤1:获取膨胀表及膨胀索引数据
使用上面这2个视图可以获取当前数据库里的膨胀表及索引情况;可以根据膨胀率进行筛查,及时处理优化膨胀表。
步骤2:处理表膨胀
常用手段:

  • 使autovacuum加快速度干活
    使用场景:根据服务器配置调整PG参数,加快autovacuum效率
    相关参数默设置参考:
    autovacuum_max_workers:=3
    一次可以运行的autoacuum进程数量
    autovacuum_vacuum_cost_limit = -1 (So, it defaults to vacuum_cost_limit) = 200
    (清理作业总成本控制)
    autovacuum_vacuum_cost_delay = 20ms
    (当一个清理工作达到autovacuum_vacuum_cost_limit指定的成本限制时,autovacuum将休眠数毫秒)
    vacuum_cost_page_hit = 1
    (读取已在共享缓冲区中且不需要磁盘读取的页的成本)
    vacuum_cost_page_miss = 10s
    (获取不在共享缓冲区中的页的成本)
    vacuum_cost_page_dirty = 20
    (在每一页中发现死元组时写入该页的成本,清理成本)
  • 监控长事务
  • 单独小表设置vacuum阈值
    使用场景:数据变化快、增、删、改频繁的小表;
    设置:例如:表T被更新的元组数阈值超过1000或10%,并进行cost评估,低于1000,就执行 vacuum 和 analyze;
ALTER TABLE t SET (autovacuum_vacuum_threshold = 1000);
ALTER TABLE t SET (autovacuum_vacuum_scale_factor = 0.1);--表大小的缩放系数;
ALTER TABLE t SET (autovacuum_vacuum_cost_limit = 1000);---对 vacuum 执行 cost 进行评估,限制在1000,超过就延迟;
ALTER TABLE t SET (autovacuum_vacuum_cost_delay = 10);--延迟的时间即为10ms
  • 手动vacuum full 表
    根据上一步骤找出来的膨胀表,在非业务时段进行vacuum full tablename; 此操作需要lock table,8级别锁,针对特别大的表,评估是否需要做此类操作。对于大表,建议使用分区,可以加快vacuum的速度。

  • 膨胀索引在线重建
    在比较繁忙的系统或者大表上执行该语句的话,可以使用concurrently 参数:
    create index concurrently idx_table_name_x1 on table_name(col_name);

  • 插件处理
    pg_repack
    pg_sequeeze

  • 优化应用程序设计
    应用程序设计时,尽量避免如下:

    • LONG SQL(包括查,增,删,改,DDL所有的SQL)
    • 打开游标后不关闭
    • 在不必要的场景使用repeatable read或serializable事务隔离级别
    • 对大的数据库执行pg_dump进行逻辑备份(隐式repeatable read隔离级别的全库备份),长时间不关闭申请了事务号的事务(增,删,改,DDL的SQL),还包括2PC

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/83582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AD】【PCB封装规范计划】 -CON排针类

像这种CON,排针的。画PCB封装的时候,要把数字用丝印标出来!!!

如何使用 Node.js和Express搭建服务器?

如何使用NodeJs搭建服务器 1. 准备工作1.1 安装Node.js 2. 安装express2.1 初始化package.json2.2 安装express2.3 Express 应用程序生成器 1. 准备工作 1.1 安装Node.js Node.js 是一个开源、跨平台的 JavaScript 运行时环境。 下载链接:Node.js官网下载 建议下…

Java面试常用函数

1. charAt() 方法用于返回字符串指定索引处的字符。索引范围为从 0 到 length() - 1。 map.getOrDefault(num, 0) :如果map存在num这个key,则返回num对应的value,否则返回0. Arrays.sort(nums); 数组排序 Arrays.asList("a","b",&q…

Xilinx ZYNQ 7000学习笔记五(Xilinx SDK 烧写镜像文件)

概述 前面几篇讲了ZYNQ7000的启动过程,包括BootRom和FSBL的代码逻辑,其中关于FSBL代码对启动模式为JTAG被动启动没有进行分析,本篇将通过将JTAG的功能和通过Xilinx SDK烧写镜像文件到flash来顺道把FSBL中的JTAG代码部分给讲解下。 1.JTAG …

NuttX实时操作系统介绍(最详细)

比起安卓、iOS、鸿蒙等,NuttX知名度不算高,该系统于2007年由Gregory Nutt先生正式开源。发展至今,NuttX以功能丰富、性能稳定、商业化成熟度高赢得了市场的认可。 NuttX是一个成熟的实时操作系统,于07年由Gregory Nutt先生正式开源…

学习笔记-接口测试(postman、jmeter)

目录 一、什么是接口测试 二、前端和后端 三、get请求和post请求的区别 四、cookie和session 五、接口测试的依据 六、HTTP状态码 七、通用接口用例 八、postman接口测试 九、Jmeter接口测试 一、什么是接口测试 通常做的接口测试指的是系统对外的接口,比…

机器学习:PCA(Principal Component Analysis主成分)降维

参考:PCA降维原理 操作步骤与优缺点_TranSad的博客-CSDN博客 PCA降维算法_偶尔努力翻身的咸鱼的博客-CSDN博客 需要提前了解的数学知识: 一、PCA的主要思想 PCA,即主成分分析方法,是一种使用最广泛的数据降维算法。PCA的主要思想…

【element-ui】el-date-picker 之picker-options时间选择区间禁用效果的实现

element-ui 时间选择器的时间区间禁用dom层引入:picker-option <el-date-pickerv-model"searchFormObj.workTime"clearablevalue-formate"yyyy-MM-dd":picker-options"pickerOptions"placeholder"请选择时间" ></el-date-pi…

基于深度强化学习的四旋翼无人机航线跟随

源自&#xff1a;指挥与控制学报 作者&#xff1a;杨志鹏 李波 甘志刚 梁诗阳 “人工智能技术与咨询” 发布 摘 要 针对无人机在空中执行航线跟随任务时无法对未知环境作出合理应对措施等问题, 提出了一种基于深度强化学习的四 旋翼无人机航线跟随方法. 通过无人机受力…

SpringMVC之JSON数据返回与异常处理机制---全方面讲解

一&#xff0c;JSON数据返回的理解 在Spring MVC中&#xff0c;当需要将数据以JSON格式返回给客户端时&#xff0c;可以使用ResponseBody注解或RestController注解将Controller方法的返回值直接转化为JSON格式并返回。这使得开发者可以方便地将Java对象转换为JSON&#xff0c;并…

【C++】STL之vector操作

文章目录 简介vector中的成员类型模板参数头文件的包含构造函数vector的访问方式&#xff1a;下标[ ]迭代器范围for 交换swap 简介 vector是stl中的一种数组容器&#xff0c;vector在英文中有矢量的意思&#xff0c;但实际上在数据结构中就是一种类似于数组的结构&#xff1b;…

AI大模型服务应用场景

大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域&#xff0c;大模型通常是指具有数百万到数十亿参数的神经网络模型。这些模型通常在各种领域&#xff0c;例如自然语言处理、图像识别和语音识别等&#xff0c;表现出高度准确和广泛的泛化能力。伴随…

Jmeter系列-定时器Timers的基本介绍(11)

简介 JMeter中的定时器&#xff08;Timer&#xff09;是一种重要的元件&#xff0c;用于模拟用户在不同时间间隔内发送请求的场景。通过使用定时器&#xff0c;可以模拟负载、并发和容量等不同情况下的请求发送频率。 使用定时器 可以在取样器下添加定时器&#xff0c;这样定…

MySQL日常使用记录

1.时间 1.1.时间格式化 yyyy-MM-dd HH:mm:ss格式&#xff0c;如下&#xff1a; select date_format(now(), %Y-%m-%d %H:%i:%s) from dual;date_format函数是将date类型按照指定的格式转换成varchar类型 1.2.日期加减 当前天 1 天 select date_format(now(), %Y-%m-%d), …

持安科技孙维伯:零信任理念下的实战攻防:ISC2023数字小镇演讲

近日&#xff0c;在ISC 2023第十一届互联网安全大会上&#xff0c;持安科技联合创始人孙维伯作为零信任办公安全赛道代表&#xff0c;亮相数字小镇New50&#xff0c;并发表《全方位防御&#xff1a;零信任理念下的实战攻防》主题演讲。 以下是本次演讲实录&#xff1a; 这几年…

系统灰度随笔记

系统灰度随笔记 这段时间系统重构&#xff0c;负责重构的其中一个模块需要与四个上游系统对接进行切换&#xff0c;虽然自己在这个过程中也设计了一套灰度方案来承接&#xff0c;将灰度的主动权控制在下游&#xff0c;但是很难同时应对四个上游系统&#xff0c;因为每个上游系…

Redis的介绍以及简单使用

Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据存储系统&#xff0c;它以键值对的形式将数据存在内存中&#xff0c;并提供灵活、高性能的数据访问方式。Redis具有高速读写能力和丰富的数据结构支持&#xff0c;可以广泛应用于缓存、消息队列、实…

vue的由来、vue教程和M-V-VM架构思想、vue的使用、nodejs

vue vue的由来 vue教程和M-V-VM架构思想 vue的初步简单使用 nodejs vue的由来 # 1 HTML(5)、CSS(3)、JavaScript(ES5、ES6、ES11)&#xff1a;编写一个个的页面 -> 给后端(PHP、Python、Go、Java) -> 后端嵌入模板语法 -> 后端渲染完数据 -> 返回数据给前端 ->…

ATLAS 200通过PCIE 接入RK3588-EP模式

ATLAS 200 作为算理模块&#xff0c;可以作为主/协处理器接入RK3588,有两种模式&#xff1a;RC 模式和EP模式 RC模式&#xff1a;rk3588 和 ATLAS 200 可分别独立处理自身业务数据&#xff0c;不存在业务互相依赖&#xff0c;二者可通过网络等方式进行通信&#xff0c;ATLAS …

【SpringCloud微服务全家桶学习笔记-服务注册zookeeper/consul】

SpringCloud微服务全家桶学习笔记 Eureka服务注册 gitee码云仓库 9.其他服务注册框架 &#xff08;1&#xff09;zookeeper安装与使用 zookeeper需安装在虚拟机上&#xff0c;建议使用CentOS&#xff0c;安装地址如下&#xff1a; zookeeper镜像源 选择第一个进入后下载ta…