• 发文
  • 评论
  • 微博
  • 空间
  • 微信

pg14新特性-利来app官方下载

yzsdba 2021-12-27 13:53 发文

postgresql14加速恢复与vacuum

我关注的pg14的性能项目其中一个是加速恢复与vacuum。在微软的pg团队中,我和pg社区其他成员大部分时间一起致力于pg开源项目。在pg14中(2021的q3),我提交了一个patch优化compactify元组函数,减少恢复时cpu的使用。这项性能优化可以使pg14的恢复快2.4倍。

compactify_tuples函数在pg内部使用的地方:

1) 崩溃恢复时

2) 备机回放

3) vacuum

因此,好消息是,改进compactify_tuples可以提高崩溃恢复性能;减少备机负载,使其更快回放来自主的日志;提高vacuum性能。

本文中,我们将介绍compactify_tuples函数的改进,该函数过去如何工作,以及pg14改写后为什么更快。

剖析恢复进程突出一个性能问题

pg中wal日志包含指令及数据。描述了对基础数据进行修改。wal确保数据持久化。当pg重启时,恢复进程将最近执行检查点位置之后的日志全部回放。顺序回放wal日志,将数据库关闭时未刷写到磁盘的更改回放到数据页中。

在运行update密集型工作负载后,故意使数据库崩溃,我们对恢复过程进行了一些分析。cpu负载大部分来自“heap2 clean”wal记录的回放。heap2 clean记录通过清除死记录占用空间来整理页内碎片。当页面变满,并需要更多空间时,就会产生heap2 clean日志。

一个tuple是表中行的内部表示。一行可能有很多tuple,但任何一个时间点,仅一个tuple有效。老事务可能访问旧版本,以便访问事务开始时的行。update会产生新版本。创建每个行的多个版本被叫做多版本并发控制(mvcc)。

从heap页中清理未使用的空间

为理解heap2 clean在pg中如何工作,需要首先了解下heap页结构。我们看下带有元组碎片的heap页:

图1 由于删除了元组而出现碎片的heap页

我们可以看到,每个页头后面都有一个“items”数组。这些item指向每个元组。pg从页尾开始将元组写入页面,当items数组和元组空间重叠时,页面变满。需要注意,页尾处的元组和item指针的顺序并不是完全反向相反。元组2和3在这里出现了乱序。在页面更新了一些记录并旧的item指针被重用后,元组就会变得乱序。我们还可以看到,图1中的页面有很多未使用的空间。未使用的空间是由于vacuum删除了元组。heap2 clean操作将清除这些未使用的空间。

在pg13及更早的版本中,heap2 clean操作会将上述内容转换为:

图2 pg14之前碎片整理的heap页

我们可以看到空白区域小时了,元组紧凑移动到了页尾。注意,元组和原来保持相同顺序。元组2和3保持交叉顺序。

pg14之前heap页compacification怎么工作

comactify_tuples函数为我们处理页面compact工作。更改前,compactify_tuples函数会对item副本执行排序。这种排序允许元组移动到页尾。本案例中,先移动tuple1,然后tuple3,接着tuple2,最后tuple4。为决定哪个tuple先移动,compactify_tuples使用qsort函数用于比较并排序。以反向偏移顺序对item数组进行排序,允许从页面尾部的元组开始移动。

由于heap页面最多可以版本几百个元组,并且由于update负载中compact的频率导致qsort耗费大量cpu。当然,如果页面仅有几个元组,排序的代价就不高了。

那么是否需要排序?是,也不是。如果以item数组的顺序移动元组,不进行排序,我们可以在稍后的页面中覆盖元组。例如,图2中,如果在移动tuple3前移动tuple2,那么我们将覆盖tuple3。

当像这样移动元组时,必须确保先将该位置的元组移动到页尾。因此对于这种本地移动必须进行排序。

怎样使heap2 clean更快?

为了在执行heap2 clean时,加快页面compact,我们需要写一个自定义qsort函数内联操作符函数。创建一个通用qsort函数会减少一些函数调用代价,但是不管怎么做qsort的复杂度都是o(n log n)。完全摆脱这种函数会更好。

使用qsort仅保证不会覆盖。因此可以将这些元组拷贝到一个临时缓冲区,这样移动元组的顺序就无关紧要了。

pg14中compactify_tuples函数完全不需要使用qsort。不用排序,可以使我们以item数组的顺序移动tuple到页尾。临时内存避免了元组在移动前被覆盖的风险,也意味着元组以正确的顺序放回到页面尾处。pg14进行compact后新的heap页为:

图3 pg14性能提升后新的compact heap页

注意,元组2和3交换了位置,并且元组现在处于item反向顺序。

新的pg14代码通过预检查进一步优化,看元组是否已将在正确的反向item指针顺序中。如果元组顺序不正确,则不需要使用临时缓冲区。然后仅移动比第一个空白空间更早的元组。其他元组已经在正确位置。现在我们再次将元组以item指针反向顺序放回元组,我们更加频繁地遇到这种预先排序的情况。平均而言,我们金辉移动页面上一半元组。新元组产生新的item指针也会维护这样的顺序。

与元组在页面中的随机顺序相比,让元组以反向顺序还可以帮助某些cpu架构更有效地预取。

现在pg14有多快?

我们的测试用力使用了包含2个int列,填充因子为85的1000万行数据。考虑元组头,允许在每8kb页面存储最多226个元组。为了生成一些wal来回放,使用pgbench,随机执行1200万次更新。1000万行中每行平均有12次更新。然后非正常关闭,重启进行崩溃恢复。在性能提升前,崩溃恢复需要148秒才能重放2.2gb的wal。

新版本的compactify_tuples代码进行同样的测试,耗时60.8秒。崩溃恢复的性能提升约2.4倍。

以前在compacity_tuples更改前,具有大量元组的页面进行compact很慢,因为qsort需要很长时间。更改后,不同数量的页面进行compact基本一致。即使每个页有很少元组,这种变化仍然会小幅提升性能。但是,当元组数量巨大时,更加有效。

pg14中的vacuum性能也有所提升

vacuum和(autovacuum)在heap页面中删除死元组也使用相同代码。因此加速compactify_tuples也意味着vacuum性能有很好改进。我们尝试对之前更新的基准测试表执行vacuum,发现pg14中运行速度比更改前快25%。以前需要4.1秒,现在仅2.9秒。

加速恢复过程还意味着备机更有可能跟上主,并在产生日志后很快回放掉。这意味着可以帮助备不落后主。

因此恢复进程和vacuum在pg14中更快--而且还有很多工作正在进行中

compacity_tuples在很多情况下确实有助于提高恢复性能。但是恢复过程在io上遇到瓶颈而不是cpu也很场景。当恢复的数据库大于可用内存时,必须等待从磁盘中读取页然后进行回放。幸运的是,我们还在研究一种方法,让恢复进程将页面预取到内核的页面缓冲中,这样物理io就可以在后台并发进行,而不是让恢复进程等待。

原文

image.png


声明:本文为ofweek维科号作者发布,不代表ofweek维科号立场。如有侵权或其他问题,请及时联系利来国际下载举报。
2
评论
评论

相关阅读

暂无数据

yzsdba

专注于开源数据库原理与使用...

热门文章排行榜
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

举报文章问题

×
  • 营销广告
  • 重复、旧闻
  • 格式问题
  • 低俗
  • 标题夸张
  • 与事实不符
  • 疑似抄袭
  • 我有话要说
确定 取消

举报评论问题

×
  • 淫秽色情
  • 营销广告
  • 恶意攻击谩骂
  • 我要吐槽
确定 取消

用户登录×