
日前,阿里云PolarDB云原生数据库以超越原记录2.5倍的性能一举登顶TPC-C基准测试排行榜,以每分钟20.55亿笔交易(tpmC)和单位成本0.8元人民币(price/tpmC)的成绩刷新TPC-C性能和性价比双榜的世界纪录。
每一个看似简单的数字背后,都蕴含着无数技术人对数据库性能、性价比和稳定性的极致追求,PolarDB的创新步伐从未止步。「阿里云瑶池数据库」公众号特此推出「PolarDB登顶TPC-C技术揭秘」系列硬核文章,为你讲述“双榜第一”背后的故事,敬请关注!
本文为系列连载第5篇——弹性并行查询(ePQ)篇。


查询数据仅涉及单个节点,比如TPC-C中交易类查询,这类查询直接路由至对应节点完成计算。 查询数据涉及多个或所有节点,比如TPC-C审计中的部分查询,这类查询由ePQ并行计算引擎完成分布式查询。

ePQ并行计算引擎为PolarDB提供了具备极致扩展能力的分布式执行框架,在一写多读形态中,由于是共享存储,任意节点均可以访问到全部数据,ePQ并行计算的子任务可以被调度到任意节点运行,调度器主要考虑因素为资源负载。但在PolarDB多主分区表形态中,每个物理分区的访问由对应节点负责,ePQ并行计算引擎同样可以感知数据的分布属性,基于代价生成最优的分布式执行计划。

2.1 整体架构
PolarDB ePQ的目标是打通集群计算层的计算资源,基本原理是将一个复杂查询任务拆分为多个子任务,子任务可以被派发到同集群内的任意节点执行计算,有效利用集群内其它节点空闲计算资源(CPU、 内存等)来加速查询。PolarDB ePQ功能属于内核特性,任意节点都可以提供完整的服务,如下图是从内核视角看到的弹性并行查询的架构图:

PolarDB ePQ架构图
并行优化器(PQ Optimizer),在串行计划的基础上做信息提取,然后基于代价的枚举拆分出最优的子计划切片(Plan Slices)。 全局资源视图(Global Resource View),维护集群内所有节点的实时负载信息,方便协调器快速找出有空闲计算资源的节点。 任务协调器(Coordinator),根据实时资源负载情况,从任务队列中调度执行。 弹性并行执行器(Parallel Execution Engine),负责将被调度的子计划切片(Plan slices)生成对应的Physical Plan,然后交给Executor模块执行。如果是远程节点执行,还需要将Phsical Plan序列化,通过内部网络通道传输到远程节点上执行。 资源管理器(Resource Manger),提供限制并行查询使用资源上限的能力,比如当CPU使用率超过了70%就不再选择并行执行。 基于共享存储的跨机并行架构,可以保证查询结果的实时性,并在跨节点一致性视图机制的保证下,子任务在任意节点执行都能读取到正确的数据。
2.2 并行优化器
并行优化器(PQ Optimizer) ,在串行计划的基础上做信息提取,然后基于代价的枚举拆分出最优的子计划切片(Plan Slices)。
并行优化是一个自底向上,基于动态规划的穷尽式枚举过程,在过程中会针对每个算子,枚举可能的并行执行方式和数据分发方式,并基于输出数据的Physical Property(distribution + order)构建物理等价类,从而做局部剪枝,获取局部子问题的最优解并向上层传递,最终到root operator获取全局最优解。
以下是针对t1 NLJ t2这个算子,做枚举过程的一个简要示例:

在整体枚举完成后,计划空间中会产生一系列带有数据分发Exchange Enforcer
的物理算子树,基于代价选择最优树即可,然后以Enforcer作为子计划的切分点,可以构建出一系列的执行计划抽象描述,输出到plan generator
中。
2.3 分布式执行引擎
执行引擎主要负责任务的派发、执行、和状态管理。 接受客户查询的线程称为leader线程,它负责将并行查询任务派发到各个节点上,每个远程节点还会有一个migrantleader线程,远程节点的workers任务由各自的migrant leader来管理,leader负责管理migrant leader和本地的workers,这样一个两级分组式管理的模式,好处是最大限度的减少了远程信令控制通道的传输内容和频次。

引擎中的通信通道有2种,一个是负责任务派发和worker状态收集的信令控制通道,它是一个双向的异步消息通道。另一个数据通道只负责传输worker的结果数据,是一个单向的传输通道,虽然传输方向是单向的,但需要支持多种数据shuffle方式,比如repartition/broadcast等,而且需要同时支持本地和远程跨机两种模式。
引擎的数据驱动模型采用的是Pull模式,这样可以灵活嵌入到MySQL的火山执行引擎中,另外pull模式的优势是数据实时性高,能做到极致的流水线处理。
2.4 自适应调度
因为是共享存储架构,理论上可以将并行任务调度到任意节点执行,但并行查询的目标是利用空闲计算资源进行加速,并且不能对客户线上业务造成负面影响。
全局资源视图模块主要负责维护实时的节点负载信息,每个节点负责采集自己的工作负载信息,比如CPU/IO、Memory等,然后将负载信息用UDP协议广播给其它所有节点,两两互相广播后,所有节点都维护了一份各个节点的资源视图列表。
Adaptive available factor机制避免资源争抢,原理是为每个节点设置一个可用比率factor,假设发现一个节点剩余可用资源为100,初始factor是个保守值,比如是20%, 那最多只使用这个节点空闲资源的20%,当检测到连续n秒资源使用率依然没有超过阈值,则逐渐提升factor比率。当一旦发现该节点资源超过预期,则将factor快速下调,这样一个慢启动快回调的自适应调整机制,来实现一个尽量的动态平衡。

基于负载的自适应调度



3.1 并行JOIN优化
Parallel NestLoop JOIN Parallel Hash JOIN Parallel Partition-wise JOIN

TPC-C Consistency 1中查询SQL
3.2 Partition-wise Materialize优化
当查询语句中有派生表且要参数JOIN时,一般的做法是先并行物化,然后再将物化表作为广播表广播到其它节点参与JOIN,当物化表结果集比较大,需要广播给上千个节点,性能损耗非常大,而且在shuffle过程中还有单点瓶颈问题,TPC-C Consistency审计中就有多个这类场景,比如consistency2中查询:
select t1.d_w_id, t1.d_id, t1.max_o_id1, t2.max_o_id2, t3.max_o_id3
from
(select d_w_id, d_id, d_next_o_id - 1as max_o_id1
from bmsql_district) t1,
(select o_w_id, o_d_id, max(o_id) as max_o_id2
from bmsql_oorder
groupby o_w_id, o_d_id) t2,
(select no_w_id, no_d_id, max(no_o_id) as max_o_id3
from bmsql_new_order
groupby no_w_id, no_d_id) t3
where t1.d_w_id = t2.o_w_id
and t1.d_w_id = t3.no_w_id
and t1.d_id = t2.o_d_id
and t1.d_id = t3.no_d_id
and (t1.max_o_id1 != t2.max_o_id2 or t1.max_o_id1 != t3.max_o_id3 or t2.max_o_id2 != t3.max_o_id3);
t2和t3两个物化表内部有group by算子,不支持展开,只能先进行物化再进行JOIN,为提升此类查询性能,ePQ支持了Partition-wise Materialize,将物化下推到各个节点分开物化,不仅避免了数据跨机shuffle的开销,也避免了gather到leader节点再广播的单点瓶颈问题,做到了更充分的并行。

TPC-C Consistency 2查询使用Partition-wise Materialize

TPC-C测试考察的是交易类业务场景,ePQ作为并行执行框架,线上业务主要应用于轻分析类查询加速,查询加速比是评估并行查询性能非常重要的指标,在相同的计算资源情况下,并行对比原串行的加速比,如下是TPC-H 100G数据量的加速比测试。

测试实例规格为16c128G主从2节点,开启ePQ,TPC-H中22条SQL均可以并行加速,平均加速比为22.5倍。因为ePQ支持分布式多机并行,水平扩容节点还可以继续线性加速,下面测试了更大数据量(TPC-H 1T)在水平扩容场景下的线性加速能力。

其中22条SQL全部支持多机并行,17条可以继续线性加速。

从用户视角看,云原生数据库最核心的价值是提供低运维成本的可弹性扩展的数据库服务,让用户可以更多专注自身业务上,关键是随着用户数据体量日益增长,依旧能提供稳定可预期的查询性能,让用户业务可持续稳定的获取关键数据insight,最大化提升业务价值。如果随着用户数据增长,报表分析类查询性能逐渐衰退,即便是扩容资源也无法改善是用户无法接受的,支持并行查询,提供可弹性扩展的线性加速能力是云原生数据必须具备的能力。

点击免费体验 PolarDB 弹性并行查询ePQ







