Hive Query生命周期 —— 鈎子(Hook)函數篇


無論你通過哪種方式連接Hive(如Hive Cli、HiveServer2),一個HQL語句都要經過Driver的解析和執行,主要涉及HQL解析、編譯、優化器處理、執行器執行四個方面。

以Hive目前原生支持計算引擎MapReduce為例,具體處理流程如下:

  1. HQL解析生成AST語法樹Antlr定義SQL的語法規則,完成SQL詞法和語法解析,將SQL轉化為抽象語法樹AST Tree
  2. 語法分析得到QueryBlock遍歷AST Tree,抽象出查詢的基本組成單元QueryBlock
  3. 生成邏輯執行計划遍歷QueryBlock,翻譯為執行操作樹Operator Tree
  4. Logical Optimizer Operator進行邏輯優化邏輯層優化器進行OperatorTree變換,合並不必要的ReduceSinkOperator,減少shuffle數據量
  5. 生成物理執行計划Task Plan遍歷Operator Tree,翻譯為MapReduce任務
  6. 物理優化Task Tree,構建執行計划QueryPlan物理層優化器進行MapReduce任務的變換,生成最終的執行計划
  7. 表以及其他操作鑒權
  8. 執行引擎執行

在Hive Query整個生命周期中,會有如下鈎子函數被執行:

HiveDriverRunHook的preDriverRun

該鈎子函數由參數hive.exec.driver.run.hooks控制,決定要運行的pre hooks,多個鈎子實現類以逗號間隔,鈎子需實現 org.apache.hadoop.hive.ql.HiveDriverRunHook接口。


HiveSemanticAnalyzerHook的preAnalyze

在Driver開始run之前,HQL經過解析會進入編譯階段的語法分析,而在語法分析前會經過鈎子HiveSemanticAnalyzerHook的preAnalyze方法處理。該鈎子函數由hive.semantic.analyzer.hook配置,鈎子需實現org.apache.hadoop.hive.ql.parse.HiveSemanticAnalyzerHook接口。

 

HiveSemanticAnalyzerHook的postAnalyze

與preAnalyze同屬於一個鈎子類,配置參數相同,會執行所有配置的語義分析hooks,但它位於Hive的語法分析之后,可以獲取HQL的輸入和輸出表及分區信息,以及語法分析得到的task信息,由此可以判斷是否是需要分布式執行的任務,以及執行引擎是什么。

生成執行計划之前的redactor鈎子

該鈎子由hive.exec.query.redactor.hooks配置,多個實現類以逗號間隔,鈎子需繼承org.apache.hadoop.hive.ql.hooks.Redactor抽象類,並替換redactQuery方法。

這個鈎子函數是在語法分析之后,生成QueryPlan之前,所以執行它的時候語法分析已完成,具體要跑的任務已定,這個鈎子的目的在於完成QueryString的替換,比如QueryString中包含敏感的表或字段信息,在這里都可以完成替換,從而在Yarn的RM界面或其他方式查詢該任務的時候,會顯示經過替換后的HQL。

task執行前的preExecutionHook

在執行計划QueryPlan生成完,並通過鑒權后,就會執行具體的task,而task執行之前會經過一個鈎子函數,鈎子函數由hive.exec.pre.hooks配置,多個鈎子實現類以逗號間隔。實現方式:

1)實現org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext

通過實現該接口的run方法,執行所有的pre-execution hooks

// Pre/Post Execute Hook can run with the HookContext
public interface ExecuteWithHookContext extends Hook {

/** hookContext: The hook context passed to each hooks.
   *  HookContext帶有執行計划、Hive的配置信息、Lineage、UGI、提交的用戶以及輸入輸出表等信息
   */
void run(HookContext hookContext) throws Exception;
}

 

2)實現org.apache.hadoop.hive.ql.hooks.PreExecute

 

該接口的run方法已經標注為過時,並且相對於ExecuteWithHookContext,PreExecute提供的信息可能不能完全滿足我們的業務需求。

public interface PreExecute extends Hook {

/**
   * The run command that is called just before the execution of the query.
   * SessionState、UGI、HQL輸入表及分區信息,HQL輸出表、分區以及本地和hdfs文件目錄信息
   */
@Deprecated
public void run(SessionState sess, Set<ReadEntity> inputs,Set<WriteEntity> outputs, UserGroupInformation ugi) throws Exception;
}

 

 task執行失敗時的ON_FAILURE_HOOKS

task執行失敗時,Hive會調用這個hook執行一些處理措施。該鈎子由參數hive.exec.failure.hooks配置,多個鈎子實現類以逗號間隔。需實實現org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext接口。

 

task執行完成時的postExecutionHook

在task任務執行完成后執行。如果task失敗,會先執行ON_FAILURE_HOOKS,之后執行postExecutionHook,該鈎子由參數hive.exec.post.hooks指定的hooks(多個鈎子實現類以逗號間隔)執行post execution hooks。實現方式:

1)實現org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext

2)實現org.apache.hadoop.hive.ql.hooks.PostExecute

ExecuteWithHookContext和PostExecute跟分別與上述task執行前的preExecutionHook、PreExecute對應,這里不再贅述。

 

HiveDriverRunHook的postDriverRun

在查詢完成運行之后以及將結果返回給客戶端之前執行,與preDriverRun對應。

此外,Hive中已經有一些內置實現的hook,下面舉一些例子以及它們的主要作用:

ATSHook:實現了ExecuteWithHookContext,將查詢和計划信息推送到Yarn App Timeline Server。

DriverTestHook:實現了HiveDriverRunHook的preDriverRun方法(對postDriverRun是空實現),用於打印輸出的命令

EnforceReadOnlyTables:pre execute hook,實現了ExecuteWithHookContext,用於阻止修改只讀表。

LineageLogger:實現了ExecuteWithHookContext,它將查詢的血統信息記錄到日志文件中。LineageInfo包含有關query血統的所有信息。

PreExecutePrinter和PostExecutePrinter:pre和post hook的示例,它將參數打印輸出。

PostExecTezSummaryPrinter:post execution hook,實現了ExecuteWithHookContext,可以打印Hive Tez計數器的相關信息。

PostExecOrcFileDump:post execution hook,實現了ExecuteWithHookContext,用於打印ORC文件信息。

UpdateInputAccessTimeHook:pre execution hook,可在運行查詢之前更新所有輸入表的訪問時間。

特別強調一下LineageLogger和LineageInfo,對於做Hive血緣關系分析很有參考價值,當然Hive血緣分析不是本篇文章的重點,這里先不做展開。

通過對上面Hive中hook的執行"位置"和作用,以及Hive本身實現的一些Hook,分析可知:自定義hook,比如實現一個pre execution hook。

首先在maven的pom中引入hive-exec的依賴,如:

<dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>2.1.0</version>
</dependency>

 

此外,還需創建一個實現ExecuteWithHookContext的類,實現其中的run方法,並設置相應的參數,使自定義的hook類生效。

最后,通過一張圖,來對Hive Hook做個總結:

關聯文章:
Hive Join優化
Apache Hive


免責聲明!

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



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