这是我参与「第四届青训营 」笔记创作活动的的第1天。
前言
首先,老师介绍了大数据体系及课程后续安排,并留下第一个问题,为什么要先介绍SQL Optimizer。
为什么要先介绍SQL Optimizer
- 流行,很多人使用
- 简单,相比于c++等程序语言
- 通用,大部分平台均可使用 最终目标:处理所有大数据
大数据体系和SQL
介绍大数据体系和SQL的处理流程,重点介绍SQL在分布式环境下的处理。
SQL的处理流程
graph TD
SQL-->Parser--> AST--> Analyzer-->LogicalPlan-->Optimizer-->PhysicalPlan-->Executor
Parser
graph TD
String--> AST
词法分析
语法分析
实现:递归下降(ClickHouse),Flex和Bison(PostgreSQL),JavaCC(flink),Antlr(Presto,Spark)
Analyzer
- 检查并绑定Database,Table,Column等元信息
- SQL的合法性检查,比如min/max/avg的输入是数值
- AST-->Logical Plan
Logical Plan(eg.left-deep tree)
- 逻辑地描述SQL对应的分步骤计算操作
- 计算操作:算子(operator)
查询优化
- SQL是一种声明式语言,用户只描述做什么,没有告诉数据库怎么做
- 目标:找到一个正确且执行代价最小的物理执行计划
- 查询优化器是数据库的大脑,最复杂的模块,很多相关问题都是NP的
- 一般SQL越复杂,Join的表越多,数据量越大,查询优化的意义就越大,因为不同执行方式的性能差别可能有成百上千倍。
Plan Fragment&Executor
- Plan Fragment
- 目标:最小化网络数据传输
- 利用上数据的物理分布(数据亲和性)
- 增加Shuffle算子
- Executor
- 单机并行:cache,pipeline,SIMD
- 多机并行:一个fragment对应多个实例
小结
- One SQL rules big data all
- SQL需要依次经过Parser,Analyzer,Optimizer和Executor的处理
- 查询优化器是数据库的大脑,在大数据场景下对查询性能至关重要
- 查询优化器需要感知数据分布,充分利用数据的亲和性
- 查询优化器按照最小化网络数据传输的目标把逻辑计划拆分成多个物理计划片段
常见的查询优化器
介绍查询优化器的分类,重点介绍RBO和CBO的原理
查询优化器的分类
按照遍历执行树分类
- Top-down Optimizer 从目标输出开始,由上往下遍历树。找到完整的最优执行计划
- BOttom-up Optimizer 从零开始,由下往上遍历计划树,找到完整的执行计划
RBO
根据关系代数等价语义,重写查询 基于启发式规则 会访问表的元信息(catalog)。不会涉及具体的表数据(data)
关系代数
- 运算符:Select,Project,Join,Rename,Union
- 等价变换:结合律,交换律,传递性
优化原则
- Read data less and faster(I/0)
- Transfer data less and faster(Network)
- Process data less and faster(CPU&Memory)
列裁剪
谓词下推
传递闭包
Runtime Filter
RBO小结
- 主流RBO实现一般都有几百条基于经验归纳得到的优化规则
- 优点:实现简单。优化速度快
- 缺点:不保证得到最优的执行计划 单表扫描:索引扫描(随机I/O)vs.全表扫描(顺序I/O) 如果查询的数据分布非常不均衡,索引扫描可能不如全表扫描 Join的实现:Hash Join vs.SortMerge Join 两表Hash Join:最小表构建哈希表——如何识别小表? 多表Join:哪种连接顺序是最优的? 是否要对每种组合都探索?