TPCC测试究竟意味着什么

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 最近分布式数据库领域可谓非常之火(也可能是非常之卷),特别的,很多人会关注TPCC的测试结果,也有不少产品会投入很多精力在TPCC的优化上。我们首先需要搞明白的是,我们从TPCC的测试结果,究竟能得出对这个分布式数据库什么样的评价。

最近分布式数据库领域可谓非常之火(也可能是非常之卷),特别的,很多人会关注TPCC的测试结果,也有不少产品会投入很多精力在TPCC的优化上。

我们首先需要搞明白的是,我们从TPCC的测试结果,究竟能得出对这个分布式数据库什么样的评价。

TPCC代表了什么

undefined

TPCC的业务场景其实很简单,本文中我们关注其中几个重要的概念即可:

  1. 仓库(Warehouse),有很多的仓库,每个仓库有很多的商品(Item),每个商品在每个仓库有自己的库存数目。仓的数目很多,比如一般测试都是1000仓起步(这个与一些电商平台是不一样的,例如淘宝,核心单元可能就个位数)。
  2. 买家(Customer),绝大多数情况下,买家只会从绑定的一个仓库买东西;少数情况下,买家才会从其他仓库买东西

基于这样的业务特征,所以在数据库的设计上,很容易想到将数据库按照仓库的ID(wid)进行分片。这种分片可以确保大多数的事务可以在单个分片内完成。

例如假设我们有这样一份TPCC的测试报告:

  • TPMC:100,000,000(1亿)
  • 数据库使用机器:222台(Intel Xeon Platinum 8163,42C84T712G)
  • Transaction Mix Percent Number

    • New-Order 45%

      • Percentage of Home order-lines 99.000%
      • Percentage of Remote order-lines 1.000%,每个订单有10个商品,所以有10%的下单涉及到分布式事务
    • Payment 43%

      • Percentage of Home Transactions 85%
      • Percentage of Remote Transactions 15%
    • Order-Status 4%
    • Delivery 4%
    • Stock-Level 4%

我们可以做如下的解读:

  1. TPMC就是指每分钟下单(New-Order)的数量。是一般情况大家最关注的指标,也是TPCC官方进行性能排名使用的指标。
  2. 下单和支付(Payment)两种事务的数量,占了总事务量的45%+43%=88%。
  3. 90%的下单操作是单机事务,85%的支付操作是单机事务,分布式事务合计占比45%*10%+43%*15%=11%。整个集群分布式事务的TPS是:100,000,000*11%/60=18万TPS
  4. 按机器数做下平均,每台机器贡献的单机TPMC是1亿/222*89%=40万,分布式TPMC是1亿/222*11%=5万,加起来是45W

可以看出,TPCC中,TPMC指标中最大头是单机事务贡献的。但是,这种单机事务其实是无法体现分布式特有的一些问题的,例如,节点之间无需互相传递数据,也无需对事务的状态进行协调等。

这里的第一个结论是,TPCC可以很好的体现一个数据库的单机性能,但是它无法很好的体现一个分布式数据库的分布式事务能力(性能、扩展性,甚至在一些不严格的测试中,连一致性也无法验证)

如果真的像TPCC一样,严格控制分布式事务的使用,对业务来说代表了什么?

代表业务永远都要去考虑分区键这个东西,只有业务能划出很统一的分区键,才能尽可能的去减少分布式事务。

无论一个分布式数据库号称多么“先进”,只要它需要你去设计分区键,那其实它就是个“伪”分布式数据库。使用这样的数据库,和使用分库分表中间件+单机数据库没有太明显的区别。

事实上,分库分表中间件+单机数据库除了这11%的分布式事务无法实现,TPCC的其他指标诸如性能、扩展性都能做的很好。只要加足够多的机器,一样能跑到很高的TPMC,这个过程会是非常线性的。只是那11%的分布式事务,阻止了分库分表+单机数据库的方案。

这里的第二个结论是,如果你的业务愿意像使用中间件“谨慎并良好的设计每个表的分区键,避免分布式事务”一样去使用分布式数据库,那么每台机器承载的TPMC(上例中的45万)是很好的参考依据,集群的总TPMC(上例中的1亿)并没有太大的参考价值

如果要看单机TPMC,我们可以与一些传统单机数据库做下对比,其单机能达到的TPMC是什么样的水平呢,我们找几份数据看一下。

  • 数据1:

这一份对官方的PG11做的测试(https://developer.aliyun.com/article/698138),在类似的机器配置中,可以跑到103W的TPMC。

  • 数据2:

TPCC官方榜单上有很多单机数据库的数据,其TPMC普遍在百万级以上(甚至是十多年前的古董级CPU)。

这样看起来非常巨大的数字(1亿TPMC),比较下来,除了机器规模着实吓人之外,和中间件+单机数据库比似乎并没有什么优势。更别说,为了提升TPMC,通常还会使用存储过程来封装TPCC的事务,而这种用法对一般业务来说侵入性太强,很少场景会使用。

也许你会说,还有11%的分布式事务呢,这是中间件+单机的方案解决不了的。

这里的问题是,11%的分布式事务一定代表着强依赖分区键,我想,大多数业务应该不想总是要想着分区键的概念吧,因为这个东西实在太难选了。

诚然,TPCC的模型对分区键的选择是非常非常友好的,每个主要(ITEM\WAREHOUSE\CUSTOMER\ORDER)的表都能按照WAREHOUSE ID进行分区。但在实际的业务中,你会发现情况远比这个复杂的多,比如:

  1. 很多电商系统的订单表会有两个查询维度,卖家和买家,选哪个当分区键?
  2. 做社保系统,缴费表按照人的id和按照企业的id去查都很常见,选哪个当分区键?
  3. 有一堆的业务代码需要去改,在SQL里带上分区键,这怎么改?

...

自然,我们想知道,什么样的技术,才能让你“忘掉”分区键这个东西呢。

二级索引与分区键

广义的“分区键”的概念,其实并不是分布式数据库特有的。

我们在单机数据库中,例如MySQL中,数据存储成了一棵一棵B树。如果一个表只有主键,那它只有一棵B树,例如:

CREATE TABLE orders(
    id int,
    seller_id int,
    buyer_id int,
    primary key (id)
);

这个表唯一的B树是按照主键(id)进行排序的。如果我们的查询条件中带了id的等值条件例如where id=1,那么就可以在这棵树上快速的定位到这个id对应的记录在哪里;反之,则要进行全表扫描。

B树用于排序的Key,通过二分查找可以定位到一个叶子节点;分区键通过哈希或者Range上的二分查找,可以定位到一个分片。可以看出它们都是为了能快速的定位到数据。

如果我们要对上面的表做where seller_id=1来查询,在MySQL中,我们并不需要将seller_id设为主键。更加自然的方式是,在seller_id上创建一个二级索引:

CREATE INDEX idx_seller_id ON orders (seller_id);

每个二级索引在MySQL中都是一棵独立的B Tree,其用于排序的Key就是二级索引的列。

也就是说,当前t1这张表,有两颗B Tree了,主键一棵,idx_seller_id一棵,分别是:

id->seller_id,buyer_id
seller_id->id

当使用where seller_id=1进行查询是,会先访问idx_seller_id这颗B树,根据seller_id=1定位到叶子节点,获取到id的值,再使用id的值到主键那颗B树上,找到完整的记录。

二级索引实际上是通过冗余数据,使用空间与提升写入的成本,换取了查询的性能。

同时,二级索引的维护代价并不是非常的高,一般情况下可以放心的在一个表上创建若干个二级索引。

同理,在分布式数据库中,想让你“忘掉”分区键这个东西,唯一的方法就是使用分布式二级索引,也称为全局索引(Global Index)。并且这个全局索引需要做到高效、廉价、与传统二级索引的兼容度高。

全局二级索引

我们在数据分布解读(一)中介绍过全局索引:

Global Index,也称为全局索引,由一组同构的Partition构成。
Global Index包含两种类型的字段,Key字段与Covering字段,Key字段为索引字段,其余字段为Covering字段。
Global Index有Partition Key与分区算法两个属性,其Partition Key是Global Index的Key字段。
......
对于Key字段的查询,CN可以直接定位到对应的Partition。

全局二级索引同样也是一种数据冗余。例如,当执行一条SQL:

INSERT INTO orders (id,seller_id,buyer_id) VALUES (1,99,1000);

如果orders表上有seller_id这个全局二级索引,可以简单理解为,我们会分别往主键与seller_id两个全局索引中执行这个insert,一共写入两条记录:

INSERT INTO orders (id,seller_id,buyer_id) VALUES (1,99,1000);
INSERT INTO idx_seller_id (id,seller_id) VALUES (1,99);

其中orders主键索引的分区键是id,idx_seller_id的分区键是seller_id。

同时,由于这两条记录大概率不会在一个DN上,为了保证这两条记录的一致性,我们需要把这两次写入封装到一个分布式事务内(这与单机数据库中,二级索引通过单机事务来写入是类似的)。

当我们所有的DML操作都通过分布式事务来对全局索引进行维护,我们的二级索引和主键索引就能够一直保持一致的状态了。

好像全局索引听起来也很简单?

实则不然,一个可以广泛使用的全局索引,以下条件缺一不可,不然只能是个玩具。

索引的强一致性、高性能与分布式事务

索引一定要是强一致的,例如:

  • 不能写索引表失败了,但是写主表成功了,导致索引表中缺数据
  • 同一时刻去读索引表与主表,看到的记录应该是一样的,不能读到一边已提交,一边未提交的结果
    ...

这里对索引的一致性要求,实际上就是对分布式事务的要求。

由于全局索引的引入,100%的事务都会是分布式事务,对分布式事务的要求和“强依赖分区键类型的分布式数据库”完全不同了,要求变得更高:

  1. 至少需要做到SNAPSHOT ISOLATION以上的隔离级别,不然行为和单机MySQL差异会很大,会有非常大的数据一致性风险。目前常见的方案是HLC、TrueTime、TSO、GTM方案,如果某数据库没有使用这些技术,则需要仔细甄别。
  2. 100%的分布式事务相比TPCC模型10%的分布式事务,对性能的要求更高,HLC、TSO、TrueTime方案都能做到比较大的事务容量,相对而言,GTM由于更重,其上限要远远低于同为单点方案的TSO(TSO虽然是单点,但由于有Grouping的优化,容量可以做的很大)。
  3. 即使用了TSO/HLC等方案,优化也要到位,例如典型的1PC、Async Commit等优化。不然维护索引增加的响应时间会很难接受。

与单机索引的兼容性

单机数据库中,索引有一些看起来非常自然的行为,也是需要去兼容的。

例如:

  • 能通过DDL语句直接创建索引,而不是需要各种各样的周边工具来完成。
  • 前缀查询,单机数据库中,索引是可以很好的支持前缀查询的,全局索引应该如何去解这类问题?
  • 热点问题(Big Key问题),单机数据库中,如果一个索引选择度不高(例如在性别上创建了索引),除了稍微有些浪费资源外,不会有什么太严重的问题;但是对于分布式数据库,这个选择度低的索引会变成一个热点,导致整个集群的部分热点节点成为整个系统的瓶颈。全局索引需要有相应的方法去解决此类问题。

面向索引选择的查询优化器

我们知道,数据库的优化器核心工作机制在于:

  1. 枚举可能的执行计划
  2. 找到这些执行计划中代价最低的

例如一个SQL中涉及三张表,在只考虑左深树的情况下:

  • 在没有全局索引的时候,可以简单理解为,执行计划的空间主要体现在这三张表的JOIN的顺序,其空间大小大致为3x2x1=6。执行计划的空间相对是较小的,优化器判断这6个执行计划的代价也会容易很多。(当然优化器还有很多工作,例如分区裁剪等等,这些优化有没有索引都要做,就不多说了)。
  • 在有全局索引的时候,情况就复杂多了。假设每个表都有3个全局索引,那执行计划空间的大小大致会变成(3x3)x(2x3)x(1x3)=162,这个复杂度会急剧的上升。相应的,对优化器的要求就会高的多。优化器需要考虑更多的统计信息,才能选择出更优的执行计划;需要做更多的剪枝,才能在更短的时间内完成查询优化。

所以我们可以看到,在没有全局索引的“分布式数据库”或者一些中间件产品中,其优化器是很羸弱的,大多是RBO的,它们根本就不需要一个强大的优化器,更多的优化内容实际上被单机优化器给替代了。

其他

索引的创建速度,索引回表的性能,索引的功能上的限制,聚簇索引,索引的存储成本等等,其实也都极大的影响了全局索引的使用体验,这里鉴于篇幅原因,就不继续展开了。

索引的数量

对全局索引的这些要求,本质来源于全局索引的数量。

透明性做的好的数据库,所有索引都会是全局索引,其全局索引的数量会非常的多(正如单机数据库中一个表一个库的二级索引数量一样)。数量多了,要求才会变高。

而,这些没有全做好的分布式数据库,即使有全局索引,你会发现它们给出的用法依然会是强依赖分区键的用法。

它们会让创建全局索引这件事,变成一个可选的、特别的事情。这样业务在使用全局索引的时候会变的非常慎重。自然,全局索引的数量会变成的非常有限。

当全局索引的数量与使用场景被严格限制之后,上述做的不好的缺点也就变得没那么重要了。

PolarDB-X的透明分布式

PolarDB-X实现了非常优秀的分布式事务与全局索引,满足上文提到了对全局索引的要求,做到了透明分布式。

在透明分布式模式下(CREATE DATABASE中指定mode='auto'),所有的索引都是全局索引,应用无需关心分区键的概念。

例如,我们的建表语句,与单机MySQL完全一致,并不需要指定分区键:

create table orders (
   id bigint, 
   buyer_id varchar(128) comment '买家', 
   seller_id varchar(128) comment '卖家',
   primary key(id),
   index sdx(seller_id),
   index bdx(buyer_id)
)

undefined

创建全局索引也与单机MySQL创建二级索引的体验一致,全程是Online的:

CREATE INDEX idx_seller_id ON orders (seller_id);

PolarDB-X的全局索引是强一致的,其数据一致性体验与单机MySQL没有明显差异,提供了符合MySQL语义的RC与RR的隔离级别。

同时,PolarDB-X在索引的维护、优化器上也做了大量的工作,确保索引能高效的创建、维护,优化器能正确的生成使用索引的执行计划。

PolarDB-X的分区算法,也能很好的处理索引中产生的热点、数据倾斜等问题,参考:https://yuque.antfin.com/coronadb/kaswnf/ixsvfi

结语

我们的结论是:

  • TPCC的业务逻辑非常契合分库分表的架构,90%的事务是单机事务。对于TPCC的测试结果,建议更多的关注其平均到每台机器的TPMC。
  • 使用全局索引的数据库,才有可能做到真正的透明;没有全局索引的数据库,和分库分表没有本质区别,都要应用自己去设计分区键。
  • 全局索引的写入必然是分布式事务,对分布式事务的性能、一致性有很高的要求。对于一个透明的分布式数据库,100%的事务都是分布式事务。
  • 全局索引的数量很关键,透明的分布式数据库,所有索引都是全局索引,数量会非常多。

需要指定分区键的分布式数据库在五六年前还是比较流行的,但在现代,透明分布式是一个合格的分布式数据库必须提供的能力。

它能够极大的减轻应用的迁移成本,例如不需要修改应用中的SQL带上分区键,不需要为每个表都设计一个分区键等;同时,也能极大的减轻开发人员的学习成本,让开发人员能将精力集中在满足业务需求上,例如,可以沿用使用单机数据库时SQL优化的经验,通过加索引的手段去改善SQL的执行性能。

相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
目录
相关文章
|
OceanBase 存储 数据库
蚂蚁金服OceanBase挑战TPCC | TPC-C基准测试之存储优化
OceanBase的TPC-C测试技术解读第五篇
3507 0
蚂蚁金服OceanBase挑战TPCC | TPC-C基准测试之存储优化
|
OceanBase 数据库 存储
|
存储 数据库 SQL
蚂蚁金服OceanBase挑战TPCC | TPC-C基准测试之SQL优化
蚂蚁金服自研数据库 OceanBase 登顶 TPC-C 引起业内广泛关注,为了更清楚的展示其中的技术细节,我们特意邀请 OceanBase 核心研发人员对本次测试进行技术解读。
1641 0
蚂蚁金服OceanBase挑战TPCC | TPC-C基准测试之SQL优化
|
数据库 OceanBase 测试技术
蚂蚁金服OceanBase挑战TPCC | 测试流程解析
蚂蚁金服自研数据库 OceanBase 登顶 TPC-C 引起业内广泛关注,为了更清楚的展示其中的技术细节,我们特意邀请 OceanBase 核心研发人员对本次测试进行技术解读。
6017 0
蚂蚁金服OceanBase挑战TPCC | 测试流程解析
|
OceanBase SQL 数据库
蚂蚁金服OceanBase挑战TPCC丨TPC-C基准测试之链路层优化
本篇文章是 OceanBase 的 TPC-C 测试技术解读的最后一篇,为方便阅读,我们将系列文章整理成PDF电子书发布在“蚂蚁金服科技”官方公众号上。
3006 0
|
弹性计算 关系型数据库 测试技术
PostgreSQL 11 1Kw TPCC , 1亿 TPCB 7*24 强压耐久测试
标签 PostgreSQL , tpcc , tpcb 背景 TPCC, TPCB是工业标准的OLTP类型业务的数据库测试,包含大量的读、写、更新、删除操作。 7*24小时强压耐久测试,主要看数据库在长时间最大压力下的 性能、稳定性、可靠性。
2270 0
|
弹性计算 关系型数据库 测试技术
PostgreSQL 11 1000亿 tpcb、1000W tpcc 性能测试 - on 阿里云ECS + ESSD (含quorum based 0丢失多副本配置与性能测试)
标签 PostgreSQL , pgbench , tpcb , tpcc , tpch 背景 https://help.aliyun.com/knowledge_detail/64950.html 阿里云ESSD提供了单盘32TB容量,100万IOPS,4GB/s读写吞吐的能力,单台ECS可以挂载16块ESSD盘,组成512 TB的大容量存储。
3167 0
|
弹性计算 关系型数据库 测试技术
PostgreSQL 11 tpcc 测试(103万tpmC on ECS) - use sysbench-tpcc by Percona-Lab
标签 PostgreSQL , tpcc 背景 环境 阿里云虚拟机 [root@pg11-test ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: ...
4385 0
|
弹性计算 关系型数据库 测试技术
|
14天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
49 3
下一篇
无影云桌面