前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Byzer 语句执行原理解析

Byzer 语句执行原理解析

作者头像
用户2936994
发布2022-07-21 14:13:35
4790
发布2022-07-21 14:13:35
举报
文章被收录于专栏:祝威廉祝威廉

Byzer 语句执行原理解析

代码语言:javascript
复制
load excel.`./example-data/excel/hello_world.xlsx` 
where header="true" 
as hello_world;

select hello from hello_world as output;

Byzer 是按下面的方式执行的:

  1. 预处理阶段,主要是加载 include 的脚本,展开 宏函数, evaluate 变量 (例子中没有体现)
  2. 按行执行阶段,在上面的例子中,会按顺序分别执行 load/select 两条语句。

在执行一条语句的时候,系统会做两件事情:

  1. 解析和翻译语句,将其转化为可以被 Runtime 执行的 AST 树,然后存储到当前用户独占的catalog中。这个过程是很快的,因为没有涉及到实际数据的操作
  2. 判断是否要真的执行数据计算

判断条件有三个:

  1. 语句是 save 语句
  2. train/run 语句中的一部分,比如 算法类的,都是会触发执行的,而其他大部分则不会。
  3. load/select 等语句是脚本中的最后一行

所以根据前面的描述,Byzer 在执行 第一条 load 语句的时候,此时情况是:

  1. 解析和翻译成AST, 并且暂存相关信息到用户独占的 catalog 里。
  2. 因为不符合前面的三个判断条件,所以并不会真实执行数据加载操作

接着 Byzer 执行第二条 select 语句,此时情况是:

  1. 解析和翻译成 AST, 并且发现依赖了表 hello_world, 去 catalog 查找该表的AST, 然后重组成一个新的AST, 然后也保存到用户独占的 catalog 中。
  2. 符合判断条件的第三个,需要执行实际的数据,展示给用户看。

这个时候 Byzer 会将 重组后的 AST 提交给 Runtime 执行数据计算。

从上面的逻辑我们可以得出如下几个结论:

  1. 第一条语句在执行的时候,并没有触发实际数据计算,也不会将数据加载到内存里。
  2. 第二条语句会将第一条语句的 AST 集合起来,一并提交给 Runtime 执行。
  3. 尽管 Byzer 执行了两条语句,但这两条语句其实被当做了一个 AST 来执行, 等价于一条 SQL, 性能也和一条 SQL 是差不多的。

对于如下代码:

代码语言:javascript
复制
load excel.`./example-data/excel/hello_world.xlsx` 
where header="true" 
as hello_world;

select hello from hello_world where name="yes" as table1;

select * from table1 as output;

当我们将他们放在 notebook 里的三个 Cell 中,然后分别执行,当我们再执行第三条语句的时候

  1. 第三条语句会将第二条和第一条的 AST 都集成过来,然后形成一个新的AST 来执行。可以简单理解为三条语句被合并成了一条语句来执行。
  2. 不会因为第一条语句,第二条语句执行过了,第三条语句执行就会变快。

对于如下代码:

代码语言:javascript
复制
load excel.`./example-data/excel/hello_world.xlsx` 
where header="true" 
as hello_world;

select hello from hello_world where name="yes" as table1;

select * from hello_world as output;

第三条语句只依赖第一条语句产生的表, 所以第三条语句会查找到第一条语句的 AST 然后重组成新的 AST 来执行。第二条语句则仅仅生成 AST,但不会参与到最后的计算。

那如何让第三条语句变快呢? 那就是执行 save 动作,切断查找依赖:

Notebook Cell 1:

代码语言:javascript
复制
load excel.`./example-data/excel/hello_world.xlsx` 
where header="true" 
as hello_world;

select hello from hello_world where name="yes" as table1;

save overwrite table1 as parquet.`/tmp/table1`;
load parquet.`/tmp/table1` as table2;

Notebook Cell 2:

代码语言:javascript
复制
select * from table2 as output;

当我们执行第二个Cell 的时候, 他会去找 table2, table2 是从 parquet 里加载的,所以此时直接从parquet 里那就好了,不需要 再到 table1 去取数据,从而触发 table1 的实际执行。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档