【国产数据库】GBase学习⑪ - 分布式执行计划
SQL执行流程
- SQL执行流程:应用—SQL—解析器(词法分析,语法分析,语义分析)—优化器(查询重写,路径搜索,代价计算)—执行器(LightProxy,FastQuery Shipping,Stream, Remote Query)—存储引擎(行存引擎、列存引擎、内存引擎)
- 解析器:
1.1 词法分析:从查询语句中识别出系统支持的关键字、标识符、操作符、终结符等。
1.2 语法分析:根据SQL语言的标准定义语法规则,使用词法分析产生的词去匹配语法规则,生成对应的抽象语法树。
1.3 语义分析:对语法树进行有效性检查,检查语法树中对应的表、列、函数、表达式是否有对应的元数据,将抽象语法树转换为逻辑执行计划。 - 优化器:
2.1 基于代价的查询优化(Cost Based Optimization,CBO):对SQL语句所待选执行路径进行代价估算,从中选择代价最低的执行路径作为最终的执行计划。
2.2 基于机器学习的查询优化(AI Based Optimization,ABO):收集执行计划的特征信息,借助机器学习模型获得经验信息,进而对执行计划进行调优,获得最优的执行计划。
Explain-执行计划
Explain语法将显示SQL语句所引用的表会采用什么样的扫描方式,如:简单的顺序扫描。索引扫描等。如果引用了多个表,执行计划还会显示用到的JOIN算法。
EXPLAIN[( option [,...])] statement;
where option can be:
ANALYZE [boolean] | ANALYSE [boolean] | --显示实际运行时间和其他统计数据
VERBOSE [boolean] | --显示额外的详细信息
COSTS[boolean] | --包括每个规划节点的估计总成本,以及估计的行数等信息
DETAIL [boolean] | --打印数据库节点的信息
TIMING [boolean] | --包括实际的启动时间和花费在输出节点上的时间信息
PLAN [boolean] | --是否将执行计划存储在plan_table中
FORMAT {TEXT|XML|JSON|YAML } --指定输出格式
分布式执行计划类型–LightProx
- 执行计划只设计一个DN节点,直接将sql语句发送到dn执行
- 单个DN即可完成结果的获取,常见于点查、精准查询场景
例:
create table t1 (id1 int, id2 int) distribute by hash(id1);
select * from t1 where id1 = 1;
分布式执行计划类型-FQS
- 计划可以涉及多个DN节点,但在执行过程中,DN节点之间无数据交互;
- FQS会对sql进行适当重写,通过remote query执行;
例:
select * from t1,t2 where t1.id1=t2.id1; -- > SELECT t1.id1,t1.id2,t2.id1,t2.id2 FROM public.t1,public.t2 WHERE ((t1.id1=t2.id1));
分布式执行计划类型-Stream
- 由cn生成执行计划,将执行计划发送到dn,dn按照接收到的计划执行相应的算子,cn收集dn的执行结果,进行处理后做出最后输出;
- Stream 算子类型:gather,redistribute,broadcast
- gather:cn将本算子以下的计划发送到其他节点,收集汇总dn的执行结果
- broadcat:执行broadcast时,dn将查询到的数据广播到所有其他dn节点,在执行过程中,拥有两种角色:consumer、producer (consumer:接受producer发送的数据;producer:新启动streamworker线程作为producer,将扫描到的所有数据,广播到所有consumer(本dn和其他dn))
- redistribute:过程和broadcast类似,单producer在发送数据根据指定的key选择发送到哪个consumer;
- 当broadcast与redistribute均能实现查询时,倾向于将小表做广播,大表做重分布。
例1:select无连接条件
insert into t1 values(1,11),(2,12),(3,13),(4,14);
insert into t2 values(1,14),(2,13),(3,1),(4,2);
explain verbose select * from t1,t2;
# cn将stream(gather类型stream)以下的计划(nested loop) 发送给dn,由dn执行;
接收cn计划的dn执行stream(broadcast 或 redistribute)时,作为consumer,启动stream worker 线程作为producer,执行此stream以下的计划(seq scan public.t1);
producer将获得的数据,按照stream类型,发送到各个dn的consumer。
每个dn 将t1表广播,然后t2 * t1, 然后cn汇总
例2:select 连接条件为分布列和非分布列
insert into t1 values(1,11),(2,12),(3,13),(4,14);
insert into t2 values(1,14),(2,13),(3,1),(4,2);
explain verbose select * from t1,t2 where t1.id1=t2.id2
# 连接条件为t1.id1(分布列)与t2.id2(非分布列)时,将t2表数据按照id2在dn上做重分布
t2表的数据根据id2 重分布在dn1和dn2,然后t1*t2,然后cn汇总
例3:select连接条件为非分布列
当链接条件均为非分布列时,通过广播和重分布均能实现链接,表规模较小时,倾向于广播,规模较大时,倾向于重分布。
例4:update连接条件为分布列
update t1时,连接条件为t1.id1(分布列)与t2.id1(分布列),不会进行重分布或广播
例5:update连接条件为分布列与非分布列
insert into t1 values(1,11),(2,12),(3,13),(4,14);
insert into t2 values(13,1),(14,2),(15,3),(16,4);
explain verbose update t1 set id2=102 from t2 where t1.id2=t2.id1;
update t1时,连接条件为t1.id2(非分布列)与t2.id1(分布列),更新的是t1表,不能广播或重分布t1表。
t2表广播到所有dn,然后t1 update
分布式执行计划类型-Remote query
Remote query 计划将查询语句发送到DN节点,在CN收集结果;
不支持Stream计划时,通过Remote query 将数据收集到CN,在CN完成相关操作。
例:update 带有 returning 语句,并存在两表连接,不支持stream 计划,CN通过remote query 从DN获取两表数据,在CN完成连接操作,根据连接结果构造最终update语句,通过remote query下发DN。
returning 将update 结果向上返回。
create table t1(id1 int,id2 int) distribute by hash(id1);
create table t2(id1 int,id2 int) distribute by hash(id1);
insert into t1 values(1,11),(2,12),(3,13),(4,14);
insert into t2 values(1,14),(2,13),(3,1),(4,2);
explain verbose update t1 set id2=102 from t2 where t1.id2=t2.id2 returning t1.id2;
cn 把查询的计划发到 dn1,dn2 ,然后 dn把t1,t2 返回cn ,然后 join 然后update 然后 returning