PostgreSQL MVCC的弊端优化方案

我们之前的博客文章“我们最讨厌的 PostgreSQL 部分”讨论了大家最喜欢的 DBMS 多版本并发控制 (MVCC) 实现所带来的问题。其中包括版本复制、表膨胀、索引维护和真空管理。本文将探讨针对每个问题优化 PostgreSQL 的方法。

尽管 PostgreSQL 的 MVCC 实现是 Oracle 和 MySQL 等其他广泛使用的数据库中最差的,但它仍然是我们最喜欢的 DBMS,而且我们仍然喜欢它!通过分享我们的见解,我们希望帮助用户释放这个强大的数据库系统的全部潜力。好消息是 OtterTune 会自动为您解决许多此类问题(但不是全部!)。

问题#1:版本复制

当查询修改元组时,无论更新其一列还是所有列,PostgreSQL 都会通过复制其所有列来创建新版本。这种复制可能会导致大量数据重复并增加存储需求,特别是对于具有许多列和较大行大小的表。

优化:不幸的是,如果不对 PostgreSQL 的内部结构进行重大重写(这会造成破坏),就没有解决此问题的解决方法。这不像在情景喜剧中替换了一个没有人注意到的角色。正如我们在上一篇文章中提到的,EnterpriseDB 在 2013 年通过 zheap 项目开始了这条道路,但该项目的最后一次更新是在 2021 年。其他人已经对 PostgreSQL 代码进行了硬分叉,以取代其 MVCC 实现。著名的例子包括 OrioleDB 和 YugabyteDB。但对这些系统的更改永远不会合并回主 PostgreSQL 代码库。所以我们暂时只能使用 PostgreSQL 的append-only MVCC。

Problem #2: Table Bloat 问题#2:表膨胀

PostgreSQL 将过期版本(死元组)和活动元组存储在同一页面上。尽管 PostgreSQL 的 autovacuum 工作程序最终会删除这些死元组,但写入繁重的工作负载可能会导致它们累积的速度快于真空处理的速度。此外,自动清理仅删除死元组以供重用(例如,存储新版本),并且不会回收未使用的存储空间。在查询执行期间,PostgreSQL 将死元组加载到内存中(因为 DBMS 将它们与活元组混合在页面上),从而增加磁盘 IO 并损害性能,因为 DBMS 检索无用的数据。如果您正在运行 Amazon 的 PostgreSQL Aurora,这将增加 DBMS 的 IOPS,并导致您给 Jeff Bezos(amazon的老板) 更多的钱!

优化:我们建议监控 PostgreSQL 的表膨胀,然后定期回收未使用的空间。 内置pgstattuple模块可以准确计算数据库中的可用空间,但它需要全表扫描,这对于生产环境中的大表来说不实用。

$ psql -c "CREATE EXTENSION pgstattuple" -d $DB_NAME
$ psql -c "SELECT * FROM pgstattuple('$TABLE_NAME')" -d $DB_NAME

或者,可以使用一次性查询或脚本来估计表的未使用空间;它们比 pgstattuple 更快、更轻量,因为它们提供了表膨胀的粗略估计。如果未使用的空间量很大,则 pg_repack 扩展会从臃肿的表和索引中删除并回收页面。它在线工作,不需要在处理过程中对表进行独占锁定(与 VACUUM FULL 不同)。

以下命令将把 pg_repack 扩展安装到自我管理的 DBMS 中(请参阅 Amazon 的 PostgreSQL RDS 说明),然后压缩单个表。

$ psql -c "CREATE EXTENSION pg_repack" -d $DB_NAME
$ pg_repack -d $DB_NAME --table $TABLE_NAME

为了最大限度地减少对数据库性能的潜在影响,OtterTune 建议我们的客户在流量较低的非高峰时段启动此过程。

问题#3:二级索引维护

当应用程序对表执行 UPDATE 查询时,PostgreSQL 还必须更新该表的所有索引以将条目添加到新版本。这些索引更新增加了 DBMS 的内存压力和磁盘 I/O,特别是对于具有大量索引的表(一位 OtterTune 客户在单个表上有 90 个索引!)。随着表中索引数量的增加,更新元组时产生的开销也会增加。 PostgreSQL 避免更新仅堆元组 (HOT) 更新的索引,其中 DBMS 将新版本存储在与先前版本相同的页面上。但正如我们在上一篇文章中提到的,OtterTune 客户的 PostgreSQL 数据库仅对 46% 的更新操作使用 HOT 优化。

优化:减少 PostgreSQL 索引写入放大的明显解决方法是减少每个表的索引数量。但这说起来容易做起来难。我们建议从表中重复和未使用的索引开始。人们可以通过检查数据库的模式来识别重复索引,以查看两个索引是否以相同的顺序引用相同的列并使用相同的数据结构(例如,B+树与哈希表)。对于未使用的索引,PostgreSQL 维护索引级指标(例如,pg_stat_all_indexes.idx_scan),用于跟踪在索引上启动的索引扫描的数量。如果索引的该值为零,则所有应用程序的查询都不会使用该索引。确保忽略未使用的主键或唯一索引,因为 DBMS 使用它们对表强制执行完整性约束。

下面的屏幕截图显示了 OtterTune 的类似检查,用于自动查找不必要的索引。

OtterTune’s Unused and Duplicate index dashboard.
OtterTune 的未使用和重复索引仪表板。

一旦确定要删除的索引,下一步就是删除它们。但是,如果您的应用程序使用对象关系映射 (ORM) 框架来管理其数据库架构,那么您不希望手动删除索引,因为 ORM 可能会在将来的架构迁移期间重新创建索引。在这种情况下,有必要更新应用程序代码中的架构。如果应用程序未使用 ORM,则可以使用 DROP INDEX 命令。

问题#4:真空管理

PostgreSQL 的性能在很大程度上取决于其 autovacuum 清理过时数据和修剪 MVCC 方案中版本链的有效性。然而,由于其复杂性,配置自动清理以正确运行并及时删除这些数据具有挑战性。默认的全局自动清理设置不适合大型表(数百万到数十亿的元组),因为触发清理可能需要很长时间。此外,如果每个 autovacuum 调用需要很长时间才能完成或被长时间运行的事务阻塞,DBMS 将积累死元组并遭受陈旧统计数据的影响。将自动清理延迟太久会导致查询随着时间的推移逐渐变慢,需要手动干预来解决该问题。

优化:虽然在 PostgreSQL 中清理表很痛苦,但好消息是它是可以管理的。但正如我们现在所讨论的,这有很多步骤,并且需要跟踪很多信息。

控制 autovacuum 的第一步是监视每个表的死元组数量。 PostgreSQL 的  pg_stat_all_tables视图提供了监控表的基本指标,包括死元组 ( n_dead_tup ) 和活动元组 ( n_live_tup ) 数量的估计。通过此类表级指标,您可以确定每个表过期元组的百分比,并确定哪些表需要额外的清理工作。

对于具有大量死元组的表,您可以调整其设置以使 PostgreSQL 更频繁地触发 autovacuum。 PostgreSQL 允许您在表级别微调 autovacuum 参数,不同的表可能需要不同的最佳设置。最重要的旋钮是 autovacuum_vacuum_scale_factor:它指定在 PostgreSQL 调用 autovacuum 之前表中必须存在的死元组的最小百分比。该旋钮的默认值为 20%。如果应用程序的一个表有 10 亿个元组,PostgreSQL 不会在该表上运行清理,直到至少有 2 亿个死元组。如果该表中的平均元组大小为 1KB,则 2 亿个死元组将消耗 200GB 的磁盘存储空间。这甚至不包括指向这些表的索引指针的额外存储开销!为了避免此问题,您应该使用 ALTER TABLE SQL 命令将大型表的比例因子旋钮设置为小于 20%:

 ALTER TABLE table_name SET (autovacuum_ vacuum_scale_factor = 0.05);

接下来,您应该检查 autovacuum 是否被长时间运行的事务阻塞。再次,我们可以依靠 PostgreSQL 的内部遥测来获取这些信息。 pg_stat_activity 视图提供每个 PostgreSQL 工作线程(即进程)当前执行状态的实时数据。它显示每个活动事务已运行多长时间。如果事务已经运行了几个小时,您应该考虑将其终止,以便 autovacuum 可以完成其操作。下面的示例查询查找所有运行时间超过五分钟的事务:

SELECT pid, NOW() - xact_start AS duration, query, stateFROM pg_stat_activityWHERE (NOW() - xact_start) > INTERVAL '5 minutes';

然后,您可以使用 pg_cancel_backend 管理函数终止查询:

SELECT pg_cancel_backend($PID_TO_KILL);

当然,在街上删除查询可能会产生意想不到的后果,因此您必须确保杀死它们不会在您的应用程序中造成问题。为了避免将来出现同样的问题,请确保事务的查询不必要地运行更长的时间,因为它们使用的是低效的查询计划。请参阅我们之前关于优化查询性能的文章,例如欺骗 ORDER BY...LIMIT 和运行 ANALYZE ,了解如何使用 OtterTune 改善慢速查询。如果您不需要它们是原子的,您还可以重构您的应用程序,将大型事务分解为较小的工作单元(但不可否认,这并不总是容易做到)。

最后,您需要查看是否存在长时间运行的真空过程,然后调整其他旋钮。与 pg_stat_activity 显示 PostgreSQL 工作线程的状态类似,pg_stat_progress_vacuum 视图显示活动 autovacuum 操作的状态。通过此视图,您可以确定真空是否需要几个小时甚至几天才能完成。如果您的 PostgreSQL DBMS 确实有长时间运行的 Vacuum,那么 OtterTune 建议调整三个旋钮:

  1. autovacuum_work_mem 参数指定 DBMS 在每次 autovacuum 调用中可以使用的最大内存量。增加此参数可以加快清理速度,因为它可以在每次调用时修剪更多的死元组。
  2. autovacuum_vacuum_cost_limit 参数控制在 PostgreSQL 强制自动清理工作者暂时退出之前可以产生多少 I/O 活动自动清理工作者。该旋钮的值越高意味着自动清理将更加积极。
  3. 与这种基于成本的控制机制相关,autovacuum_vacuum_cost_delay  参数确定 autovacuum 工作线程在 DBMS 强制其退出后必须等待多长时间。较短的延迟意味着自动清理每次都会更快地恢复操作。

原文地址

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

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

相关文章

关于 PostgreSQL 删除数据库 - 命令行删除,报错数据库不存在,pgadmin 报错存在会话链接 导致无法删除数据库问题

序言 测试环境: Windows 10问题 笔者尝试过在 cmd 命令行,使用PostgreSQL 的 psql 工具登录 postgresql,删除某个有问题的数据库,准备新建重载该数据库时,发现 DROP DATABASE database_name ,竟然报错该…

埃科光电在科创板上市:同创伟业、毅达资本为股东,实控人为董宁

7月19日,合肥埃科光电科技股份有限公司(下称“埃科光电”,SH:688610)在上海证券交易所科创板上市。本次上市,埃科光电的发行价为73.33元/股,发行数量为1700万股,募资总额约为12.47亿元&#xff…

Shell运行原理以及Linux中的权限问题

目录 一、shell的运行原理 二、Linux权限的概念 2.1 用户账号切换 2.2 仅提升当前指令的权限 2.3 将普通用户添加到信任列表 三、Linux权限管理 3.1 文件访问者的分类 3.2 文件类型和访问权限 3.3 字符权限值的表示方法 3.3.1 字符表示方法 3.3.2 八进制表示法 3.4…

XSS 攻击的检测和修复方法

XSS 攻击的检测和修复方法 XSS(Cross-Site Scripting)攻击是一种最为常见和危险的 Web 攻击,即攻击者通过在 Web 页面中注入恶意代码,使得用户在访问该页面时,恶意代码被执行,从而导致用户信息泄露、账户被…

BUFG/BUFGCE/BUFH/BUFHCE/BUFH/BUFGHCE/BUFMR/BUFMRCE/BUFR/IBUF/IBUFDS

本文对BUFG/BUFGCE/BUFH/BUFHCE简单介绍,便于后续查看。 原语的使用:在vivado中找到所要用的原语,直接将其实例化到设计中即可。 文章目录 BUFGBUFGCEBUFHBUFHCEBUFMRBUFRBUFMRCEIBUFIBUFDS 下图为 7 系列 FPGA 时钟架构图: BU…

Appium+python自动化(十二)- Android UIAutomator终极定位凶器(超详解)

简介 乍眼一看,小伙伴们觉得这部分其实在异性兄弟那里就做过介绍和分享了,其实不然,上次介绍和分享的大哥是uiautomatorviewer,是一款定位工具。今天介绍的是一个java库,提供执行自动化测试的各种API。 Android团队在4…

数据结构(王道)——数据结构之 二叉树

一、数据结构之 二叉树概念: 特殊的二叉树结构: 满二叉树完全二叉树 二叉排序树 平衡二叉树 二叉树基本概念总结: 二、二叉树的常用性质: 1、【二叉树】的叶子结点比二分支结点多一个 2、【m叉树】的第i层至多有m^(i-1)个结点 3、…

关于Qt For android第一次编译时出现的问题

搞了三四天,搞的快崩溃了,问题提示为 FAILURE: Build failed with an exception.* What went wrong: A problem occurred configuring root project android-build. > Could not resolve all artifacts for configuration :classpath.> Could not…

pytorch 2.0初探:和pytorch 1.13的速度对比

看到pytorch2.0出来了,而且宣传提速明显,一行代码即可提速43%左右: compiled_model torch.compile(model) We then measure speedups and validate accuracy across these models. Since speedups can be dependent on data-type, we measu…

真正的理解WPF中的TemplatedParent

童鞋们在WPF中经常看到 TemplatedParent ,或者经常看到下面的用法: {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content} 是不是看的一脸蒙圈? 先看官方文档: 意思是 和这个控件的 模板上的 父亲,如果这个控件不是模板创建的,那么这个值就…

CSS 渐变边框及动画

转载请注明出处,点击此处 查看更多精彩内容 用 CSS 实现渐变边框及动画,下面对关键点进行解释说明,查看完整代码及预览效果请 点击这里。 简单说明原理:使用伪元素 ::before 绘制一个渐变色,然后使用伪元素 ::after 绘…

16. 存储过程和存储函数

文章目录 1.存储过程和存储函数2.创建和使用存储过程2.1 语法:2.2 第一个存储过程,打印hello world2.3 调用语法2.4 带参数的存储过程2.5 调试存储过程 3.创建和使用存储函数3.1 存储函数定义3.2 存储函数语法:3.3 存储函数案例: …

Mybatis操作数据库执行流程的先后顺序是怎样的?

MyBatis是一个支持普通SQL查询、存储及高级映射的持久层框架,它几乎消除了JDBC的冗余代码。使Java开发人员可以使用面向对象的编程思想来操作数据库。对于MyBatis的工作原理和操作流程的理解,我们先来看下面的工作流程图。 MaBatis的工作流程 在上图中…

为什么弹性内容交付网络是决定网站性能的关键

如今的用户对于所访问网站都对网站有自己的标准,他们期望访问的网站性能良好,具有快速的页面加载时间和易于访问、新鲜且动态的内容,同时他们还希望享受无缝且安全的体验,无需停机或内容访问受到限制。比如微博等平台每次在网络热…

布隆过滤器在海量数据去重验证中应用

布隆过滤器在海量数据去重验证中应用 文章目录 布隆过滤器在海量数据去重验证中应用引子面试结束级方案——从数据库中取新手级方案——利用redis的set数据结构专业级方案——利用布隆过滤器 布隆过滤器基本概念优点缺点布隆过滤器的数据结构布隆过滤器的工作流程布隆过滤器的优…

数据库应用:MySQL备份与恢复

目录 一、理论 1.数据备份 2.完全备份与恢复 3.完全备份与恢复应用 4.增量备份与恢复 5.增量备份与恢复应用 6.使用脚本备份 7.日志管理 二、实验 1.完全备份与恢复 2.增量备份与恢复 3.使用脚本备份 三、问题 1.mysqldump报错 四、总结 一、理论 1.数据备份 …

企业电子招标采购系统源码Spring Cloud + Spring Boot + MybatisPlus + 前后端分离 + 二次开发

项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审…

(ceph)CephFS 文件系统 MDS接口

创建 CephFS 文件系统 MDS 接口 //服务端操作 1)在管理节点创建 mds 服务 cd /etc/ceph ceph-deploy mds create node01 node02 node032)查看各个节点的 mds 服务 ssh rootnode01 systemctl status ceph-mdsnode01 ssh rootnode02 systemctl status cep…

浙大数据结构第三周之03-树3 Tree Traversals Again

题目详情: An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2)…

怎么对XMind思维导图加密?

在现代社会中,信息安全变得越来越重要。对于那些使用XMind思维导图来组织和管理重要信息的人来说,保护思维导图中的内容免受未经授权的访问变得至关重要。本文将介绍如何加密XMind思维导图,以确保您的信息安全。 什么是XMind思维导图&#x…