本文转载自 www.postgres.cn 下的文章:

再谈PostgreSQL的膨胀和vacuum机制及最佳实践
http://www.postgres.cn/news/viewone/1/390

还有两个相关的文章也挺不错:

也谈PostgreSQL的Vacuum机制及其最佳实践
http://bbs.postgres.cn/news/viewone/1/387

新特性:postgresql的vacuum漫谈
https://mp.weixin.qq.com/s/EzRqxPDowf3mqsbV6FkJWA

作者介绍

朱贤文,成都文武信息技术有限公司创始人,PostgreSQL中国用户会核心组成员,熟悉数据库,存储和集群技术;

成都文武信息技术有限公司是PostgreSQL和GreenPlum数据库服务的专业厂商,主要产品是ECOX集群管理系统和Hunghu Cloud,专门运行数据库的私有云系统,带高端存储功能。公司总部位于天府软件园。公司网站 w3.ww-it.cn

写本文的原因

这两天有两篇专门介绍PostgreSQL的vacuum机制的技术文章,得到了比较热烈和正面的反馈,让用户可以比较清楚地理解和使用这个特性。

我个人觉得有点小遗憾:这两篇文章没有跳出技术的角度,分析为什么会有这样的机制和实现。

所以我打算写点文字补充一下,跳出技术角度,来理解和分析为啥会有这两种机制,以及PostgreSQL选择这样的机制又啥好处。最后在总结一下如何用好这种机制,让数据库更快更好地服务我们的生产系统。

如果有不合妥当的地方,欢迎斧正 !

多版本并发控制机制

要说清楚这个事情之前,我们先看看几种基本的多版本并发控制机制的实现方式。实现MVCC的数据库管理系统,当它需要更改某块数据的时候,它不会直接去更改,会创建这份数据的新版本,在新版本进行更改,所以会存储多份版本,每个事务能看见哪一份版本的数据,要看隔离级别的实现方式,通常的办法是数据块的快照。

正是因为这个原因,引入了另一个问题,如何消除老旧的、没有使用的、无用数据(版本),目前主流上有3种处理实现方式:

  • 第一种,以Oracle为代表的,把旧版本数据放入UNDO,新数据放入REDO,然后更改数据。这种方式,旧版本的数据放入了UNDO,所以可以有效避免膨胀。
  • 第二种,以SQL Server为代表的,把旧版本的数据写入专门的临时表空间,新数据写入日志,然后去更改数据。这种方式,旧版本的数据放入了专门的临时表空间,所以也可以有效地避免膨胀。
  • 第三种,以PostgreSQL为代表的,把旧版本标示为无效,新数据写入日志,成功后把新版本的数据写入新的位置。这种实现机制是导致数据膨胀严重的一个重要原因,因为旧版本的数据虽然表示为无效状态,但是没被回收前还是占据存储空间。

各种机制的比较

对于第一种、第二种实现方式,好处是更改数据的时候不会导致明显的膨胀,把数据膨胀限制在专门的存储空间内。

不好的地方也比较明显,因为改写数据的时候,会先把旧版本数据写入到UNDO或者临时表空间,然后再写日志,所以IOPS的消耗会大一倍,IOPS没有被有效地用于事务处理,这是其一;其二以Oracle为例,undu/redo设置的大小跟业务系统的负载特征相关性很强,设置不好容易导致问题,有经验的DBA一定遇到过snapshot too old这样的错误,就是undo空间不合适导致的一种问题;其三,在数据库崩溃的时候,重新启动数据库会有一个恢复的过程,简单地说Oracle这种实现方式,繁忙的数据库恢复的过程长,启动很慢,因为正确的数据版本需要通过undu,redo的数据去做比较和计算,对于生产系统可能不允许(当然也跟checkpoint本身的设置有关系)。

对于第三种实现方式,好处是IOPS可以充分地用于事务处理,提高业务系统的性能,系统恢复的时候,回滚操作只需要变更指针,所有的数据都在系统能,系统可以快速完成回滚和恢复,让数据库系统尽快投入生产工作。

这种实现方式也会有明显的副作用,就是容易产生数据膨胀,数据库需要经常做回收的工作;

再论实现机制的取舍

站在另一个角度,要弄清楚这个问题,还需要理解一下磁盘提供的基本功能。磁盘本身提供几个特性:

  1. 对外提供存储容量,保存数据,比如600GB;
  2. 磁盘每秒向应用提供一定中断响应次数,术语上叫IOPS (IO Per Sec),这个跟磁盘转速有关系;现在的高速磁盘单盘都可以提供80~100 IOPS。
  3. 传输数据的的带宽,比如ATA 33/66/100 SATA 3G/6G等。

磁盘驱动器在90年代前是很昂贵的外部设备,提供的存储空间和IOPS都非常有限;它作为应用系统永久存储数据的重要存储设备,在使用它的时候需要仔细规划,合理取舍,需要仔细权衡如何使用好这种资源。

Oracle为代表的数据库,明显是倾向将磁盘的空间有效利用起来,避免数据膨胀,虽然会牺牲一些性能,但是磁盘空间的利用效率高一些,90年代以前的应用系统大多数是单机系统,没那么并发用户,所以将磁盘空间合理利用起来,这种设计思想也是合理的。

PostgreSQL为代表的数据库,明显倾向于有效利用IOPS,将能利用的IOPS尽量用于支持应用系统,以提升应用系统的性能;同时牺牲磁盘空间的利用率作为代价,因为90年代以前,磁盘的IOPS真的很昂贵,PostgreSQL的设计可以充分的用好硬件的IOPS,有数据膨胀的负面影响也是值得的,因为膨胀的空间可以放在夜间来回收。

所以设计MVCC的实现机制,为啥要选择牺牲数据膨胀,或者牺牲IOPS,它们只是站在不同的角度,选择了不同的技术实现方式,做了合理的取舍的结果;不同的实现有好的方面,也有负面影响

最佳实践

既然现在PostgreSQL有比较大的潜在的数据膨胀的问题,如何利用好PostgreSQL,避免这种机制引起的数据膨胀和相关的负面影响,让PostgreSQL更好地为业务系统服务,那么解决方法不外乎从两个方面入手:

一方面需要尽量减少数据膨胀,具体方法就是设置合适的fillfactor这个参数,让每个数据块预留一定的空间用于记录更新;当有预留更新的空间,新记录会在预留的空间内更新,因为旧数据跟更新后的数据在同一个数据块中,所以索引本身不必更新;可以降低IO发生的次数,并且提高性能;一般来说设置为建议为80,这个值可以根据应用的特点进行调整,比如:如果没有update,只有insert/delete这样的操作,可以用默认的100;如果update的几率比较大,比如每一条数据都需要改,那么50是一个好的开始。

另一方面让被占用的磁盘空间尽快回收,具体方法就是设置好vacuum相关的参数,让数据库内的垃圾数据及时和有效地得到回收。中心思想就是需要让回收的动作在系统设置允许的时间内完成垃圾数据的回收清理,这里面涉及到一些具体的参数,需要强调一下,系统默认的参数autovacuumvacuumscalefactor=0.2,以及autovacuumanalyzescalefactor=0.1,这两个系统默认设置对于大表明显太大,建议对于大表可以有针对性的设置。具体的方法,用户可以更加自己系统的硬件配置,负载特征以及表的实际情况,设置合适的值,主要是autovacuum*相关的设置;

好消息是PostgreSQL 12会引入类似于undo的机制,来改善目前这个问题,顺利的话会在19年第四季度发布,让我们拭目以待。

[转载]再谈PostgreSQL的膨胀和vacuum机制及最佳实践的更多相关文章

  1. [转载]再谈百度:KPI、无人机,以及一个必须给父母看的案例

    [转载]再谈百度:KPI.无人机,以及一个必须给父母看的案例 发表于 2016-03-15   |   0 Comments   |   阅读次数 33 原文: 再谈百度:KPI.无人机,以及一个必须 ...

  2. [转载]再谈iframe自适应高度

    Demo页面:主页面 iframe_a.html ,被包含页面 iframe_b.htm 和 iframe_c.html 下面开始讲: 通过Google搜索iframe 自适应高度,结果5W多条,搜索 ...

  3. 再谈内存管理与ARC运行机制(一)

    内存管理 内存在Objective-C开发中是一种相对稀缺的资源,拿Iphone4为例,它的内存只有512mb,所以妥善的处理好所创造,所使用的每个对象与变量都将成为一个问题.在ARC出现以前,同大部 ...

  4. 再谈Linux内核中的RCU机制

    转自:http://blog.chinaunix.net/uid-23769728-id-3080134.html RCU的设计思想比较明确,通过新老指针替换的方式来实现免锁方式的共享保护.但是具体到 ...

  5. 浅谈HTTP中Get与Post的区别/HTTP协议与HTML表单(再谈GET与POST的区别)

    HTTP协议与HTML表单(再谈GET与POST的区别) GET方式在request-line中传送数据:POST方式在request-line及request-body中均可以传送数据. http: ...

  6. Another Look at Events(再谈Events)

    转载:http://www.qtcn.org/bbs/simple/?t31383.html Another Look at Events(再谈Events) 最近在学习Qt事件处理的时候发现一篇很不 ...

  7. 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

    这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...

  8. 再谈前端HTML模板技术

    在web2.0之前,写jsp的时候虽然有es和JSTL,但是还是坚持jsp.后面在外包公司为了快速交货,还是用了php Smart技术. web2.0后,前端模板技术风行. 代表有如下三大类: Str ...

  9. 再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

    浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览器特意的阻塞.两个很明 ...

随机推荐

  1. Windows服务器如何查看共享目录信息

    查看Windows服务器上的共享目录的相关信息,可以使用两种方式: 1:命令net share 查看: 2:通过计算机管理的Shared Folders查看

  2. Windows7安装 docker-compose的过程

    Docker在Windows7系统上安装成功后[详情见Windows7下docker的安装以及遇到的问题],要用到docker-compose相关命令,而docker-compose相关命令在dock ...

  3. SQL AVG 函数

    定义和用法 AVG 函数返回数值列的平均值.NULL 值不包括在计算中. SQL AVG() 语法 SELECT AVG(column_name) FROM table_name SQL AVG() ...

  4. PHP按权重随机

    之前业务部门提了一个需求,要求将广告按照ecpm高低进行随机.(即:ecpm高的获取流量的几率大) 如下数组: //要求AD1的概率要求为50%,AD2概率为25% ,AD3的概率为15%,AD4的概 ...

  5. flask轻量级框架入门

    # -*- encoding: utf-8 -*- #导入Flask类, 导入重定向,url_for是简易寻址跳转, from flask import Flask,redirect,url_for, ...

  6. 优先队列Priority Queue和堆Heap

    对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...

  7. vue填坑指南之模板的使用

    坑提示:"The template root requires exactly one element" Src下面有个App.vue文件,在index里引用了这个文件以后,我在. ...

  8. SpringMVC 框架介绍以及环境搭建

    目录 前端设计模式介绍 分析前端设计模式 Spring MVC简单介绍 Spring和Spring MVC的关系 配置Spring MVC的环境并简单测试 前端设计模式介绍 前端设计模式其实和前端没啥 ...

  9. docker 容器的启动方式

    1.Docker 优势: .更高效利用系统资源:由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高.无论是应用执行速度.内存损耗或者文件存储速度,都要比传统 ...

  10. Spring中@Transactional用法

    作者:bladestone 来源:CSDN 原文:https://blog.csdn.net/blueheart20/article/details/44654007 版权声明:本文为博主原创文章,转 ...