新型并行集群QD理论
1 简介
1.1 定义、首字母缩写词和缩略语
- Master:管理节点,系统的访问入口,其处理客户端连接的访问以及用户提交的SQL语句。
- Segment:计算节点,是数据真正存储和查询处理的地方。
- Gnet:集群内部进行数据交换的通道。
- QD:QueryDispatcher,负责创建、分发查询计划,汇总呈现最终结果。
- QE:QueryExecutor,负责完成自身部分的处理工作以及与其它处理线程之间交换中间结果。
- Motion:QE和QD之间以及QE和QE之间数据移动的操作。
- Slice:一个移动操作将计划分成了两部分,每部分称为一个Slice。
- Gang:所有节点上处理相同Slice的QE的集合称为Gang。
- 并行度:一个节点内处理同一个Slice的QE的个数(greenplum通过在一个segment上部署多个instance达到并行的目的)。
- 表切片:集群为了节点内可以由多个处理线程并行执行,将表在一个节点内分为多个子表,每个子表为一个切片。一个并行线程处理一个或者多个表切片。
1.2 什么是QD?
这里提到的QD(QueryDispatcher)是参考greenplum对于集群的设计而来的,greenplum将对于语句的执行分为两个部分,分别为QD和QE,QD负责将用户输入SQL语句进行词法、语法分析、语义的检查、并根据Query结构生成对应的Plan,然后QE负责将下发下来的Plan执行,并根据需要交换中间结果。
2 QD + QE vs xCluster
2.1 执行计划分发方式
- 原有的xCluster作为一款调度节点的中间件产品,在执行用户的语句过程中,与各个节点交互通过SQL方式进行,优点是具备强大的解藕能力,可以方便的替换节点,保证尽可能小的改动量,缺点比较明显,SQL的拼接较复杂,每个节点都要进行相应的词法、语法、语义、生成计划,比较耗时。
- QD + QE方式下放到各个节点的大部分是执行计划,即在Master处已经生成了对应的执行计划,下方到各个Segment上时,只需要找到对应的计划执行即可,减少重复工作,缺点是对于Master的压力会增加,因此这种架构,Master的计算能力以及内存应当适当增加,缺点是解藕能力差,生成的Plan仅能在kstore产品执行。
2.2 数据交换方式
- 原有的xCluster数据交换方式目前为两种,一种为loader方式,另外一种为insert into方式,loader方式是源端agent直接获取目的端kstore的connection,然后调用importhandler方式将数据发送到目的端kstore中。insert into方式是源端获取到数据之后,发送给对应的目的端agent,然后agent将数据导入到kstore中,这中间有很大的性能瓶颈,包括以下几点
- xCluster节点agent通过jdbc方式从节点kstore拉取数据,受到fetchsize的控制,为了平衡第一条数据吐出时间和加载数据速度,这个值并非越大越好,这种方式节点kstore只能通过单线程流水式吐出数据,通过驱动的各种接口到集群,没有充分利用多线程、网络资源。
- 集群进行了多层处理,需要将数据内部形式转换成jdbc所需的外部形式,导入时再将jdbc的外部形式转成kstore需要的内部形式,对cpu压力较大,而且比较耗时。
- 集群中间结果的转发需要通过临时表方式,创建、删除临时表较耗时,而且只有临时表数据完整时才能进行下一步连接,这里完全是串行方式,对资源利用率不高。
- QD + QE方式数据转发不需要建临时表,节省了建表、删表时间,另外数据转发时直接获取到对应的目的节点,通过UDP方式直接发送到对应的端口,减少了序列化、反序列化的过程,减少了cpu的损耗并提升了性能,最后,由于发送的数据就是kstore内部行形式,目的端可以直接利用行进行后续的连接操作,而不必等所有数据获取完毕才进行下一步操作,使其由原本的串行方式变成了并行方式,提高了资源利用率,减少了不必要的等待。
3 新MPP如何实现QD + QE
- QD(QueryDispatcher)
- 首先,通过Parser,analyze_and_rewrite,Planner生成执行计划,该计划与原有kstore的区别在于多了一个新的motion算子,用来实现节点间数据转发功能。
- 其次,在EXECOpen时,构造SliceTable、Gangs以及将计划下发到需要执行的QE上。
- 之后,在EXECGetNext时,等待下层节点发送来的数据,进行相应的汇总操作或者其它操作,例如limit,agg等。
- 最后,在EXECClose时,将之前初始化的SliceTable、Gangs等销毁,释放资源。
- QE(QueryExecutor)
- 在接到上层下发的Plan信息时,从中找到自己所属的slice,执行后,通过motion算子将数据发送到对应的数据节点。