瀚高分布式数据库HGDB Sharding在2021年4月22日的TPC-C网测中,tpmC值突破1000万大关。其中,性价比指标,Price/tpmC单价低于1元人民币,属业内首次。
更重要的是,这个结果并非实验室内的竞技,而是在座各位人人可以亲手做到、重复再现,并可屡屡超越的!
在此,我们与大家分享一下有关测试的过程。
一、TPC-C测试简介
TPC-C是专门针对联机事务处理系统(OLTP系统)的测试规范,是由TPC委员会在1992年7月发布的。
TPC(Transaction Processing Performance Council,事务处理性能委员会)是由数十家会员公司创建的非盈利组织,总部设在美国。TPC的成员主要是计算机软硬件厂家,而非计算机用户,其功能是制定商务应用基准程序的标准规范、性能和价格度量,并管理测试结果的发布。
TPC-C测试用到的模型是一个大型的商品批发销售公司,它拥有若干个分布在不同区域的商品仓库。当业务扩展的时候,公司将添加新的仓库。每个仓库负责为10个销售点供货,其中每个销售点为3000个客户提供服务,每个客户提交的订单中,平均每个订单有10项产品,所有订单中约1%的产品在其直接所属的仓库中没有存货,必须由其他区域的仓库来供货。同时,每个仓库都要维护公司销售的100000种商品的库存记录。
TPC-C测评系统数据库由9张表组成,它们之间的关系如下图:

其中,表框里的数字表示该表将要存放多少条记录,仓库数W的调整在测试中能够体现数据库所能够支持的数据规模的能力;表间的数据表示数据的父子关系之间儿子的个数,比如一个Warehouse要对应10个District等,另外,“+”号表示这种对应关系可能会更多。
TPC-C基准测试系统需要处理的交易主要为以下几种:
1、新订单(New-Order) :客户输入一笔新的订货交易;
2、支付操作(Payment) :更新客户帐户余额以反映其支付状况;
3、发货(Delivery) :发货(模拟批处理交易);
4、订单状态查询(Order-Status) :查询客户最近交易的状态;
5、库存状态查询(Stock-Level) :查询仓库库存状况,以便能够及时补货。
TPC-C测试的结果主要有两个指标,即流量指标(Throughput,简称tpmC)和性价比(Price/Performance,简称Price/tpmC)。
流量指标(Throughput,简称tpmC):按照TPC组织的定义,流量指标描述了系统在执行支付操作、订单状态查询、发货和库存状态查询这4种交易的同时,每分钟可以处理多少个新订单交易。所有交易的响应时间必须满足TPC-C测试规范的要求,且各种交易数量所占的比例也应该满足TPC-C测试规范的要求。在这种情况下,流量指标值越大说明系统的联机事务处理能力越高。
性价比(Price/Performance,简称Price/tpmC):即测试系统的整体价格与流量指标的比值,在获得相同的tpmC值的情况下,价格越低越好。
二、瀚高数据库单节点测试
在我们做瀚高分布式数据库测试之前,我们先做一个单节点的瀚高数据库测试,对所使用的系统性能进行一次摸底。
1、测试环境的准备
在这个测试中,我们选用的设备是华为云(我们欢迎更多的云服务供应商与我们开展合作)。
为了便于测试结果的横向比较,我们在华为云上创建弹性云服务器(ECS),并选用x86技术架构服务器:
华为云访问地址为:www.huaweicloud.com
也可以直接点击链接:
https://console.huaweicloud.com/ecm/?agencyId=07f24b2bfd000f8b1ff6c004caa5bc16®ion=cn-east-3&locale=zh-cn#/ecs/createVm
跳转至ECS服务器订阅页面:

在此,我们订阅一台c6s.8xlarge.2,配置是:
服务器类型 | c6s.8xlarge.2 |
处理器类型 | 第二代英特尔® 至强® 可扩展处理器 |
处理器核/线程 | 32vCPU |
内存 | 64GB |
该服务器的按需使用价格是5.9元/小时。如果按照三年订阅,单价会更低:

在单机的测试中,为了装载10000仓的数据量,我们为该服务器额外增加2T的超高IO数据盘,费用0.0014元/GB/小时:

配备2T存储后的单节点服务器总价格为8.806元/小时:

此外,我们订阅另一台机器作为测试用的客户端,运行BenchmarkSQL基准程序。该客户端的配置是:
服务器类型 | c6s.4xlarge.2 |
处理器类型 | 第二代英特尔® 至强® 可扩展处理器 |
处理器核/线程 | 16vCPU |
内存 | 32GB |
该测试环境的网络选用了华为云的内网。
操作系统与数据库软件:
操作系统 | CentOS Linux release 7.4.1708 (Core) |
数据库 | 瀚高企业版数据库HGDB |
测试工具 | BenchmarkSQL5.0 |
性能监控 | nmon_x86_64_rhel7 |
在此,要说明一下,我们在华为云上选择了一款非常普通,甚至是有些低配的服务器来作为我们的数据库服务器。我们的目的并不是为了在该服务器单机上创造高吞吐量,而是考虑到在未来多节点分布式配置的时候以该规模的服务器作为我们的数据节点。目前,我们选择的这款服务器从成本来说比较适合未来大批量订阅。这是一款大多数客户触手可及的设备。
2、硬件参数配置
1)内核参数的优化
需要根据实际情况进行调整,本次测试中,对/etc/sysctl.conf修改,之后执行sysctl -p加载。
vm.dirty_background_bytes:内存中允许存在的脏页值,达到该值后,后台开始刷盘。vm.dirty_background_bytes在本例中设置为64M,即64*1024*1024 bytes
vm.dirty_bytes:用脏数据填充的绝对最大系统内存量,当系统到达此点时,必须将所有脏数据提交到磁盘,同时所有新的I/O块都会被阻塞,直到脏数据被写入磁盘。本示例中,vm.dirty_bytes设置为512M,即512*1024*1024 bytes
vm.swappiness:值越大,表示越积极使用交换分区,越小表示越积极使用物理内存。我们在此设置为1,尽可能不用交换分区,仅在内存不足的情况下,使用交换空间。
参数汇总如下:
vm.dirty_background_bytes = 67108864 vm.dirty_bytes = 536870912 vm.swappiness = 1 |
2)关闭透明大页
透明大页允许大页做动态的分配,运行时动态分配内存,可能会导致数据库崩溃等不可控的错误。Oracle、Redis、PostgreSQL等服务都建议关闭这个特性,我们也关闭。
执行以下命令进行关闭:
echo never > sys/kernel/mm/transparent_hugepage/enabled echo never > sys/kernel/mm/transparent_hugepage/defrag echo 0 > sys/kernel/mm/transparent_hugepage/khugepaged/defrag |
3、数据库参数配置
瀚高数据库基于PostgreSQL为核心发展而来,出于用户使用习惯的考虑,我们保留了PostgreSQL原本的文件命名,修改数据目录下的postgresql.conf文件进行相应设置。
1)IO调优的关键参数:
IO的调优很重要的一点是检查点的设置,检查点是数据库的关键行为,同时也是IO敏感的,其保证了数据库的一致性状态,定期执行检查点是很重要的,确保数据变化持久保存到磁盘中并且数据库的状态是一致的。
checkpoint_timeout表示系统自动执行checkpoint之间的最大时间间隔,这个值可以在压测过程中调大,尽量避免执行checkpoint争抢IO,此处设置为20min;checkpoint_completion_target的范围为0~1,此处设为0.9,当写的WAL的日志量超过90%时,就会发生一次checkpoint,设置尽量大一点,避免执行checkpoint争抢IO增加;
max_wal_size表示写满多少个WAL时执行checkpoint,这个尽量调大,以避免执行checkpoint争抢IO,建议设置为100G;
min_wal_size:只要wal日志目录使用空间小于该值,那么旧的wal日志就会循环使用而不是进行删除。这个参数是为了确保足够的WAL空间预留给突发情况,此处建议设为10GB;
wal_level:minimal会去掉除从崩溃或者立即关机中进行恢复所需的信息之外的所有记录;减少wal日志生成,从而减少checkpoint执行频率;
max_wal_senders:当wal_level 设置为 minimal时,该参数必须设置为0;
synchronous_commit:默认为ON,表示事务提交为同步方式。本次测试设置为OFF,即异步方式。当操作系统崩溃时存在数据丢失的风险,风险大小取决后续3个参数的配置。bgwriter_delay:background writer每次扫描之间的时间间隔,也就是刷shared buffer脏页的进程调度间隔,尽量高频调度,减少用户进程申请不到内存而需要主动刷脏页的可能;bgwriter_lru_maxpages:表示一次最多刷多少脏页;bgwriter_lru_multiplier:写出至多bgwriter_lru_multiplier * N个脏页,并且不超过该参数值的限制。其中N是最近一段时间在两次BgWriter运行期间系统新申请的缓冲区页数。后台写进程根据最近服务进程需要的buffer数量乘上这个比率估算出下次服务进程需要的buffer数量,再使用后台写进程刷脏页面,使缓冲区能使用的干净页面达到这个估计值;
autovacuum自动清理进程,在压测期间,可以关闭,减少IO争抢;
fsync是一个比较重要的参数,为了追求性能,并且能确保数据库不出现问题,该测试中关闭fsync,但可能丢失数据,造成数据不一致。
wal_writer_delay:指定WAL writer刷写WAL的频繁程度,如果设置了synchronous_commit = off,建议设置该参数。WAL进程每次在完成写事务日志的任务后,就会等待该参数时间,然后将新产生的事务日志从缓冲区写到WAL文件中。根据自身系统的运行状况进行配置,如果时间过长可能造成WAL buffer的内存不足,数据丢失的危险;过小将会引起WAL的不断的写入,对磁盘的IO也是很大考验。
2)内存调优的关键参数
最重要的就是share_buffer,在普通场景下建议设置为内存的25%,不超过40%;在TPC-C的场景下尽可能设大一点,根据warehouse数量及内存进行调整,理想情况下的调整原则是尽量将数据都放入内存中,减少双缓存的影响。此次测试,我们设置为36GB;
work_mem:减少外部文件排序的可能,提高效率;设置过大容易导致内存溢出,数据库进程被kill,可以根据实际环境进行调整。
maintenance_work_mem:加速建立索引,一般可以按每1GB内存设置为50MB来设置,我们64G内存,设置为3G
effective_cache_size:值越大,越倾向于走索引扫描,此处我们设置为48GB
huge_pages:通过启用“大内存页”,系统只需要处理较少的页面映射表,从而减少访问及维护它们的开销;但是,如果服务器内存不富裕的话,建议关闭;
3)重要参数修改汇总如下:
max_connections = 200 #单机的BenchmarkSQL并发设置为150,本次测试设置为200 max_wal_size = 100GB min_wal_size = 10GB checkpoint_timeout = 20min checkpoint_completion_target=0.9 autovacuum = off synchronous_commit = off shared_buffers = 36GB maintenance_work_mem = 3GB effective_cache_size = 48GB |
以上的设置仅是基于基本的概念,并未做极致的调优。其目的还是为了拿一个单机数据节点的吞吐量结果作为基准。
4、测试数据库的准备
1)BenchmarkSQL的下载及编译
BenchmarkSQL是一款经典的开源数据库测试工具,内嵌了TPC-C测试脚本,本文使用5.0版本进行测试。官网下载地址为:
https://sourceforge.net/projects/benchmarksql/
使用unzip解压下载包,进入“benchmarksql-5.0”目录执行ant命令编译,看到“BUILD SUCCESSFUL”提示后,证明环境已准备好。
[root@localhost benchmarksql-5.0]# ant Buildfile: root/benchmarksql-5.0/build.xml init: [mkdir] Created dir: /root/benchmarksql-5.0/build compile: [javac] Compiling 11 source files to /root/benchmarksql-5.0/build dist: [mkdir] Created dir: /root/benchmarksql-5.0/dist [jar] Building jar: /root/benchmarksql-5.0/dist/BenchmarkSQL-5.0.jar BUILD SUCCESSFUL Total time: 3 seconds |
2)BenchmarkSQL配置文件
接下来,我们需要对BenchmarkSQL的配置文件进行定制,配置文件存放在run目录下。瀚高数据库基于PostgreSQL发展而来,主要的改进在于服务器端,客户端保留与PostgreSQL兼容,为此,我们在此只需关注props.pg配置文件即可。
相关参数介绍:
Warehouse:指“仓库”数量,每个warehouse大小大概是100MB。本示例中,我们的仓库数设置为10000仓。
Loadworkers:用于在数据库中初始化数据的加载进程数量,使用过程中可以根据实际情况调整,如32,加载速度会随worker数量的增加而有所提升。
Terminals:指的是并发连接数,指同时有多少终端并发执行,表示并发程度,建议设置为服务器CPU核数的2-6倍,本示例中,我们的服务器为32核,连接数建议在64~192,经过多轮调试,连接数150为最佳。
runMins=20:指要测试的持续时间,单位为分钟,如果runMins设置为20,那么测试持续20分钟结束。
newOrderWeight、paymentWeight、orderStatusWeight、deliveryWeight、stockLevelWeight为每笔交易占的比重,和TPC-C的标准符合,不需要变更。
参数设置如下:
db=postgres driver=org.postgresql.Driver conn=jdbc:postgresql://192.168.1.95:5866/benchmarksql user=benchmarksql password=benchmarksql warehouses=10000 loadWorkers=32 terminals=150 //To run specified transactions per terminal- runMins must equal zero runTxnsPerTerminal=0 //To run for specified minutes- runTxnsPerTerminal must equal zero runMins=30 //Number of total transactions per minute limitTxnsPerMin=0 //Set to true to run in 4.x compatible mode. Set to false to use the //entire configured database evenly. terminalWarehouseFixed=true //The following five values must add up to 100 //The default percentages of 45, 43, 4, 4 & 4 match the TPC-C spec newOrderWeight=45 paymentWeight=43 orderStatusWeight=4 deliveryWeight=4 stockLevelWeight=4 |
3)准备测试数据库
执行以下命令来准备测试用的数据库:
highgo=# CREATE USER benchmarksql WITH ENCRYPTED PASSWORD 'changeme'; highgo=# CREATE DATABASE benchmarksql OWNER benchmarksql; |
5、测试数据的加载
我们本次的测试,计划的数据规模是1万仓。为此,我们采用BenchmarkSQL生成数据,数据量在1TB左右,使用32个加载进程。
[root@node run]# pwd /opt/benchmarksql-5.0/run [root@node run]# nohup ./runDatabaseBuild.sh props.pg >> builddata.out 2>&1 & [root@node run]#tail -f builddata.out alter table bmsql_history add primary key (hist_id); # ------------------------------------------------------------ # Loading SQL file ./sql.postgres/buildFinish.sql # ------------------------------------------------------------ -- ---- -- Extra commands to run after the tables are created, loaded, -- indexes built and extra's created. -- PostgreSQL version. -- ---- vacuum analyze; |
在这个平台上,该过程可能要花几小时。
加载完成后,可以通过以下命令查看数据库大小,验证数据加载的准确性
# select pg_size_pretty(pg_database_size('benchmarksql')); pg_size_pretty ---------------- 998 GB (1 row) |
6、初始化数据库状态
在测试之前,为了充分保证初始状态的一致性,建议对数据库做一次analyze和checkpoint,并对系统清理缓存BUFF/CACHE,具体如下:
操作系统root下执行:
[root@tpcc-service0006 ~]# sync; echo 3 > /proc/sys/vm/drop_caches; |
数据库服务器运行:
highgo=# checkpoint; CHECKPOINT highgo=# analyze; ANALYZE highgo=# \q |
7、执行测试
执行测试:
[root@node2 run]# pwd /opt/benchmarksql-5.0/run [root@node2 run]# nohup ./runBenchmark.sh my_postgres.properties >> terminal_120t20f30c.out 2>&1 & [root@node2 run]# tail -f terminal_120t20f30c.out |
部署性能监控程序,方便收集系统资源占用情况:
[root@node2 opt]# pwd /opt [root@node2 opt]#./nmon -s10 -c600 -f -m /hgsoft/nmondata/ (根据实际调参数) |
8、测试结果统计
这样,我们得到HGDB数据库在华为云c6s.8xlarge.2类型服务器(第二代英特尔® 至强® 可扩展处理器:1个物理cpu,每个cpu有16个core,每个core超线程数为2,总计32vCPU;内存64GB;超高IO磁盘)单机运行1万仓TPC-C的结果:
数据库 | tpmC | 并发数 | Cpu% | User% | sys% | Wait% |
HGDB | 264,634.47 | 150 | 98% | 77.4 | 17.1 | 3.5 |
性能指标及详细输出见如下截图:



26.4万tpmC,这个结果可以说是一个非常普通的结果,相信大家按照上述的配置和步骤基本都能实现。不过,相对于我们订阅的服务器配置,这个结果是可以接受的(毕竟我们准备挑战的是分布式)。我们也相信通过高水平的调试,该单节点的吞吐量还可以进一步提升。
接下来,我们将以该配置的服务器作为数据节点,来构建瀚高分布式数据库HGDB Sharding。
三、瀚高分布式数据库HGDB Sharding
在我们进行分布式多节点数据库测试之前,先简单介绍一下瀚高分布式数据库HGDB Sharding。
瀚高分片数据库管理系统HGDB Sharding是一个支持多节点横向扩展的,适用于大规模OLTP应用场景的数据库解决方案。
在大规模OLTP应用系统的设计中,数据库服务器的扩展能力是一个无法回避的问题。当业务所需要的数据库事务吞吐量超过单个节点数据库处理能力的时候,就要考虑数据库的多节点扩展问题。
共享存储的数据库集群是传统多节点架构中较为常见的,以Oracle RAC最为著名。共享存储集群提供了多个数据库服务器共享同一个存储、管理同一份数据。它提供了数据库服务器之间的高可用性以及一定程度上的性能扩展性。由于共享存储集群中的各数据库共享同一块存储、管理同一份数据。所以,各个节点之间需要就数据的访问进行通信协调。这部分的负担限制了这一类架构的横向扩展性。以Oracle RAC为例,在实际环境中,8台服务器一般就是吞吐量扩展的极限。再增加服务器,各节点之间通信的成本会吞噬扩展性,整体吞吐量会不增反降。即便在8台之内,性能扩展比率也不是很高的。
要使得多节点数据库系统拥有良好的扩展性,突破节点数量的限制,就需要考虑非共享的分布式数据库解决方案。现有的多节点、非共享的分布式数据库系统,主要是用于OLAP业务场景的,典型的产品有Greenplum。但是,普通的非共享分布式数据库并不适合承担OLTP的任务,跨节点的事务可能需要两阶段提交以保证事务完整性、多节点之间的通信协调可能耗费扩展性,等等。市场上大多数非共享的分布式数据库系统都是用来做数据仓库,承担OLAP任务的。
HGDB Sharding是瀚高软件提供的一款采用多节点、非共享分布式架构的数据库。它被命名为Sharding,表明它是采用了数据分片技术,同时也是为了与传统分布式OLAP的数据库产品有所区分,它是针对大规模OLTP应用场景的解决方案。
HGDB Sharding是HGDB数据库的增强版本。它是由协调节点(CN0~CNm)和数据节点(DN1~DNn)构成。它们实际上是同一个软件版本介质,只是在安装配置时给予不同的配置参数而成为不同的角色。其中,数据节点是实际管理数据的节点,协调节点负责提供用户全局访问的入口。除了CN0节点之外,CN1~CNm节点实际上都可以看成是无状态的节点。CN0节点同时负责管理整个集群的信息。
HGDB Sharding的各节点部署架构如下:

协调节点CN负责提供全局服务:前端应用可以登录到各CN节点并得到全局的访问视图。在现有的版本中,只有CN0提供数据库的读写服务,而其它CN,从CN1到CNm目前只提供只读服务。
数据节点DN负责提供局部服务,也称之为分片服务。前端的应用如果登录到DNi的话,就只能访问DNi上的数据,也就是分片服务器上的数据。每个DN节点都是可读写的。不过,一般情况下不建议用户直接访问DN节点。我们为用户提供了扩展的JDBC作为应用开发的接口。在研发过程中,为其中使用的技术申请了专利,目前在受理中:

所有的协调节点CN与数据节点DN都是由数据库实例构成的。这也意味着一个物理的服务器设备可以运行多个数据库实例,也就是上述的CN或DN节点。不过,在实际的业务系统中,为了充分发挥系统的扩展性能,各个数据节点DN和协调节点CN将会被部署在不同的物理设备上。
HGDB Sharding的高可用通过数据库实例的实时物理复制来实现。其中,所有的DN节点和CN0节点都有各自的镜像节点,并且运行在分离的硬件平台上。一旦某个DN节点或CN0节点出现故障,高可用管理系统会把用户的数据库工作负载切换到其相应的镜像节点上。CN1~CNm节点实际上等同于无状态的节点,它们如果出现故障,可以就地或在其它物理节点上重建。这些也同样由高可用管理模块负责管理。HGDB Sharding的高可用管理模块是自带的,是以HGDB高可用方案为技术基础定制的。
四、HGDB Sharding的数据分片以及对测试数据的改造
HGDB Sharding的工作基础是数据分片。在此,我们简单介绍HGDB Sharding环境下的数据分片。
数据库表在HGDB Sharding中分为分片表和重复表两大类。所谓分片表,在一个单节点数据库中其实就是一张分区表,而在分布式数据库中,这些分区被不同的数据库工作节点(数据节点)所管理,因此成为分片表,以示区别。
哪些表设计成分片表,哪些表设计成重复表,这是由数据库的使用者、数据结构的设计者来决定的。在大规模OLTP应用中,我们考虑到单个数据库服务器节点的处理能力是有限的,随着业务规模增大,并发访问量的加大,对于数据库的压力终究会超出单个服务器的承载能力。我们的数据库表分片方案就是从应对这个问题开始的。
分片表:允许用户选取表中的一个字段(目前只支持单字段)作为分区字段,该分区字段的取值通过系统内置的散列函数将表分成若干个(与DN的节点数相同)分区。表的数据会根据分区被分散到这些数据节点(DN)上,由各个数据节点管理。需要被设计成分片表的数据库表具有如下特点:
表的行数随着业务规模增大而迅速增大;
表的行数随着访问量的增大而增大;
表的数据被频繁更新、承担高密度事务处理;
重复表:有一些表会被设计成同一张表的数据在每个数据节点(DN)各有一份,使得每个数据节点(DN)都能在本节点访问到内容一样的重复表。这主要是为了提升访问效率。需要被设计成重复表的数据库表具有如下特点:
表的行数基本不随业务规模的增大而增大;
信息相对固定,更新频率较低;
业务参与度较高,承担查询为主;
例如:

在这个案例中,用户表(customers)、订单表(orders)、订单明细(line items)这三张表的内容会随着业务量(用户数量、订单数量)的增长而增长。因此,把这三张表设计成分片表。
这里需要注意的是,在将这三张表设计成分片表的时候,我们选择的分区字段是customer,也就是客户表的键值。这是因为:customers, orders, line items这三张表在业务中经常关联,而关联的字段就是customer。以customer作为分区键,使得日常业务中逻辑相关的数据会被置于同一个分区/分片节点上。因此,这里就有一个table family(表族)的概念。在我们的例子中,customers, orders, line items这三张表,以customer字段作为分区字段构成了一个表族(table family)。
在这个例子中,还有一张名为products的产品表。这个产品表的内容一般不随着用户数、业务量的增长而增长,而且内容也相对固定。但是,产品表的业务参与度很大,几乎每项业务都会去读取、访问这个产品表。因此,产品表(products)将被设计成重复表,在每个数据节点(DN)保存内容相同的一份。
在HGDB Sharding中,我们允许一个数据库中定义多个table family。
回到TPC-C测试,我们对BenchmarkSQL工具业务数据库模式(数据结构)进行改造,并将建表语句改造成符合瀚高分布式数据库分片表和复制表语法结构的SQL,在CN节点上执行。改造内容如下:

根据BenchmarkSQL业务及数据结构情况,将BenchmarkSQL的bmsql_warehouse、bmsql_district、bmsql_customer、bmsql_history、bmsql_new_order、bmsql_oorder、bmsql_order_line、bmsql_stock设计为分片表;将BenchmarkSQL的bmsql_config、 bmsql_item设为重复表,结合分布式SQL语法,整理出改造后BenchmarkSQL建表语句如下:
-----------分片表建表语句----------- create table bmsql_warehouse ( w_id integer not null, w_ytd decimal(12,2), w_tax decimal(4,4), w_name varchar(10), w_street_1 varchar(20), w_street_2 varchar(20), w_city varchar(20), w_state char(2), w_zip char(9) ) partition by hash (w_id);
create table bmsql_district ( d_w_id integer not null, d_id integer not null, d_ytd decimal(12,2), d_tax decimal(4,4), d_next_o_id integer, d_name varchar(10), d_street_1 varchar(20), d_street_2 varchar(20), d_city varchar(20), d_state char(2), d_zip char(9) ) partition by hash (d_w_id);
create table bmsql_customer ( c_w_id integer not null, c_d_id integer not null, c_id integer not null, c_discount decimal(4,4), c_credit char(2), c_last varchar(16), c_first varchar(16), c_credit_lim decimal(12,2), c_balance decimal(12,2), c_ytd_payment decimal(12,2), c_payment_cnt integer, c_delivery_cnt integer, c_street_1 varchar(20), c_street_2 varchar(20), c_city varchar(20), c_state char(2), c_zip char(9), c_phone char(16), c_since timestamp, c_middle char(2), c_data varchar(500) ) partition by hash (c_w_id);
create table bmsql_history ( hist_id integer, h_c_id integer, h_c_d_id integer, h_c_w_id integer, h_d_id integer, h_w_id integer, h_date timestamp, h_amount decimal(6,2), h_data varchar(24) ) partition by hash (h_w_id);
create table bmsql_new_order ( no_w_id integer not null, no_d_id integer not null, no_o_id integer not null ) partition by hash (no_w_id);
create table bmsql_oorder ( o_w_id integer not null, o_d_id integer not null, o_id integer not null, o_c_id integer, o_carrier_id integer, o_ol_cnt integer, o_all_local integer, o_entry_d timestamp ) partition by hash (o_w_id);
create table bmsql_order_line ( ol_w_id integer not null, ol_d_id integer not null, ol_o_id integer not null, ol_number integer not null, ol_i_id integer not null, ol_delivery_d timestamp, ol_amount decimal(6,2), ol_supply_w_id integer, ol_quantity integer, ol_dist_info char(24) ) partition by hash (ol_w_id);
create table bmsql_stock ( s_w_id integer not null, s_i_id integer not null, s_quantity integer, s_ytd integer, s_order_cnt integer, s_remote_cnt integer, s_data varchar(50), s_dist_01 char(24), s_dist_02 char(24), s_dist_03 char(24), s_dist_04 char(24), s_dist_05 char(24), s_dist_06 char(24), s_dist_07 char(24), s_dist_08 char(24), s_dist_09 char(24), s_dist_10 char(24) ) partition by hash (s_w_id);
--------重复表建表语句----------- create table bmsql_config ( cfg_name varchar(30) primary key, cfg_value varchar(50) ) PARTITION BY REPLICATION;
create table bmsql_item ( i_id integer not null, i_name varchar(24), i_price decimal(5,2), i_data varchar(50), i_im_id integer ) PARTITION BY REPLICATION; |
五、分布式TPC-C测试
在本次测试中,我们动用了50台服务器进行1万仓的TPC-C测试,为每台服务器配备200G的超高IO存储,最终,每台服务器的价格为6.2188元/小时。

按照3年的计费方式会更优惠,每台服务器三年总费用为55,080元

(记下这个数字为后续成本计算做准备)
1、环境的准备
本次测试在华为弹性云上进行,其用到的服务器有:
50台服务器,规格为“通用计算增强型 | c6s.8xlarge.2 | 32vCPUs | 64GB”,用来安装和运行HGDB Sharding分布式数据库;
30台测试机,规格为“通用计算增强型 | c6s.4xlarge.2 | 16vCPUs | 32GB”,用来安装和运行BenchmarkSQL。
之所以订阅多台测试机,是为了避免单台测试机自身可能成为吞吐量的瓶颈。最终的测试结果是所有测试机所获得的吞吐量之和。
所有的服务器与测试机都在华为云内网中。
操作系统与数据库软件:
操作系统 | CentOS Linux release 7.4.1708 (Core) |
数据库 | 瀚高企业版分布式数据库HGDB Sharding |
测试工具 | BenchmarkSQL5.0 |
性能监控 | nmon_x86_64_rhel7 |
本次分布式数据库分别安装在50台规格为c6s.8xlarge.2的华为云ECS虚拟机上,每个DN节点对应一台虚拟机,其中CN0跟DN1装在了同一台虚拟机、CN1跟DN2装在了一台虚拟机上。CN0为读写节点,CN1为只读节点,DN1~DN50为可读写节点。
2、硬件参数配置
内核参数、关闭大页的操作均与单节点相同
3、数据库参数配置
数据库系统在设置参数的时候要分CN节点还是DN节点。
CN节点数据目录下的postgresql.conf文件做如下设置:
wal_level = logical max_wal_senders = 200 max_replication_slots = 200 max_connections = 4000 wal_keep_segments=100 checkpoint_timeout = 20min checkpoint_completion_target=0.9 |
DN节点数据目录下的postgresql.conf文件,需要在单节点基础上修改和增加如下参数的配置:
max_connections = 4000 max_prepared_transactions = 4000 |
max_connections:最大连接数是根据客户端的并发数进行计算的,每个客户端发起120个并发,共计30个客户端,共计产生3600个并发。
max_prepared_transactions:设置可以同时处于prepared状态的事务的最大数目,通常配置为与max_connections相同的值。
4、加载测试数据
分布式环境下,测试数据的加载有以下的步骤:
1)采用BenchmarkSQL生成1万仓测试数据(csv文件),约1TB。
2)使用“瀚高分布式加载工具”把数据加载到50节点的分布式系统内。
3)在“瀚高分布式建表工具”中执行BenchmarkSQL创建索引和外键的SQL脚本。
这样,就完成了数据的加载。
5、初始化数据库状态
初始化数据库状态需要每一个数据节点上执行与单节点相同的操作(如“第二段、第6节”所述)。
6、运行测试
1)首先,在benchmarksql-5.0安装路径/.../benchmarksql-5.0/lib/postgres内替换成瀚高分布式数据库增强接口:sharding-jdbc-EnhancedEdition-1.0-full.jar,并进行相应配置。
2)在30台BenchmarkSQL测试机同时执行以下命令开始测试:
[root@node2 run]# pwd /opt/benchmarksql-5.0/run [root@node2 run]# nohup ./runBenchmark.sh hgdbSharding.properties >> terminal_120t20f30c.out 2>&1 & [root@node2 run]# tail -f terminal_120t20f30c.out |
3)部署性能监控程序,以便分析收集系统资源占用情况:
[root@node2 opt]# pwd /opt [root@node2 opt]#./nmon -s10 -c600 -f -m /hgsoft/nmondata/ |
7、结果统计
这里是测试过程中每个客户端的截屏:
C1:

C2:

C3:

在此不一一列举,最后:
C30:

我们得到各客户端的结果列表:
BenchmarkSQL测试机 | tpmC(NewOrders) |
client1 | 379029.03 |
client2 | 368887.89 |
client3 | 374844.67 |
client4 | 366970.31 |
client5 | 383818.42 |
client6 | 369340.03 |
client7 | 301277.56 |
client8 | 307099.84 |
client9 | 364270.22 |
client10 | 340277.82 |
client11 | 309489.75 |
client12 | 339624.31 |
client13 | 378569.25 |
client14 | 335975.02 |
client15 | 340254.96 |
client16 | 345161.44 |
client17 | 321007.56 |
client18 | 367503.03 |
client19 | 341995.37 |
client20 | 338111.25 |
client21 | 368059.84 |
client22 | 376430.29 |
client23 | 344076.55 |
client24 | 359475.11 |
client25 | 365805.67 |
client26 | 372301.13 |
client27 | 363605.27 |
client28 | 365461.63 |
client29 | 343303.60 |
client30 | 363757.97 |
total | 10,595,784.79 |
我们得到最终的测试结果是:
数据库 | tpmC | 并发数 | CPU% | User% | sys% | Wait% |
分布式(50台) | 10,595,784.72 | 3600 | 76.2% | 60.3 | 15.5 | 0.4 |
通过观察CPU、IO、网络等资源的使用情况,可以看出系统性能并未达到最优。无限的提升空间,等您来突破!
至此,瀚高分布式数据库HGDB Sharding在华为云上动用了50个节点的c6s.8xlarge.2虚拟服务器,在1万仓的数据规模下,TPC-C吞吐量指标tpmC达到10,595,784.72,突破1千万大关。
我们再来计算性价比指标:根据TPC的官方文档:
http://tpc.org/tpc_documents_current_versions/pdf/tpc-c_v5.11.0.pdf
系统的成本需要包括运行数据库服务器的硬件、操作系统、数据库软件,以及整个系统3年的支持维护费用。由于我们的设备采用的是云计算,为此,我们需要以三年的订阅与服务来统计我们的系统成本:
项目 | 系统规格 | 单价 (3年期) | 节点数 | 总计 (人民币元) |
华为云 服务器 | c6s.8xlarge.2CPU:1个物理cpu、每个cpu有16个core,每个core超线程数为2,总计32vcpus内存:64GECS系统盘:通用型SSD|40GBECS数据盘:超高IO|200GB操作系统:CentOS Linux release 7.4.1708 (Core) | 55,080 | 50 | 2,754,000 |
瀚高分布式数据库 | 瀚高数据库节点单价参考央企采购名录,每个节点计人民币10万 50节点分布式数据库服务,按节点进行计费 | 10,0000 | 50 | 5,000,000 |
瀚高分布式数据库技术支持 | 第一年免服务费,从第二年开始收产品15%的服务费。 | 30,000 | 50 | 1,500,000 |
系统总价(元) | 9,254,000 | |||
TPC-C吞吐量tpmC | 10595784.72 | |||
性价比(price/tpmC) | 0.8733661776397435元 |
六、结果分析与点评
我们从几个方面来点评本次的测试结果:
1、分布式的扩展性
我们采用分布式的数据库,其目的就是为了比单机提供更大的事务处理吞吐量,支撑更大规模的并发用户数。那么,在理想状态下,采用N个节点的数据库,其吞吐量应该是单节点的N倍。
在我们的测试结果中,50节点的服务器,tpmC值的输出达到10,595,784.72,而相应的单节点测试tpmC值是264634.47。
10595784.72 / (264634.47 x 50) = 0.8008
也就是说,本系统的线性扩展性达到80%。考虑到我们采用了两阶段提交机制维护分布式环境下的事务完整性,这个扩展性在目前市场上分布式OLTP数据库中是非常高的。
2、与TPC的历史排名的比较
我们去看一下TPC的官方网站:http://tpc.org
目前,根据性能指标排名,TPC-C的结果是:
http://tpc.org/tpcc/results/tpcc_perf_results5.asp?resulttype=all

我们可以看到,排在最前面的是阿里/蚂蚁金服的OceanBase在2019和2020年做的创纪录的测试。从第三开始,是来自韩国的Goldilocks数据库。目前,国内的公司科蓝在推该款数据库。不过,Goldilocks在此列出的tpmC值并不出众,单机服务器最高在380,475,38万多。用一个高端一点的x86服务器应该比较容易达到。
这也说明近年来世界上著名的大厂已经好久不做TPC-C测试了。在此,我们勾选一下右边的方框“Include Historical Results”,看看整个历史上(包括已经失效的测试结果)tpmC的排名是什么样的:
http://tpc.org/tpcc/results/tpcc_results5.asp?print=false&orderby=tpm&sortby=desc

从这里,我们可以看到,排在OceanBase之后的是Oracle在2011年6月1日的30,249,688、IBM DB2在2010年10月13日的10,366,254,以及Oracle在2013年9月25日的8,552,523。
那么,我们今天的结果,10,595,784.72,超过了IBM DB2在2010年10月13日的10,366,254,在TPC-C的历史上排名第四。
事实上,在今天的市场上,关系数据库系统的tpmC值超过500万就已经能够支撑几乎所有的高强度的OLTP应用。因此,传统的数据库大厂如Oracle、IBM等,在早年超越500万tpmC之后就很少再做类似的测试了。
今天,瀚高的HGDB Sharding使用了50台普通配置的华为云c6s.8xlarge.2虚拟服务器,突破了1000万tpmC大关。这说明瀚高分布式数据库足以承担各种大型企业级OLTP应用。
再让我们来看看性价比指标,在tpmC超过500万的历史案例中,性价比排在前面的是(tpmC排名第一的)蚂蚁金服OceanBase的3.98人民币,以及tpmC排名第5的Oracle SPARC T5-8的0.55美元。
而今天,瀚高HGDB Sharding的Price/TpmC达到了1元人民币之内(0.87元),这在TPC历史上500万tpmC的系统中尚属首次!这也体现了瀚高分布式数据库在云计算环境下业界领先的性价比优势。
3、您也能做到的结果
有人可能会质疑,瀚高提供的这个测试结果并没有得到TPC委员会的认可,它不在TPC公布的结果中。确实是这样,瀚高提供的这个分布式数据库的测试结果,是瀚高工程师团队在华为云上网测的结果。但我们想要与大家分享的是:这个结果是大家都能做得到的结果,是我们每个人看得见、摸得着的结果。
曾几何时,TPC网站所公布的测试结果离我们很远。如果时光倒流回2010年,IBM DB2就公布了在Power 780上跑出了10,366,254 tpmC的结果。在那个年代,国内拥有Power 780的客户也不少,可谁敢想象自己的Power 780上能让DB2的TPC-C值突破1000万?能跑出100万的都没几个。TPC的官方结果对于我们普通用户都属于天文数字,那是一个专业的竞技场,不属于我们日常的生产环境。
而今天,瀚高数据库分享给大家的,是我们每个人看得见、摸得着、而且是触手可及的结果。它体现了国产数据库在近几年快速发展的步伐。
我们选用国内的云计算厂商的服务,订阅了价格低廉的服务器,安装了自主研发的数据库产品,仅仅做最简单的调优,目的是希望这样的工作在我们绝大多数客户那里都可以由他们自行完成。然后,我们跑出一个结果,这个结果能够在TPC-C的历史纪录中占有一席之地,能够挑战我们近30年来在市场上所熟知、所仰慕的世界级数据库大厂。TPC-C头部的结果从此不再是空中楼阁,不再是大厂的专利,不再是巨额资金的堆积,而是我们日常工作的一部分。
我们暂时没有计划向TPC申请认证我们的结果,我们也没有计划花费资金去获得专业机构的认证。我们只希望把这个测试过程分享给大家,我们的口号是:“您也能做到!”。如果各位对我们分享的测试结果感兴趣,可以上华为云的订阅网站:
https://www.huaweicloud.com/
订阅虚拟服务器。我们也欢迎其他云计算厂商与我们合作,让我们有机会体验瀚高分布式数据库在各个云计算平台上的表现。
联系瀚高基础软件有限公司(7*24热线400-708-8006),我们会提供给大家瀚高分布式数据库HGDB Sharding的试用版本。
大家可以按照本文中所述的步骤(详细的操作文档将随试用版一同提供),重复测试的过程。
如果您的测试结果比我们做得好,请您务必联系瀚高软件,我们的技术团队及负责人将登门拜访,向您请教数据库优化的技巧。
如果您的测试达不到我们所说的结果,也请您务必联系瀚高软件,我们会安排技术团队帮助您达到我们曾经做到的结果。
瀚高软件全体同仁会不懈努力,为市场提供有份量的国产数据库产品。




