<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          擴(kuò)展 Spark SQL 解析

          共 3727字,需瀏覽 8分鐘

           ·

          2021-04-24 23:58

          4f906a69ae7642ad5e7384eaf2c88232.webp


          大家好久不見了,今天跟大家分享下Spark吧,談?wù)勅绾涡薷腟park SQL解析,讓其更符合你的業(yè)務(wù)邏輯。好,我們開始吧...


          理論基礎(chǔ)


          ANTLR

          Antlr4是一款開源的語法分析器生成工具,能夠根據(jù)語法規(guī)則文件生成對(duì)應(yīng)的語法分析器?,F(xiàn)在很多流行的應(yīng)用和開源項(xiàng)目里都有使用,比如Hadoop、Hive以及Spark等都在使用ANTLR來做語法分析。


          ANTLR 語法識(shí)別一般分為二個(gè)階段:

          1.詞法分析階段 (lexical analysis)

          對(duì)應(yīng)的分析程序叫做 lexer ,負(fù)責(zé)將符號(hào)(token)分組成符號(hào)類(token class or token type)

          2.解析階段

          根據(jù)詞法,構(gòu)建出一棵分析樹(parse tree)或叫語法樹(syntax tree)

          745c33287ae33ad96ab07c3d3924673c.webp

          ANTLR的語法文件,非常像電路圖,從入口到出口,每個(gè)Token就像電阻,連接線就是短路點(diǎn)。

          00840f0f26cc5c5d42e531ed1875b204.webp

          語法文件(*.g4)

          上面截圖對(duì)應(yīng)的語法文件片段,定義了兩部分語法,一部分是顯示表達(dá)式和賦值,另外一部分是運(yùn)算和表達(dá)式定義。

          stat: ? expr NEWLINE ? ? ? ? ? ? ?  # printExpr
          ? | ? ID '=' expr NEWLINE ? ? ? ? # assign
          ? | ? NEWLINE ? ? ? ? ? ? ? ? ? ? # blank
          ? ;

          expr: ? expr op=('*'|'/') expr ? ? # MulDiv
          ? | ? expr op=('+'|'-') expr ? ? # AddSub
          ? | ? INT ? ? ? ? ? ? ? ? ? ? ? ? # int
          ? | ? ID ? ? ? ? ? ? ? ? ? ? ? ? # id
          ? | ? '(' expr ')' ? ? ? ? ? ? ? # parens
          ? ;

          接下來,加上定義詞法部分,就能形成完整的語法文件。


          完整語法文件:

          grammar LabeledExpr; // rename to distinguish from Expr.g4

          prog: ? stat+ ;

          stat: ? expr NEWLINE ? ? ? ? ? ? ? # printExpr
          ? | ? ID '=' expr NEWLINE ? ? ? ? # assign
          ? | ? NEWLINE ? ? ? ? ? ? ? ? ? ? # blank
          ? ;

          expr: ? expr op=('*'|'/') expr ? ? # MulDiv
          ? | ? expr op=('+'|'-') expr ? ? # AddSub
          ? | ? INT ? ? ? ? ? ? ? ? ? ? ? ? # int
          ? | ? ID ? ? ? ? ? ? ? ? ? ? ? ? # id
          ? | ? '(' expr ')' ? ? ? ? ? ? ? # parens
          ? ;

          MUL : ? '*' ; // assigns token name to '*' used above in grammar
          DIV : ? '/' ;
          ADD : ? '+' ;
          SUB : ? '-' ;
          ID : ? [a-zA-Z]+ ; ? ? // match identifiers
          INT : ? [0-9]+ ; ? ? ? ? // match integers
          NEWLINE:'\r'? '\n' ; ? ? // return newlines to parser (is end-statement signal)
          WS : ? [ \t]+ -> skip ; // toss out whitespace


          SqlBase.g4

          Spark的語法文件,在sql下的catalyst模塊里,如下圖:

          6a55d4cda53bffcef44e5577d61edff4.webp

          擴(kuò)展語法定義

          一條正常SQL,例如 Select t.id,t.name from t ?, 現(xiàn)在我們?yōu)槠涮砑右粋€(gè) JACKY表達(dá)式,令其出現(xiàn)在 Select 后面 ,形成一條語句

          Select t.id,t.name JACKY(2) from t


          我們先看一下正常的語法規(guī)則:

          655d934163e7fe1aca708d1196032d9a.webp

          現(xiàn)在我們添加一個(gè) jackyExpression

          b2b8ff415ed2a9456489c488c84a1214.webp

          jackExpression 本身的規(guī)則就是 JACKY加上括號(hào)包裹的一個(gè)數(shù)字

          76cc8b77de0289f4b671fefc8d766549.webp

          將 JACKY 添加為token

          0c2926fff0732cd9101f603219be09c6.webp

          修改語法文件 如下:

          jackyExpression
          ? : JACKY'(' number ')'
          ? //expression
          ? ;

          namedExpression
          ? : expression (AS? (identifier | identifierList))?
          ? ;

          namedExpressionSeq
          ? : namedExpression (',' namedExpression | jackyExpression )*
          ? ;



          擴(kuò)展邏輯計(jì)劃


          經(jīng)過上面的修改,就可以測(cè)試語法規(guī)則,是不是符合預(yù)期了,下面是一顆解析樹,我們可以看到j(luò)ackyExpression已經(jīng)可以正常解析了。

          baae0cbe4ff124d73465dcf7a2ea84ba.webp


          Spark 執(zhí)行流程

          這里引用一張經(jīng)典的Spark SQL架構(gòu)圖

          332f5334b34251904ad857142300e030.webp

          我們輸入的 SQL語句 首先被解析成 Unresolved Logical Pan ,對(duì)應(yīng)的是

          faa0e225d276b04b94ed0faa348480cd.webp

          給邏輯計(jì)劃添加遍歷方法:


           ?override def visitJackyExpression(ctx: JackyExpressionContext): String = withOrigin(ctx) {
          ? ?println("this is astbuilder jacky = "+ctx.number().getText)

          ? ?this.jacky = ctx.number().getText.toInt

          ? ?ctx.number().getText
          }


          再處理namedExpression的時(shí)候,添加jackyExpression處理


           ? ?// Expressions.
          ? ?val expressions = Option(namedExpressionSeq).toSeq
          ? ? .flatMap(_.namedExpression.asScala)
          ? ? .map(typedVisit[Expression])


          //jackyExpression 處理
          ? ?if(namedExpressionSeq().jackyExpression()!=null && namedExpressionSeq().jackyExpression().size() > 0){
          ? ? ?visitJackyExpression(namedExpressionSeq().jackyExpression().get(0))
          ? }


          好了,到這里從邏輯計(jì)劃處理就完成了,有了邏輯計(jì)劃,就可以在后續(xù)物理計(jì)劃中添加相應(yīng)的處理邏輯就可以了(還沒研究明白... Orz)。


          測(cè)試

          測(cè)試用例

          public class Case4 {
          ? ?public static void main(String[] args) {
          ? ? ? ?CharStream ca = CharStreams.fromString("SELECT `b`.`id`,`b`.`class` JACKY(2) FROM `b` LIMIT 10");
          ? ? ? ?SqlBaseLexer lexer = new SqlBaseLexer(ca);
          ? ? ? ?SqlBaseParser sqlBaseParser = new SqlBaseParser(new CommonTokenStream(lexer));
          ? ? ? ?ParseTree parseTree = sqlBaseParser.singleStatement();

          ? ? ? ?AstBuilder astBuilder = new AstBuilder();
          ? ? ? ?astBuilder.visit(parseTree);
          ? ? ? ?System.out.println(parseTree.toStringTree(sqlBaseParser));
          ? ? ? ?System.out.println(astBuilder.jacky());
          ? }
          }


          執(zhí)行結(jié)果

          74e5c06f733edaaa45bf75b3f2f8d81f.webp







          關(guān)注 【?麒思妙想】解鎖更多硬核。

          歷史文章導(dǎo)讀



          如果文章對(duì)您有那么一點(diǎn)點(diǎn)幫助,我將倍感榮幸


          歡迎??關(guān)注、在看、點(diǎn)贊、轉(zhuǎn)發(fā)?



          瀏覽 69
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费二手毛片 | 91精品国产综合久久久不卡电影 | 天堂网一区二区三区 | 色花av| 欧美中文一区 |