Day01:SQL Optimizer 解析 课程笔记(上)| 青训营笔记

102 阅读4分钟

这是我参与「第四届青训营」笔记创作活动的的第2天。

基础知识:大数据体系

大数据体系

大数据体系和 SQL

介绍大数据体系和 SQL 的处理流程,重点介绍 SQL 在分布式环境下的处理。

Why SQL?

One SQL rules big data all.

  • SQL 更流行、更简单,可以被更多其他领域的专业人士(如数据分析师、数据挖掘师等)所使用;
  • 目前 SQL 被大多数大数据分析引擎所支持,从而避免手动编写分布式计算程序带来的麻烦。
    • SQL 已经是大数据领域的事实标准与接口。

SQL的处理流程

总体流程:

flowchart LR
SQL[[SQL]] -->
Parser(Parser) --AST-->
Analyzer(Analyzer) --Logical Plan-->
Optimizer(Optimizer) --Physical Plan-->
Executor(Executor)

1. Parser(语法解析器)

【输入】SQL String

【输出】抽象语法树(Abstract Syntax Tree, AST)

【步骤】

  1. 词法分析
    拆分字符串并分类,得到关键词、数值常量、字符串常量、运算符号等 token
  2. 语法分析
    将 token 组成 AST 的节点,最终得到 AST

Ref: 编译原理

【AST的例子】

AST的例子

【现有的实现方式】

  • 递归下降(ClickHouse)
  • Flex 和 Bison(PostgreSQL)
  • JavaCC(Flink)
  • Antlr(Presto、Spark)

2. Analyzer(查询分析器)

【输入】抽象语法树(Abstract Syntax Tree, AST)

【输出】逻辑计划(Logical Plan)

【需要完成的任务】

  • 检查 Database、Table、Column 等信息是否合法并与真实数据库的情况做绑定映射
  • 根据相关的元数据检查 SQL 合法性(此处检查的内容一般只有在得到了元数据后才能被检查,例如 min 函数的输入是否为数值)
  • 根据 AST 生成 逻辑计划(部分系统该任务由专门的 Convertor 完成)
    逻辑计划:逻辑地描述 SQL 对应的分步骤计算操作(称为算子,operator),仍然是以树的形式呈现,树中的每个节点都是算子
    注意:逻辑计划中并没有说明算子的具体执行方法,比如没有说明使用什么算法进行排序

【逻辑计划的例子】

SELECT country.name, SUM(weblog.bytes) as total
FROM country
  INNER JOIN geoip ON country.id = geoip.country_id
  INNER JOIN weblog ON geoip.host = weblog.host
WHERE weblog.reply = "200" and weblog.host is not null GROUP BY country.name
ORDER BY total
LIMIT 10

对应的逻辑计划:

逻辑计划的例子

注意:这个例子中的逻辑计划是左深树(left-deep tree),特点是每个连接操作与一个关系作为另一个连接操作的输入时,该连接操作永远在左边(根结点除外)。

3. Optimizer(查询优化器)

SQL 是一种声明式语言:

  • 只描述做什么
  • 没有告诉数据库怎么做

【查询优化器的任务】找到一个正确执行代价最小的物理执行计划(Physical Plan)

【难点】查询优化器是数据库最复杂的模块,很多相关问题都是NP的。

【意义】查询优化器是数据库的大脑,一般 SQL 越复杂,Join 的表越多,数据量越大,查询优化的意义就越大,因为不同执行方式的性能差别可能有成百上千倍。大数据背景下,查询优化器的好坏对查询性能至关重要!

执行计划子树(Plan Fragment/Segment)

物理执行计划也会表示成一棵树。

  • 背景:分布式场景下,数据可能分别存储在不同的物理机器结点中。
  • 方案:在生成物理计划时,会把物理计划拆分为若干个部分,称为执行计划子树
  • 特点:每个机器节点实际上只会拿到这些部分中的某个或某几个,而不是完整的物理执行计划。
  • 划分计划子树
    • 目标:最小化网络数据的传输。
    • 原理:查询优化区需要根据数据亲和性和物理分布,尽量保证数据只在本地读取,而不是通过网络读取。(这也要求查询优化器需要感知数据的物理分布)
    • 各个计划子树的连接:Shuffle 算子(后续课程会详细介绍)

执行计划子树的例子

4. Executor(查询执行器)

生成的执行计划子树会被发送给各个结点,由 Executor 执行。

为了提高执行效率,Executor 在设计时需要考虑并利用并行机制实现并行执行:

  • 单机并行角度:针对 Cache、指令流水线优化,尽可能使用 SIMD 指令
  • 多机并行角度:一个执行计划子树对应多个机器结点