【Flink】第二十八篇:Flink SQL 与 Apache Calcite

2022-03-31 11:22:09 浏览数 (1)

源码分析系列推荐:

【Flink】第四篇:【迷思】对update语义拆解D-、I 后造成update原子性丢失

【Flink】第十五篇:Redis Connector 数据保序思考

【Flink】第十六篇:源码角度分析 sink 端的数据一致性

【Flink】第二十四篇:源码角度分析 DataStream API 调用逻辑

【Flink】第二十五篇:源码角度分析作业提交逻辑

【Flink】第二十六篇:源码角度分析Task执行过程

【Flink】第二十七篇:三天撸了一个 Flink SQL 字段血缘算法

接上篇 【Flink】第二十七篇:三天撸了一个 Flink SQL 字段血缘算法 ,从本篇开始深入Flink SQL的解析流程及原理。

本文内容:

  1. Apache Calcite介绍
  2. 从源码工程中一瞥Flink SQL中的Calcite

DSL & GPL

通用编程语言(General Purpose Language):

可以用来编写任意计算机程序,并且能表达任何的可被计算的逻辑,同时也是图灵完备的。例如,Java、C、Python。

领域专用语言(Domain Specific Language):

能够高效的描述特定领域的世界观和方法论的语言。例如,SQL、HTML & CSS、Regex。

平衡本质:

DSL 通过在表达能力上做妥协以换取在某一领域内的高效表达 (世界级软件开发大师 Martin Fowler 对于DSL的解释)。有限的表达能力就成为了 GPL 和 DSL 之间的一条界限。DSL高效简洁的领域语言,与通用语言相比能极大降级理解和使用难度,同时极大提高开发效率的语言。

DSL需要有特定解析器对其进行构建:

  • 没有计算和执行的概念;
  • 本身不需直接表示计算;
  • 只需声明规则和事实及某些元素之间的层级和关系;

解析器概念

功能:

1. 设计词法、语法、语义:定义 DSL 中的元素是什么样的,元素代表什么意思

2. 实现 Parser,对 DSL 解析,最终通过解释器来执行

核心概念:

1. 抽象语法树(Abstract Syntax Tree,AST):

抽象语法树是源代码结构的一种抽象表示,它以树的形状表示语言的语法结构。

抽象语法树一般可以用来进行代码语法的检查,代码风格的检查,代码的格式化,代码的高亮,代码的错误提示以及代码的自动补全等等。

2. 词法解析器 Lexer:

词法分析是指在计算机科学中,将字符序列转换为单词(Token)的过程。

3. 语法解析器 Parser:

语法解析器通常作为 编译器解释器 出现。它的作用是进行语法检查,并构建由输入单词(Token)组成的数据结构(AST)。

常见解释器:Apache Antlr、SQLParser、Apache Calcite(JavaCC)

Apache Antlr


概念:

它的鼻祖级工具是lex、yacc。 举例,如何将java源码转换成字节码?实现这个需求,需要按照java规范,将源码中的每个词法(如public、class、package)、类名、包名等转换成对应的字节码。那么如何取得这些词、类名、包名、变量名呢? 正则表达式在这里可能就显得力不从心了。因为除了要寻找这些词法外,还需要处理复杂的上下文关系(如变量的作用范围)。这些正是antlr擅长的地方。

谁在使用:Hive、Spark、Oracle、Presto、Elasticsearch

核心组件: 词法Lexer 语法Parser

1. 词法Lexer:

  • 标识符,即各类编程语言中所说的以下划线、字母开头的字符串
  • 字面量,英文叫Literal,其实就是可以当作值的东西,放在操作符两边。如数字、单引号字符串、双引号字符串、各个进制写法等
  • 字符,单字符(!、~、=、>等)、双字符(>=、<=)等
  • 关键字,如Java中的class、package、import、public等

2. 语法Parser:

  • 例如,变量定义、类定义

词法和语法规则配置放在 .g4 文件里。

Apache Calcite

概念:

是面向 Hadoop 新的查询引擎,它提供了标准的 SQL 语言、多种查询优化和连接各种数据源的能力,除此之外,Calcite 还提供了 OLAP 和 流处理 的查询引擎。

使用Calcite作为SQL解析与处理引擎有:Hive、Drill、Flink、Phoenix、Storm。

历史:

起源于Hive,原名optiq,为 Hive 提供基于成本模型的优化。2014年成为Apache孵化项目,并更名Calcite。建设者是Julian Hyde,曾经是 Oracle 引擎的主要开发者、SQLStream 公司的创始人和主架构师、Pentaho BI 套件中 OLAP 部分的架构师和主要开发者。现在他在 Hortonworks 公司负责 Calcite 项目。

设计目标:

“ one size fits all (一种查询引擎,连接多种前端和后端)”,希望能为不同计算平台和数据源提供统一的查询引擎,并以类似传统数据库的访问方式(SQL 和高级查询优化)来访问Hadoop 上的数据。

设计目标是成为动态的数据管理系统,所以在具有很多特性的同时,也舍弃了比如数据存储、处理数据的算法和元数据仓库。在应用和数据存储及数据处理引擎之间很好地扮演中介的角色。

特性:

1. 支持标准 SQL 语言;

2. 独立于编程语言和数据源,可以支持不同的前端和后端;

3. 支持关系代数、可定制的逻辑规划规则和基于成本模型优化的查询引擎;

4. 支持物化视图(materialized view)的管理(创建、丢弃、持久化和自动识别);

Calcite 的物化视图是从传统的关系型数据库系统(Oracle/DB2/Teradata/SQL server)借鉴而来,传统概念上,一个物化视图包含一个 SQL 查询和这个查询所生成的数据表。

物化视图可以进一步扩展为 DIMMQ(Discardable, In-Memory, Materialized Query)。简单地说,DIMMQ 就是内存中可丢弃的物化视图,它是高级别的缓存。

5. 基于物化视图的 Lattice 和 Tile 机制,以应用于 OLAP 分析;

6. 支持对流数据的查询。

Calcite 对其 SQL 和关系代数进行了扩展以支持流查询。Calcite 的 SQL 语言是标准 SQL 的扩展,而不是类 SQL,这个差别非常重要。

核心组件:

1. 模板引擎FreeMarker

语法模板文件 parserImpls.ftl 配置文件 conf.fmpp -> .jj 模板文件

2. 语法解析器JavaCC

.jj 模板文件 -> 生成解析器代码文件 .java

在Flink源码工程中的体现:

工程机理:

例如,Flink SQL中的 WATERMARK FOR AS 定义水位线,我们来看看涉及到哪些东西:

1. parserImpls.ftl:

主要完成:

(1) 定义三个成员变量:eventTimeColumnName、pos、watermarkStrategy

(2) 为事件时间属性名eventTimeColumnName赋值

(3) 为字符串位置偏移量pos赋值

(4) 为水位线所属的AST树节点SqlNode赋值watermarkStrategy

这里的赋值是由calcite codegen生成的解析器代码完成的(下节介绍),而SqlWatermark是引入的类,我们看一看这个SqlNode:

这个SqlWatermark本质是对SqlNode的规则定义,继承自SqlCall,UML如下,

所以本质就是一个SqlNode。

但是在哪里引入的SqlWatermark类呢?我们看Parser.tdd

而在这个文件的开始有这个定义:

FlinkSqlParserImpl即为Calcite根据DSL文件描述文件parserImpls.ftl生成的类名的定义。

而parserImpls.ftl和Parser.tdd是如何产生联系的呢?我们看config.fmpp,

至此,我们大致了解Flink是如何在工程角度与Calcite相遇的,更多细节限于笔者能力和时间有限就不过多展开了。下一篇将介绍Calcite在Flink中的解析流程及一些细节。

0 人点赞