Impala前端代碼分析
Table of Contents
- 1 概述
- 2 文法分析和ParseNode
- 3 Analyzer
- 4 生成執行計劃和Planner
- 5 Catalog
1 概述
前端代碼使用java。感覺使用java的原因是,本身文法分析不會占用太多時間,毫秒級可以完成,不是性能瓶頸。而且文法分析的代碼通常比較複雜,邏輯較多,如果再自己管理記憶體的話,會影響開發效率。
Impala通過jni調用前端java代碼,前後端資料傳遞采用thrift格式。
前端的代碼主要包括以下幾個功能:
- 将使用者送出的query轉換成文法樹,這個通過jflex和cup完成(hive使用的是antlr)
- 文法分析
- 生成執行計劃
- 在編譯中通路中繼資料
2 文法分析和ParseNode
ParseNode定義了一個接口。jflex和cup分析完的文法樹中,每一個節點都實作了這個接口。文法分析就是在這個ParseNode組成的樹中進行的。
ParseNode的實作和繼承關系如下:
- Expr (表達式)
- Predicate (謂詞,出現在where語句中)
- BetweenPredicate
- BinaryPredicate (=, !=, <=, >=, <, >)
- CompoundPredicate (&&, ||, !)
- InPredicate
- IsNullPredicate
- LikePredicate
- LiteralPredicate
- BoolLiteral
- DateLiteral
- FloatLiteral
- IntLiteral
- NullLiteral
- StringLiteral
- AggregateExpr (count, min, max, distince, sum, avg)
- ArithmeticExpr (*, /, %, DIV, +, -, &, |, ^, ~)
- CaseExpr
- CastExpr
- FunctionCallExpr
- LiteralExpr
- TimestampArithmeticExpr
- Predicate (謂詞,出現在where語句中)
- QueryStmt
- SelectStmt
- UnionStmt
- InsertStmt
- ShowDbStmt
- ShowTablesStmt
- DescribeStmt
- UseStmt
- TableRef
- BaseTableRef
- InlineViewTableRef (alias)
其中,Expr繼承了TreeNode類,可以組成一個求值樹。而其他ParseNode雖然沒有繼承TreeNode,但也都有類似的資料結構。可以通路孩子節點。這樣ParseNode就組成了一顆文法樹。
文法分析階段主要進行了一些基本的文法檢查,類型檢查,并抽取一些資訊,放到Analyzer類中,例如alias映射表等等。
3 Analyzer
Analyzer是文法分析的一個産出。Analyzer用于收集某一個QureyBlock内的資訊。類似Hive中的QB類。
其主要成員變量包括:
- DescriptorTable descTbl;
- Catalog catalog;
- String defaultDb;
- IdGenerator<ExprId> conjunctIdGenerator;
- Analyzer parentAnalyzer;
- Map<String, TupleDescriptor> aliasMap;
- Map<String, SlotDescriptor> slotRefMap;
- Map<ExprId, Predicate> conjuncts;
- Map<TupleId, List<ExprId> > tuplePredicates;
- Map<SlotId, List<ExprId> > slotPredicates;
- Map<TupleId, List<ExprId> > eqJoinConjuncts;
- Set<ExprId> assignedConjuncts;
- Map<TupleId, TableRef> outerJoinedTupleIds;
- Map<TableRef, List<ExprId> > conjunctsByOjClouse;
- Map<ExprId, TableRef> ojClouseByConjunct;
- Set<ExprId> whereClauseConjuncts;
4 生成執行計劃和Planner
Planner負責将分析後的文法樹轉換成執行計劃,即PlanFragments。
Planner的入口函數是Planner::createPlanFragments()。其主要流程如下:
-
createSinglePlan:
根據文法分析的結果,周遊并生成一個邏輯執行計劃樹。樹中的節點是PlanNode。樹的根節點是最後被執行的節點。
-
createPlanFragments:
将生成的執行計劃切割成多個PlanFragment。這個過程類似Hive中将執行計劃分割成多個MapRed階段。目前Impala劃分階段的規則是:如果遇到ScanNode, HashJoinNode, MergeNode, AggregationNode, SortNode,則産生一個新的PlanFragment。每一個PlanFragment之間通過ExchangeNode相連。ExchangeNode在運作時中會負責跨Impalad的資料傳輸。
-
computeMemLayout:
對于輸入表,計算在記憶體中的layout。主要目的是為了計算一條記錄在記憶體中會占用多少位元組(由TupleDescriptor描述),以及每一個字段在記憶體中如何分布(由SlotDescriptor描述)。
最後PlanFragments就會成為實體執行計劃,轉成thrift後傳回給前端。
5 Catalog
Impala直接使用了Hive的HiveMeteStoreClient類,用于通路中繼資料。這就意味着,必須還要啟動一個HiveMetaStore程序,用于提供中繼資料服務。目前Catalog預設采用lazy模式,隻在需要時加載database和table對象。
Catalog主要在文法分析階段使用,用于擷取Hive中繼資料,目前在Planner中沒有使用Catalog。
Author: <[email protected]>
Date: 2013-02-20 19:43:07 CST
HTML generated by org-mode 6.21b in emacs 23