【二 Hive3.1.2源码阅读--SQL的解析、编译、优化】
- 从前文中可以看到
runInternal调用了compile方法,在compile方法我们可以看到执行了以下步骤:
1.1 首先通过ParseUtils.parse将sql解析为抽象的语法树ASTNode
1.2 然后通过sem.analyze(tree, ctx);对解析出来的抽象语法树进行编译和优化 - 我们先进入
ParseUtils.parse中进行查看
/** Parses the Hive query. */public static ASTNode parse(String command, Context ctx) throws ParseException {return parse(command, ctx, null);}/** Parses the Hive query. */public static ASTNode parse(String command, Context ctx, String viewFullyQualifiedName) throws ParseException {ParseDriver pd = new ParseDriver();ASTNode tree = pd.parse(command, ctx, viewFullyQualifiedName);tree = findRootNonNullToken(tree);handleSetColRefs(tree);return tree;} 2.1 进入pd.parse(command, ctx, viewFullyQualifiedName);2.1.1首先调用
new HiveLexerX(new ANTLRNoCaseStringStream(command))对sql进行词法语法解析得到一个词法解析器,使用的是antlr框架(其是什么后续介绍)2.1.2 根据词法解析器得到token(具有特殊意义的字符串的封装)
tokens = new TokenRewriteStream(lexer)2.1.3 根据token生成解析器
parser = new HiveParser(tokens)2.1.4 根据解析器可以获取statment然后获取抽象语法树
tree = (ASTNode) r.getTree()public ASTNode parse(String command, Context ctx, String viewFullyQualifiedName)throws ParseException {if (LOG.isDebugEnabled()) {LOG.debug("Parsing command: " + command);}// 语法分析HiveLexerX 是一个词法解析类HiveLexerX lexer = new HiveLexerX(new ANTLRNoCaseStringStream(command));//词法语法的解析(使用antlr框架)// 根据词法分析的结果得到tokens的,此时不只是单纯的字符串,而是具有特殊意义的字符串的封装,其本身是一个流 。TokenRewriteStream tokens = new TokenRewriteStream(lexer);//得到tokenif (ctx != null) {if (viewFullyQualifiedName == null) {// Top level queryctx.setTokenRewriteStream(tokens);} else {// It is a viewctx.addViewTokenRewriteStream(viewFullyQualifiedName, tokens);}lexer.setHiveConf(ctx.getConf());}// HiveParser是一个语法解析类HiveParser parser = new HiveParser(tokens);//转化为解析器if (ctx != null) {parser.setHiveConf(ctx.getConf());}parser.setTreeAdaptor(adaptor);HiveParser.statement_return r = null;try {r = parser.statement();} catch (RecognitionException e) {e.printStackTrace();throw new ParseException(parser.errors);}if (lexer.getErrors().size() == 0 && parser.errors.size() == 0) {LOG.debug("Parse Completed");} else if (lexer.getErrors().size() != 0) {throw new ParseException(lexer.getErrors());} else {throw new ParseException(parser.errors);}ASTNode tree = (ASTNode) r.getTree();//得到抽象语法树tree.setUnknownTokenBoundaries();return tree;} - 获取到抽象语法树以后,下一步就是执行编译和优化
sem.analyze(tree, ctx);
3.1 进入analyze方法
public void analyze(ASTNode ast, Context ctx) throws SemanticException {//初始化上下文initCtx(ctx);init(true);// 其中analyzeInternal是抽象方法,由不同的子类实现,较为复杂 。// 大致功能为将ASTNode转化为Task,包括可能的optimizeanalyzeInternal(ast);} 3.2 从上文可以看到其调用了analyzeInternal方法其中analyzeInternal是抽象方法,由不同的子类实现,较为复杂 。大致功能为将ASTNode转化为Task,包括可能的optimize
4. 编译优化执行完以后,将任务转化为QueryPlan
plan = new QueryPlan()5. 最后回到前文的类中,执行execute方法将QueryPlan转化为MR任务
6. 最终sql的解析、编译、优化可以按以下图片的步骤执行
6.1 将sql语句转化为抽象语法树
6.2 根据抽象语法树生成基本的执行单元QueryBlock
6.3 根据QueryBlock生成操作树OperatorTree
6.4 对操作树OperatorTree进行优化
6.5 将优化后的操作树转化为任务树TaskTree
6.6 对任务树TaskTree进行物理优化
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
