Greenplum 6针对OLTP的使用场景完成了多项优化,极大的改进了多并发情况下简单查询、删除和更新操作的性能。这些改进包括:
基于这些优化,在我们的测试环境中,Greenplum 6的TPC-B性能相比最新的Greenplum 5提升了60倍,单条更新操作性能提升了70倍,单条插入峰值性能提升到3.6倍,单条查询性能也提升到3.5倍。尤其是对于单条查询的场景,我们在Greenplum 6中消除了大部分锁竞争,使得master的CPU使用率可以超过90%,这样通过提升master硬件性能可以进一步提升查询的TPS性能,在我们的一个单机192核的测试环境中(1个master+18个segment),单条查询TPS可以达到22万。
我们的测试环境基于谷歌云平台(Google Cloud Platform,简称GCP),为5个虚拟主机的集群,包含一个master主机和四个segment主机,master和segment虚拟主机的配置信息如下:
每一台segment主机运行一个segment节点,整个集群没有配置mirror与standby节点。除此之外还需要一台虚拟主机来运行测试工具pgbench,它的配置不需要很高,在我们的测试中采用的是4核5 GB的配置。
我们的测试采用了自行编译的Greenplum, 以下为版本信息:
Greenplum 6 | Greenplum 5 |
---|---|
6.0.0-beta.3 | 5.18.0 |
./configure \ –prefix=$HOME/opt/gpdb \ –disable-orca \ –disable-gpfdist \ –disable-pxf \ CFLAGS=’-g -O3 -march=native’ \ CXXFLAGS=’-g -O3 -march=native’ |
./configure \ -prefix=$HOME/opt/gpdb5 \ –disable-orca\ –disable-gpfdist \ –disable-pxf \ CFLAGS=’-g -O3 -march=native’ \ CXXFLAGS=’-g -O3 -march=native’ |
gpconfig -c gp_enable_global_deadlock_detector -v on
gpconfig -c log_statement -v none
gpconfig -c checkpoint_segments -v 2 –skipvalidation
我们的测试采用pgbench进行,统一采用编译自Greenplum 6的版本,数据规模为1000倍,未对数据做额外调整。 测试项目分为四个,分别是包含多条语句的标准TPC-B事务、单条查找语句、单条更新语句和单条插入语句。对于每个项目,测试统计了在并发客户端从10增加到200时的TPS数值。
Pgbench的TPC-B测试混杂了大表与小表的插入、更新与查询操作。Greenplum 6的TPS峰值4300左右,而Greenplum 5的峰值在70左右,性能提升幅度达到60倍。导致巨大性能差异的一个关键在于Greenplum 6引入了全局死锁检测功能从而支持了HEAP表数据表的并发更新,而Greenplum 5中对同一张表的更新必须串行进行。
-- pgbench -c $N -j $N -r -T 60 -P 1 -s 1000
\set scale 1000
\set nbranches 1 * :scale
\set ntellers 10 * :scale
\set naccounts 100000 * :scale
\set random aid 1 :naccounts
\set random bid 1 :nbranches
\set random tid 1 :ntellers
\set random delta -5000 5000
BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
在只读测试中Greenplum 6的TPS峰值可达到79000以上,而Greenplum 5的TPS幅值则仅为23000,提升幅度达到350%。
-- pgbench -c $N -j $N -r -T 60 -P 1 -s 1000 -S
\set scale 1000
\set naccounts 100000 * :scale
\set random aid 1 :naccounts
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
除了pgbench内置的测试外我们也对单条更新的场景进行了测试,Greenplum 6的峰值TPS为7300,Greenplum 5的峰值TPS为100左右,提升幅度达到了70倍以上。
-- pgbench -c $N -j $N -r -T 60 -P 1 -s 1000 -f update-only.sql
\set scale 1000
\set naccounts 100000 * :scale
\set random aid 1 :naccounts
\set random delta -5000 5000
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
在单条插入测试中Greenplum 6的TPS峰值超过18000,Greenplum 5的TPS峰值为5000,提升幅度达到360%。
-- pgbench -c $N -j $N -r -T 60 -P 1 -s 1000 -f insert-only.sql
\set scale 1000
\set nbranches 1 * :scale
\set ntellers 10 * :scale
\set naccounts 100000 * :scale
\set random aid 1 :naccounts
\set random bid 1 :nbranches
\set random tid 1 :ntellers
\set random delta -5000 5000
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
由于全局死锁检测功能的引入,Greenplum 6的更新类操作的性能产生了质的飞越,与此同时我们也发现了很多进一步优化的空间。
在测试中我们注意到一些编译选项对更新类操作的性能及稳定性有巨大的影响。wal_segment_size是一个只读GUC,它的含义是单个WAL分片文件的大小,每当写入了若干个分片文件后会触发一次强制刷盘,显然它的值越大则刷盘频率越低,但是每次刷盘的数据量也越大耗时越长,此时同主机上的其它进程的I/O操作性能都会受到极大干扰,进而导致整个集群的性能瞬时下降。在Greenplum中此GUC的默认值为64MB,根据以上的测试数据我们注意到Greenplum中的更新操作的TPS的波动非常大,而当将其调整为Postgres的默认值16MB时则波动幅度明显减少,平均TPS值也有所提升。但是此值仅支持在编译时通过“configure –with-wal-segsize=SEGSIZE”指定,因此如何支持运行时调整以及微调的策略会是我们未来的一项工作内容。
我们也注意到,在单条插入的测试项目中,当Greenplum 6的并发数超过峰值点时其性能反而出现了一定幅度的下降,根据我们的初步测试这与内部锁竞争有关,如果我们能够对其进行优化则在Greenplum 6的后续版本中可以期待更高的插入性能。