您的位置:首页 > Web前端

Impala学习--Impala前端代码分析

2013-02-20 19:40 591 查看

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

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: <kyle@localhost.localdomain>
Date: 2013-02-20 19:43:07 CST
HTML generated by org-mode 6.21b in emacs 23
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  impala