[Spark SQL] 主要執(zhí)行流程

預(yù)備知識(shí)

先介紹在Spark SQL中兩個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu):Tree和Rule。

SparkSql的第一件事就是把SQLText解析成語法樹,這棵樹包含了很多節(jié)點(diǎn)對(duì)象,節(jié)點(diǎn)可以有特定的數(shù)據(jù)類型,同時(shí)可以有0個(gè)或者多個(gè)子節(jié)點(diǎn),節(jié)點(diǎn)在SparkSQL中的表現(xiàn)形式為TreeNode對(duì)象。舉個(gè)實(shí)際的例子:

  • Literal(value: Int): 一個(gè)常量
  • Attribute(name: String): 變量name
  • Add(left: TreeNode, right: TreeNode): 兩個(gè)表達(dá)式的和

x + (1 + 2) 在代碼中的表現(xiàn)形式為:Add(Attribute(x), Add(Literal(1), Literal(2)))


而Rule則是應(yīng)用在Tree上的規(guī)則,通過模式匹配,匹配成功的就進(jìn)行相應(yīng)的規(guī)則變換,若不成功則繼續(xù)匹配子節(jié)點(diǎn),如在Optimizer模塊中有個(gè)常量累加的優(yōu)化規(guī)則,通過該規(guī)則,可以將兩個(gè)常量節(jié)點(diǎn)直接轉(zhuǎn)化為值相加后的一個(gè)常量節(jié)點(diǎn),如下圖:



可以看見先匹配第一個(gè)Add節(jié)點(diǎn)沒有匹配成功,再匹配其子節(jié)點(diǎn)Add成功了。

總流程圖

下圖便是SparkSql整個(gè)解析成RDD的流程圖,紅色部分便是SparkSql優(yōu)化器系統(tǒng)Catalyst,和大多數(shù)大數(shù)據(jù)SQL處理引擎設(shè)計(jì)基本相同(Impala、Presto、Hive(Calcite)等)。下面簡(jiǎn)述一下每個(gè)組成部分都做了什么,后續(xù)博客中會(huì)進(jìn)行詳解。


Parser

  1. sqlText先通過SparkSqlParser生成語法樹。
  2. Spark1版本使用的是scala原生的parser語法解析器,從2.x后改用的是第三方語法解析工具ANTLR4,只需要定制好語法,可以通過插件自動(dòng)生成對(duì)應(yīng)的解析代碼。
  3. 然后通過AstBuilder配合antlr的visitor模式自主控制遍歷Tree,將antlr里面的節(jié)點(diǎn)都替換成catalyst(優(yōu)化器系統(tǒng))里面的類型,所有的類型都繼承了TreeNode特質(zhì),TreeNode又有子節(jié)點(diǎn)children: Seq[BaseType],便有了樹的結(jié)構(gòu)。
  4. 此過程解析完后形成的AST(抽象語法樹)為 unresolved LogicalPlan。

Analyzer

  1. 上個(gè)步驟還只是把sql字符串通過antlr4拆分并由SparkSqlParser解析成各種LogicalPlan(TreeNode的子類),每個(gè)LogicalPlan究竟是什么意思還不知道。
  2. 接下來就需要通過Analyzer去把不確定的屬性和關(guān)系,通過catalog和一些適配器方法確定下來,比如要從Catalog中解析出表名user,是臨時(shí)表、臨時(shí)view,hive table還是hive view,schema又是怎么樣的等都需要確定下來。
  3. 將各種Rule應(yīng)用到Tree之上的真正執(zhí)行者都是RuleExecutor,包括后面的Optimizer 也繼承了RuleExecutor, 解析的套路是遞歸的遍歷,將新解析出來的LogicalPlan來替換原來的LogicalPlan。
  4. 此過程解析完后形成的AST為 resolved LogicalPlan。若沒有action操作,后續(xù)的優(yōu)化,物理計(jì)劃等都不會(huì)執(zhí)行。

Optimizer

  1. 這個(gè)步驟就是根據(jù)大佬們多年的SQL優(yōu)化經(jīng)驗(yàn)來對(duì)SQL進(jìn)行優(yōu)化,比如謂詞下推、列值裁剪、常量累加等。
  2. Optimizer 也繼承了RuleExecutor,并定義了一批規(guī)則,和Analyzer 一樣對(duì)輸入的plan進(jìn)行遞歸處理,此過程解析完后形成的AST為 optimized LogicalPlan。

SparkPlanner

通過優(yōu)化后的LogicalPlan還只是邏輯上的,接下來需要通過SparkPlanner 將optimized LogicalPlan應(yīng)用到一系列特定的Strategies上,即轉(zhuǎn)化為可以直接操作真實(shí)數(shù)據(jù)的操作及數(shù)據(jù)和RDD的綁定等,此過程解析完后形成的AST為 PhysicalPlan。

prepareForExecution

此模塊將 physical plan 轉(zhuǎn)化為 executable physical plan,主要是插入 shuffle 操作和 internal row 的格式轉(zhuǎn)換。

execute

最后調(diào)用SparkPlan的execute()執(zhí)行計(jì)算。每個(gè)SparkPlan里面都有execute的實(shí)現(xiàn),一般都會(huì)遞歸調(diào)用children的execute()方法,最后便會(huì)觸發(fā)整個(gè)Tree的計(jì)算。


最后上個(gè)流程圖


sql整個(gè)執(zhí)行流程

后續(xù)會(huì)對(duì)每個(gè)模塊進(jìn)行詳細(xì)解析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容