达梦分布式集群DPC_分布式执行计划执行拆分流程
1 DPC任务拆分原理
1.1 分布式架构思想
从单机-分布式,最大的变化是表数据从存储到一个节点(一台服务器),变化成分散到多个节点(多台服务器存储);
例如 当客户端产生一个任务时,如执行"select *from表"
1.单机的任务执行方式为单线程调度,例如一个人承包一个任务
2.当表数据存储在多台服务器,就出现了任务拆分的解决方案,任务拆分为多个部分,每个人负责一部分,最后对结果汇总
通过将大任务分为多个小任务,每个小任务存储在不同服务器,让多台服务器并行执行任务来提升性能
1.2 DPC如何实现任务拆分?
达梦dpc的架构为SP+MP+BP,计算节点+元数据节点+数据存储节点
1. SP为计算节点:
作用为进行分布式执行计划的生成,分发子任务到BP,结果集汇总等
例如
SP类似于总控节点,对任务进行拆解,并分发任务给BP
2. MP为元数据节点:
提供数据字典信息,包含数据分布等信息
例如
MP存储了哪个分区存储在哪个BP上
可以给SP提供元数据信息,方便SP的任务分发和计划生成等
3. BP是数据存储节点:
BP是数据存储节点,一般每台服务器至少配置1个BP,方便数据拆分,并执行SP分发的任务
例如
建表时通过创建分区表,指定不同的分区存储在不同BP上,实现数据拆分;
达梦DPC通过这三层架构协同,来解决分布式任务的拆分执行问题
2 DPC任务拆分完整示例
2.1 单表查询
2.1.1 创建分区表,存储在不同BP上
create table Y1(A int, B int) partition by hash(A) partitions 3 ;
--默认会存储在3个BP上
2.1.2 生成sql的最佳执行计划
1.sql请求:客户端连接SP发送sql语句 select *from Y1;
2.解析:SP收到请求后,向MP申请Y1表的元数据信息,然后进行语法检查、语义检查、共享池检查
3.优化器阶段:默认没有缓存,会进行到优化器阶段,生成最佳执行计划
①.优化器会首先生成单机版本的最佳执行计划(CBO)
project[0x1215e4170] n_exp(3) (cost: 0.04461, rows: 1)
base table[0x1215e4cc8] (Y1, INDEX47617565, FULL SEARCH) (cost: 0.04461, rows: 1)
②生成单机最佳执行计划后,插入分发操作符(send、recv为分布式操作符)
recv[0x1215e6f20] (cost: 0.04461, rows: 1)
send[0x1215e68d8] send_type(DIRECT) sites(5:1,12:1,10:1) gi_polic(UNIT) (cost: 0.04461, rows: 1)
project[0x1215e4170] n_exp(3) (cost: 0.04461, rows: 1)
base table[0x1215e4cc8] (Y1, INDEX47617565, FULL SEARCH) (cost: 0.04461, rows: 1)
最佳执行计划
1 #NSET2: [1, 1, 20]
2 #ERECV: [1, 1, 20]; stask_no(-1), l_stask_no(0), n_key(0), in_turn(0), trig(0)
3 #ESEND: [1, 1, 20]; stask_no(0), type(DIRECT), sites(5:1,12:1,10:1), sql_invoke(0), pwj_opt(0), table(-); INFO_BITS(0xc)
4 #GI: [1, 1, 20]; policy(PART_UNIT), gi_unit[0..0], scan_type[0](FULL)
5 #PRJT2: [1, 1, 20]; exp_num(3), is_atom(FALSE)
6 #CSCN2: [1, 1, 20]; INDEX47617565(Y1); btr_scan(1)
2.1.3 代码生成并执行、拆分
当拿到最佳执行计划后,进行可执行代码生成后执行
2.1.3.1 任务拆分步骤
①任务分发
NSET2执行根计划,任务号为stask_no(-1)=-1,往下走遇到了ERECV,这个是分布式的操作符,开始进行任务分割和数据分发,QC(查询调度总单元)调度发送所有子计划到BP上;
2 #ERECV: [1, 1, 20]; stask_no(-1), l_stask_no(0), n_key(0), in_turn(0), trig(0)
3 #ESEND: [1, 1, 20]; stask_no(0), type(DIRECT), sites(5:1,12:1,10:1), sql_invoke(0), pwj_opt(0), table(-); INFO_BITS(0xc)
--分析
主任务号为stask_no(-1),子任务号为