PostgreSQL 超越百万 tpmc

作者:胡森

导语

随着 PostgreSQL9.6大版本的 release,许多新的特性也横空出世,其中不乏一些让众多用户期待已久的特性,如同步复制(多同步备机),FDW 支持 remote joins、sorts,并行查询更是千呼万唤始出来。除了新的特性之外,PG9.6还对性能以及锁做了很多优化,这些优化在大并发 oltp 的场景表现尤为突出。

1、并行查询(olap)

PG9.6 的并行查询是通过在执行过程中,根据并行执行计划,启动多个 worker(多进程) 同时计算,并将结果汇总的方式提升查询性能。

目前支持的并行算子有:seqscan, nestloop join, hash join 以及简单的 aggregation。

虽然支持了并行,但是也并不是所有查询都会并行。并行需要满足一个最基本的条件,就是表大小一定要大于 min_parallel_relation_size(全局参数,可设置),这样才有可能进行并行查询。

满足了最基本的条件之后,就需要根据表大小以及 min_parallel_relation_size 计算出并行查询过程中需要的 worker 个数:

然后生成并行的可执行路径,并计算相关的代价。可执行路径的代价通常由三部分组成:启动代价,cpu 代价,io 代价。非并行的执行路径代价:

并行执行由于会启动多个 worker 进行计算,所以在 cpu 上的消耗会由多个 worker 进行均摊;但是由于需要启动额外进程,所以也会需要额外的代价,并行执行路径的代价:

优化器会对各个可执行路径的代价进行比较,选择代价最小的路径;也就是说,虽然生成了并行的可执行路径,但是如果代价大于非并行的路径,也不会走并行。

以 seqscan 为例,看一下并行查询的流程:根据并行查询 worker 的个数对表进行划分(按页划分),每一个 worker 负责自己的那部分数据页,读取数据并进行条件判断,将符合结果的数据放到一个共享队列中,由一个 gather node 进行数据的收集与返回。

PG9.6 的并行到底会对性能带来多大的提升呢?

这里使用了业界 OLAP 标准 TPC-H 进行了相关测试,测试的机型为 Z3,PG 代码为 9.6.1,TPC-H 数据量为 10G:

从测试结果可以看出,对某些 sql,如 1/4/7/12/19 等,并行性能提升的比较明显;但是对于另外一些,如 8/9/10/13/20 等,并行和非并行的性能相差无几。并行并不是适用于所有场景,只是对那些适用的场景会提升查询性能。

2、大并发 oltp

PG9.6 对锁进行了优化,使其在大并发的场景下拥有更好的扩展性。这里主要介绍WALInsertLock和ProcArrayLock,并以PG9.3.5和PG9.6.1为例进行对比说明。

全局锁

获取锁的函数

类型

WALInsertLock

XLogInsert

LW_EXCLUSIVE

ProcArrayLock

ProcArrayEndTransactionGetSnapshotData

LW_EXCLUSIVELW_SHARED

在 PostgreSQL 中,每一个对数据库的修改操作,都需要写一个 XLog。在9.3.5的版本中,写 XLog 需要以排他形式获取 WALInsertLock 这个全局锁,然后写入 XLog ,释放锁,再由其他进程获取锁进行操作。由于每个进程都是获取排它锁,导致写 XLog 的过程是串行进行的。在大并发写的场景下,对单一锁的竞争比较激烈,影响整体性能。

为了有效降低对 WALInsertLock 这个全局锁的竞争,9.6版本中对 WALInsertLock 进行了 partition ,将其划分成多个分区锁。每个进程根据自己的 id 选取一个分区锁,然后在 XLogBuffer 中为自己预留一个空位,再进行写入,实现了多个进程并行写 XLog 。(其实并行写 XLog 的优化在 PG9.4 版本中就已经有了)

在 PostgreSQL 中,每一个 select、DML 操作都需要获取一个全局快照( snapshot )来进行数据的可见性判断( MVCC ),每个获取快照的动作都需要以共享形式获取ProcArrayLock 。在每个事务结束(commit/abort)的时候,都需要清除自己的事务信息,目的是为了保证其他事务可以正确的获取到快照信息。由于这个操作需要进行修改操作,所以以排他形式获得 ProcArrayLock 。

以 PG9.3.5 为例,看一下ProcArrayLock锁竞争关系:

获取快照的过程是获取共享锁,所以所有需要获取快照进行查询的进程可以进行并发操作,只会影响到需要进行事务提交或者回滚的进程。

事务提交或者回滚的时候需要获取排它锁,所有其他需要获取快照或者结束事务的进程都需要进行阻塞,等待当前锁释放,这里对锁的竞争比较激烈,影响到并发。

9.6 对这部分进行了优化,当一个进程获取排它锁进行事务提交或者回滚时,其他需要在同一时刻进行事务处理的进程,组成一个等待队列,由队列头去获取锁。当队列头获取锁之后,为队列中所有成员完成事务处理,并唤醒成员。这种方式有效地将多进程对锁的竞争降低了,减少了锁冲突,提升了扩展性。

9.6 做了这么多优化,到底性能如何?

这里使用了业界 OLTP 标准 TPC-C 进行了相关测试,测试的机型分别为 Z3,intel(96cores, 760GB,3*4TB nvme), power(160cores, 512GB,3*1TB nvme)。TPC-C 数据量为 200 仓库,20GB,并发 100。测试结果如图:

从图中可以看出,9.6 的性能要明显好于 9.3.5,尤其是在 Intel 的 96cores 的机器上,tpmc 高达 113 万,一台机器就可以满足大多数的 OLTP 业务需求。从 cpu 使用率也可以看出,9.6 的优化提升了并发能力,使得资源得到更充分的利用。

除了 TPC-C 以外,还在 power 和 Intel(96 cores) 上面测试了 9.6 的 qps(select only),结果如图:

PostgreSQL 9.6 已经可以很好地支持大并发 OLTP 查询,甚至单机就可以满足大部分 OLTP 业务。并且现在已经有了最基本的并行查询,后续版本也会对并行查询进行增强和优化。相信在不久的未来,PostgreSQL 会成为一个能同时承载 OLTP OLAP 的强大数据库。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逆向与安全

菜鸟 学注册机编写之 “RSA”

选取两个别人不知道的大素数p, q. 公共模n = p*q 欧拉值φ(n) = (p-1)(q-1) 选取公匙(加密匙) e , 条件是1< e <φ(n...

1200
来自专栏小白安全

某素材网扒下来情人节网页代码

素材网里卖几分钱的 效果图: 演示地址:http://www.17sucai.com/pins/demo-show?id=23136 提供...

2865
来自专栏Jed的技术阶梯

Spark读写HBase之使用Spark自带的API以及使用Bulk Load将大量数据导入HBase

以上两个算子分别是基于Hadoop新版API和hadoop旧版API实现的,大部分代码都一样,需要注意的是新版API使用中Job类,旧版API使用JobConf...

1002
来自专栏函数式编程语言及工具

Akka(39): Http:File streaming-文件交换

 所谓文件交换指的是Http协议中服务端和客户端之间文件的上传和下载。Akka-http作为一种系统集成工具应该具备高效率的数据交换方式包括文件交换和数据库表...

2239
来自专栏后端之路

htmlunit 解决https证书不信任问题

代码如下 @Test public void testHtmlUnit() throws Exception { WebClient c...

2879
来自专栏王磊的博客

Express调用mssql驱动公共类dbHelper

直接上代码: /** * Created by chaozhou on 2015/9/18. */ var mssql = require('mssql')...

3397
来自专栏calmound

匈牙利算法

今天学习了下匈牙利算法,发现这个早在几个月前学过的知识已经忘记的一干二净了,记得当初学习的时候只是看书,看论文,现在要好好的总结下,防止以后再次忘记。 此次总结...

2717
来自专栏函数式编程语言及工具

SDP(5):ScalikeJDBC- JDBC-Engine:Streaming

  作为一种通用的数据库编程引擎,用Streaming来应对海量数据的处理是必备功能。同样,我们还是通过一种Context传递产生流的要求。因为Streamin...

2574
来自专栏函数式编程语言及工具

PICE(4):MongoDBStreaming - gRPC Protobuf conversion

   前两篇我们介绍了JDBC和Cassandra的gRPC streaming实现。相对MongoDB来说,JDBC和Cassandra支持字符类型的quer...

770
来自专栏西安-晁州

nodejs封装mssql

对mssql操作Sqlserver数据库的基本封装: 记录一下: /** * Created by chaozhou on 2015/9/18. */ va...

3300

扫码关注云+社区