SQL Optimizer 解析 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第1天,本篇笔记主要是关于第一次大数据课程《SQL Optimizer》的课堂笔记
大数据体系
SQL的处理流程
- parser:SQL语句(string类型)作为输入,输出AST(abstract syntax tree-抽象语法树)
- 语法分析:拆分字符串,得到关键字、数值常量、字符串常量、运算符号等token
- 词法分析:将token组成AST node,最终得到AST
AST示意图
- Analyzer:AST作为输入,输出Logical Plan-逻辑执行计划(
逻辑地描述SQL对应的分步骤计算操作 计算操作:算子)- 检查并绑定Database,Table,Column等元信息
- SQL的合法检查
- Optimizer:查询优化,找到一个正确且代价最小的物理执行计划 Plan Fragment:执行计划子树
- 目标:最小化网络数据传输
- 利用数据的物理分布(数据亲和性)(数据分布在多个结点上,每个节点最好只读本地数据)
- 增加shuffle算子(shuffle算子:用于连接结点)
- Executor:
- 单机并行:cache,pipeline,SIMD
- 多机并行: 一个fragment对应多个实例
- 查询优化器分类: 根据遍历方向:
1. Top-down Optimizer:从目标输出开始,从上往下遍历计划树,找到完整的最优执行计划
2. Bottom-up Optimizer:从零开始,由下往上遍历计划树,找到完整的执行计划
根据优化方法:
1. RBO(Rule-based Optimizer):
根据关系代数等价语义,重写查询
基于启发式规则(根据经验)
会访问表的元信息,不会涉及具体的表数据
2. CBO(Cost-based Optimizer):
使用一个模型估算执行计划的代价,选择代价最小的执行计划
算子代价:CPU,内存,磁盘I/O,网络I/O等代价
RBO:
- 关系代数基础:
- 优化原则:
- 优化I/O:读更少的数据/更快的读取数据
- 优化网络:传输更少的数据/更快的传输数据
- 优化CPU&内存:处理的数据更少、更快
- 几种策略:
- 列裁剪:一个查询对应的算子,实际上用不到的列并不需要读取/保留,所以应尽早地去掉这些列,从而减少对I/O或内存地占用,实现地时候会从上往下进行扫描。
- 谓词下推:谓词指代where中的表达式。若我们提前过滤数据不会导致最终结果出错,就今早过滤。
- 传递闭包:根据表达式的等价关系以及过滤条件,可以推导出新的过滤条件
- Runtime Filter
select pv.siteId, user.name from pv join pv.siteId = user.siteId and pv.userId = user.Id where user.siteId > 123;
列裁剪:
谓词下推:
传递闭包:
Runtime Filter:
- 小结:
- 主流RBO实现一般都有几百条基于经验归纳得到的优化规则
- 优点:实现简单,优化速度快
- 缺点:不保证得到最优的执行计划 CBO:
- 流程:
graph TD
统计信息+推导规则 --> 计算算子代价 --> 计算执行计划代价 --> 执行计划枚举
- 统计信息:
- 原始表统计信息
- 推导统计信息:
- 选择率(selectivity):对于某一个过滤条件,查询会从表中返回多大比例的数据
- 基数(cardinality):在查询计划中常指算子需要处理的行数
- 小结:
- CBO使用代价模型和统计信息估算执行计划的代价
- CBO使用贪心或动态规划算法寻找最优执行计划
- 在大数据场景下CBO对查询性能非常重要