SQL Optimiter解析 | 青训营笔记
这是我参与【第四届青训营】笔记创作活动的第1天。
SQL的处理流程:SQL经Paser编译成为AST,AST经Analyzer形成Logical Plan,Logical Plan再经过Optimizer形成Physical Plan,Physical Plan交给Executor去处理数据并返回结果。
RBO关系代数:select、project、join、rename、union等
RBO等价变换:交换律、结合律、传递性
RBO优化原则:阅读数据少且快(I/O)、传递数据少且快(Network)、处理数据少且快(CPU&Memory)
RBO的四种优化:列裁剪、谓词下推、传递闭包、Runtime Filter
RBO小结:
主流RBO实现一般都有几百条基于经验归纳得到的优化规则。
优点:实现简单,优化速度快
缺点:不保证得到最优的执行计划
单表扫描:索引扫描(随机I/O)vs. 全表扫描(顺序I/O)
如果查询的数据分布非常不均衡,索引扫描可能不如全表扫描。
Join的实现:Hash Join vs. SortMerge Join
两表Hash Join:用小表构建哈希表——如何识别小表?
多表Join:
哪种链接顺序是最优的?
是否要对每种组合都探索?
CBO概念:
1.使用一个模型估算执行计划的代价,选择代价最小的执行计划。
执行计划的代价等于所有算子的执行代价之和。
通过RBO得到(所有)可能的等价执行计划。
2.算子代价:CPU、内存、磁盘I/O、网络I/O等代价
和算子输入数据的统计信息有关:输入输出结果的行数,每行大小……
叶子算子Scan:通过统计原始表数据得到
中间算子:根据一定的推导规则,从下层算子的统计信息推到得到
和具体的算子类型,以及算子的物理实现有关
CBO——统计信息
1.原始表统计信息
表或者分区级别:行数、行平均大小、表在磁盘中占用了多少字节等
列级别:min、max、num nulls、num not nulls、num distinct value(NDV)、histogram等
2.推导统计信息
选择率(selectivity):对于某一个过滤条件,查询会从表中返回多大比例的数据
基数(cardinality):在查询计划中常指算子需要处理的的行数
*注:准确的cardinality远比代价模型本身重要。
3.收集方式:
在DDL里指定需要收集的统计信息,数据库会在数据写入时收集或者更新统计信息
手动执行explain analyze statem ent,触发数据库收集或者更新信息
动态采样
4.推导规则:Filter Selectivity
AND条件:fs(a AND b)=fs(a)*fs(b)
OR条件:fs(a OR b)=fs(a)+fs(b)-(fs(a)*fs(b))
NOT条件:fs(NOT a)=1.0-fs(a)
等于条件:literal<min && literal>max : 0
1/NDV
小于条件(X<literal)
literal<min : 0
literal>max : 1
(literal-min)/(max-min)
CBO通常使用【贪心算法】或者【动态规则】选出最优的执行计划
CBO小结:
CBO使用代价模型和统计信息估算执行计划的代价
CBO使用贪心或者动态规化算法寻找最优执行计划
在大数据场景下CBO对查询性能非常重要
Apache Calcite
统一的SQL查询引擎
模块化、插件化、稳定可靠
内置RBO和CBO
异构数据模型:关系型、半结构化、流式、地理空间数据
Calcite RBO
HepPlanner
优化规则:Pattern(匹配表达式子树)、等价变换(得到新的表达式)
内置有100+优化规则
四种匹配规则:
arbitrary/depth_fitst:深度优先
top_down:拓扑顺序
bottom_up:与top_down相反
遍历所有的rule,直到没有rule可以被触发
优化速度快,实现简单,但不保证最优
VocanoPlanner
基于Volcano/Cascade框架
成本最优假设
Memo:存储候选执行计划。本质是AND/OR graph,共享子树减少内存开销
Group:等价计划集合
Top-down动态规划搜索
小结:
主流的查询优化器都包含RBO和CBO
Apache Calcite是大数据领域很流行的查询优化器
Apache Calcite RBO定义了许多优化规则,使用Pattern匹配子树,执行等价变换
Apache Calcite RBO基于Volcano/Cascade框架
Valcano/Cascade的精髓:Memo、动态规划、剪枝