基於calcite做傻瓜式的sql優化(二)


 上一篇:基於calcite做傻瓜式的sql優化(一)

因為主要想借助hive的思路來實現對sql的優化,所以這一篇主要是梳理一條sql在hive內部大概是什么樣的生命周期

首先通過一張圖看下,內部sql大概執行流:

 

 sql經過一系列的規則處理后,最后變成task tree,然后mapreduce通過task tree來執行job

接下來通過源碼,看下是如何處理的!

另外我把編譯好的hive(1.2.1版本)和hadoop(2.7.0版本)代碼放在Git上,這樣感興趣的同學直接下載下來,就可以在本地debug跑

Hive編譯后的源碼:https://github.com/niutaofan/apache-hive-1.2.1-src.git
hadoop編譯后的源碼:鏈接:https://pan.baidu.com/s/1meF9MFHUAyY1Mk7mMOdqIg  密碼:fwnh

1、大體流程

1)、Driver.compile 接收SQL , 然后通過:pd.parse(command)將SQL轉換為ASTNode(這個過程包含了詞法解析和語法解析)

  1.1、ParseDriver.parse接收到sql語句,然后通過:r = parser.statement();解析了詞法和語法

  1.2、拿到解析后的HiveParser.statement_return,然后通過ASTNode tree = (ASTNode) r.getTree();獲取到ASTNode

2)、通過sem.analyze(tree, ctx);從AST Node到Phsical Optimize這幾個階段,都是在SemanticAnalyzer.analyzeInternal()方法中進行的(語義解析、生成邏輯執行計划、優化邏輯執行計划等)

  2.1、拿到ASTNode之后,通過SemanticAnalyzer.analyzeInternal()進行優化;

  2.2、代碼會調度到CalcitePlanner.analyzeInternal (這個方法內部會做 一個流程的判斷:if (runCBO) 是否執行CBO優化),當然不管執行RBO還是CBO,最后調用的都是:SemanticAnalyzer.analyzeInternal()

  2.3、在SemanticAnalyzer.analyzeInternal()方法中,首先基於ASTNode做了各種規則優化,根據需求包括了籠統的:RBO和CBO的優化,最終返回Operator

    在Hive中,使用Calcite來進行核心優化,它將AST Node轉換成QB,又將QB轉換成Calcite的RelNode,在Calcite優化完成后,又會將RelNode轉換成Operator Tree,說起來很簡單,但這又是一條很長的調用鏈。

    Calcite優化的主要類是CalcitePlanner,更加細節點,是在CalcitePlannerAction.apply()這個方法,CalcitePlannerAction是一個內部類,包括將QB轉換成RelNode,優化具體操作都是在這個方法中進行的。

  

2、一條sql的源碼之路

如果想debug的方式走讀源碼,那么需要如下幾個步驟:

第一步:啟動本地的hadoop源碼(NameNode和DataNode)

 

 

 第二步:啟動hive的metastore服務

 

 

 第三步:啟動(Debug方式)CliDriver類

 

 

 

根據上文提示, sql在客戶端執行后,會在Driver.compile 接收SQL , 然后通過:pd.parse(command)將SQL轉換為ASTNode(這個過程包含了詞法解析和語法解析)

eg. 執行一段sql(sql的數據,提前放入hive了) , 看下hive是如何解析和優化的

select 
  * 
from 
  (
    select 
      Sname, 
      Sex, 
      Sage, 
      Sdept, 
      count(1) as num 
    from 
      student_ext 
    group by 
      Sname, 
      Sex, 
      Sage, 
      Sdept
  ) t1 
where 
  Sage > 10;

Driver.compile代碼:

 

 

 上圖比較重要的點:

ParseDriver

Hive使用的是antlr來做詞法、語法的解析工作,最終生成一棵有語義的ast樹
而在Hive中調用antlr類的代碼org.apache.hadoop.hive.ql.parse.ParseDriver類,通過ParseDriver.parse 可以返回HiveParser.statement_return 

而這個HiveParser.statement_return通過強轉,即可拿到ASTNode,如下圖:

 ps:這塊兒存在極大的性能問題,后續會提到並改進

 

######################################################思考############################################################################################

如果需求是快速實現對用戶輸入的sql進行詞法和語法解析,以便達到自定義或者sql優化的需求,那么可不可以利用上述內容進行重構???

答案是肯定可以的,而且非常簡單,只需要知道,hive在做sql的詞法和語法解析,使用的是哪個包(org.apache.hadoop.hive.ql.parse)

然后開啟一個新的工程,導入hive-exec包即可

第一步:maven導入依賴

 <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec-nt</artifactId>
            <version>1.2.1</version>
 </dependency>
 <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.1</version>
 </dependency>

第二步:代碼編寫 

import org.apache.hadoop.hive.ql.parse.ASTNode;
import org.apache.hadoop.hive.ql.parse.ParseDriver;
import org.apache.hadoop.hive.ql.parse.ParseException;
/**
 * Created by niutao
 */
public class Tests {
    public static void main(String[] args) {
        String sql = "SELECT `object_id`, `column1_id`, COUNT(DISTINCT `cookie`) AS `COOKIE`\n" +
                "FROM `D_DSJ_INDEX_PDS`.`INDEX2_FLW_COOKIE_INTEREST_OBJECT_D_FACT`\n" +
                "WHERE `dim_day` >= '2020-03-03' AND `dim_day` <= '2020-03-16' AND `series_id` = '692'\n" +
                "GROUP BY `object_id`, `column1_id`\n" +
                "ORDER BY COUNT(DISTINCT `cookie`) IS NULL DESC, COUNT(DISTINCT `cookie`) DESC\n" +
                "LIMIT 200";
        //1、導入模仿hive,導入ParseDriver
        ParseDriver pd = new ParseDriver();
        //2、解析sql
        try {
            ASTNode ast = pd.parse(sql);
            //3、測試,打印解析樹
            System.out.println(ast.dump());
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

打印 結果:

 

 通過以上方式,即可將sql解析出ASTNode

###################################################################################################################################################### 

接着之前的源碼,看下在生成ASTNode之后 , 是如何根據ASTNode來做優化的;

請查看下一篇:基於calcite做傻瓜式的sql優化(三)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM