这是我参与「第四届青训营 」笔记创作活动的的第1天
[第四届青训营笔记创作活动]
前言
一、 SQL 的处理流程
- Parse
- String -> AST:将 SQL 语句解析,进行词法分析和语法分析,得到抽象语法树 AST (Abstruct Syntax Tree)
- 词法分析:拆分字符串,得到关键字、数值常量、字符串常量、运算符号等 token
- 语法分析:将 token 组成 AST node ,最终得到一个 AST
- 实现:递归下降 (ClickHouse),Flex 和 Bison (PostgreSQL),JavaCC (Flink),Antlr (Presto,Spark)
- String -> AST:将 SQL 语句解析,进行词法分析和语法分析,得到抽象语法树 AST (Abstruct Syntax Tree)
- Analyzer
- 检查并绑定Database,Table,Column等元信息
- SQL的合法性检查,比如min/max/avg等的输入是数值类型
- AST -> Logical Plan:将AST解析成Logical Plan
- Optimizer
- 利用一些 Rule (规则),优化执行任务流程,将 Analyzed logical plan 解析成 Optimized Logical Plan,得到 Physical Plan
- Executor
- 执行 Physical Plan
二、 什么是查询优化器
- 数据库主要由三部分组成,分别是解析器、优化器和执行引擎,如下图所示:
- 其中优化器是数据库中用于把关系表达式转换成执行计划的核心组件,很大程度上决定了一个系统的性能
三、 为什么需要查询优化
- SQL 是一种声明式语言,用户只描述做什么,没有告诉数据库怎么作
- 需要找到一个正确且代价最小的物理执行任务
- 对于复杂的 SQL 任务,Join 的表越多,数据量越大,不同的执行方式的性能可能相差成百上千倍,因此查询优化就显得尤为重要
常见的查询优化器
一、 RBO (Rule - based Optimizer)
- 根据关系代数等价语义,重写查询
- 基于启发式
- 会访问表的元信息 (catalog),不会涉及表数据 (data)
二、 CBO (Cost - based Optimizer)
- 划分算子 (Operator)
- 根据统计信息和代价模型 (Cost Model) 计算每个执行计划的 代价 (Cost)
- 通过贪心或者动态规划算法选择代价最小的执行计划执行
查询优化器的工作流程
一、 RBO
-
列裁剪
- 利用列裁剪可以把那些查询不需要的字段过滤掉,使得扫描的数据量减少
-
谓词下推
- 将过滤条件尽可能地下推到底层,最好是数据源
-
传递闭包 (常量折叠)
- 将常量表达式计算求值,并用求得的值来替换表达式,放入常量表
-
Runtime Filter
- 在 Join 的 probe 端提前过滤掉那些不会命中 Join 的输入数据来大幅减少 Join 中的数据传输和计算,从而减少整体的执行时间
二、 CBO
-
Exploration
- 根据优化规则进行等价转换,生成等价关系表达式,此时原有关系表达式会被保留
-
Build Physical Plan
- 决定各个Operator的具体实现
-
Find Best Plan
- 根据统计信息计算各个执行计划的 Cost,选择Cost最小的执行计划