Hive SQL解析/执行计划生成流程分析
2013-10-21 15:59
295 查看
Hive有三种用户接口:
在hive shell中输入“show tables;”实际执行的是:
CLI入口函数:cli.CliDriver.main()
读入参数->建立SessionState并导入配置->处理输入文件中指令CliDriver.processFile();或交互型指令CliDriver.processLine()->解析输入CliDriver.processCmd()
(1)如果是quit或者exit,退出
(2)以source开头的,读取外部文件并执行文件中的HiveQL
(3)!开头的命令,执行操作系统命令(如!ls,列出当前目录的文件信息)
(4)list,列出jar/file/archive
(5)其他命令,则生成调用相应的CommandProcessor处理,进入CliDriver.processLocalCmd()
下面看看CliDriver.processLocalCmd()这个函数:
set/dfs/add/delete指令交给指定的CommandProcessor处理,其余的交给org.apache.hadoop.hive.ql.Driver.run()处理
org.apache.hadoop.hive.ql.Driver类是查询的起点,run()方法会先后调用compile()和execute()两个函数来完成查询,所以一个command的查询分为compile和execute两个阶段。
Compile
(1)利用antlr生成的HiveLexer.java和HiveParser.java类,将HiveQL转换成抽象语法树(AST)。
首先使用antlr工具将srcqlsrcjavaorgapachehadoophiveqlparsehive.g编译成以下几个文件:HiveParser.java, Hive.tokens, Hive__.g, HiveLexer.java
HiveLexer.java和HiveParser.java分别是词法和语法分析类文件,Hive__.g是HiveLexer.java对应的词法分析规范,Hive.tokens定义了词法分析后所有的token。
然后沿着“Driver.compile()->ParseDriver.parse(command, ctx)->HiveParserX.statement()->antlr中的API”这个调用关系把输入的HiveQL转化成 ASTNode类型的语法树。HiveParserX是由antlr生成的HiveParser类的子类。
(2)利用对应的SemanticAnalyzer类,将AST树转换成Map-reduce task。主要分为三个步骤:
a)AST -> operator DAG
b)optimize operator DAG
c)oprator DAG -> Map-reduce task
首先接着上一步生成的语法树ASTNode, SemanticAnalyzerFactory会根据ASTNode的token类型生成不同的 SemanticAnalyzer (所有这些SemanticAnalyzer都继承自BaseSemanticAnalyzer)
1)ExplainSemanticAnalyzer
2)LoadSemanticAnalyzer
3)ExportSemanticAnalyzer
4)DDLSemanticAnalyzer
5)FunctionSemanticAnalyzer
6)SemanticAnalyzer
然后调用BaseSemanticAnalyzer.analyze()->BaseSemanticAnalyzer. analyzeInternal()。
下面以最常见的select * from table类型的查询为例,进入的子类是SemanticAnalyzer. analyzeInternal(),这个函数的逻辑如下:
1)doPhase1():将sql语句中涉及到的各种信息存储起来,存到QB中去,留着后面用。
2)getMetaData():获取元数据信息,主要是sql中涉及到的 表 和 元数据 的关联
3)genPlan():生成operator tree/DAG
4)optimize:优化,对operator tree/DAG 进行一些优化操作,例如列剪枝等(目前只能做rule-based optimize,不能做cost-based optimize)
5)genMapRedTasks():将operator tree/DAG 通过一定的规则生成若干相互依赖的MR任务
Execute
将Compile阶段生成的task信息序列化到plan.xml,然后启动map-reduce,在configure时反序列化plan.xml
实例分析:
在hive中有这样一张表:
执行如下的查询:
通过explain命令可以查看执行计划:
依照hive.g的语法规则,生成AST如下:
生成的执行计划operator tree/DAG如下:
Hive优化策略:
1. 去除查询中不需要的column
2. Where条件判断等在TableScan阶段就进行过滤
3. 利用Partition信息,只读取符合条件的Partition
4. Map端join,以大表作驱动,小表载入所有mapper内存中
5. 调整Join顺序,确保以大表作为驱动表
6. 对于数据分布不均衡的表Group by时,为避免数据集中到少数的reducer上,分成两个map-reduce阶段。第一个阶段先用Distinct列进行shuffle,然后在 reduce端部分聚合,减小数据规模,第二个map-reduce阶段再按group-by列聚合。
7. 在map端用hash进行部分聚合,减小reduce端数据处理规模。
参考文献: http://fatkun.com/2013/01/hive-group-by.html
原文网址: Hive SQL解析/执行计划生成流程分析
请我喝咖啡
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons
BY-NC-ND 3.0
cli (Command line interface) | bin/hive或bin/hive –service cli | 命令行方式(默认) |
hive-server/hive-server2 | bin/hive –service hiveserver 或bin/hive –service hiveserver2 | 通过JDBC/ODBC和Thrift访问(Impala通过这种方式借用hive-metastore) |
hwi (Hive web interface) | bin/hive –service hwi | 通过浏览器访问 |
在hive shell中输入“show tables;”实际执行的是:
1 | bin /hadoop jar hive /lib/hive-cli-0 .9.0.jar org.apache.hadoop.hive.cli.CliDriver -e 'SHOW TABLES;' |
读入参数->建立SessionState并导入配置->处理输入文件中指令CliDriver.processFile();或交互型指令CliDriver.processLine()->解析输入CliDriver.processCmd()
(1)如果是quit或者exit,退出
(2)以source开头的,读取外部文件并执行文件中的HiveQL
(3)!开头的命令,执行操作系统命令(如!ls,列出当前目录的文件信息)
(4)list,列出jar/file/archive
(5)其他命令,则生成调用相应的CommandProcessor处理,进入CliDriver.processLocalCmd()
下面看看CliDriver.processLocalCmd()这个函数:
set/dfs/add/delete指令交给指定的CommandProcessor处理,其余的交给org.apache.hadoop.hive.ql.Driver.run()处理
org.apache.hadoop.hive.ql.Driver类是查询的起点,run()方法会先后调用compile()和execute()两个函数来完成查询,所以一个command的查询分为compile和execute两个阶段。
Compile
(1)利用antlr生成的HiveLexer.java和HiveParser.java类,将HiveQL转换成抽象语法树(AST)。
首先使用antlr工具将srcqlsrcjavaorgapachehadoophiveqlparsehive.g编译成以下几个文件:HiveParser.java, Hive.tokens, Hive__.g, HiveLexer.java
HiveLexer.java和HiveParser.java分别是词法和语法分析类文件,Hive__.g是HiveLexer.java对应的词法分析规范,Hive.tokens定义了词法分析后所有的token。
然后沿着“Driver.compile()->ParseDriver.parse(command, ctx)->HiveParserX.statement()->antlr中的API”这个调用关系把输入的HiveQL转化成 ASTNode类型的语法树。HiveParserX是由antlr生成的HiveParser类的子类。
(2)利用对应的SemanticAnalyzer类,将AST树转换成Map-reduce task。主要分为三个步骤:
a)AST -> operator DAG
b)optimize operator DAG
c)oprator DAG -> Map-reduce task
首先接着上一步生成的语法树ASTNode, SemanticAnalyzerFactory会根据ASTNode的token类型生成不同的 SemanticAnalyzer (所有这些SemanticAnalyzer都继承自BaseSemanticAnalyzer)
1)ExplainSemanticAnalyzer
2)LoadSemanticAnalyzer
3)ExportSemanticAnalyzer
4)DDLSemanticAnalyzer
5)FunctionSemanticAnalyzer
6)SemanticAnalyzer
然后调用BaseSemanticAnalyzer.analyze()->BaseSemanticAnalyzer. analyzeInternal()。
下面以最常见的select * from table类型的查询为例,进入的子类是SemanticAnalyzer. analyzeInternal(),这个函数的逻辑如下:
1)doPhase1():将sql语句中涉及到的各种信息存储起来,存到QB中去,留着后面用。
2)getMetaData():获取元数据信息,主要是sql中涉及到的 表 和 元数据 的关联
3)genPlan():生成operator tree/DAG
4)optimize:优化,对operator tree/DAG 进行一些优化操作,例如列剪枝等(目前只能做rule-based optimize,不能做cost-based optimize)
5)genMapRedTasks():将operator tree/DAG 通过一定的规则生成若干相互依赖的MR任务
Execute
将Compile阶段生成的task信息序列化到plan.xml,然后启动map-reduce,在configure时反序列化plan.xml
实例分析:
在hive中有这样一张表:
uid | fruit_name | count |
a | apple | 5 |
a | orange | 3 |
a | apple | 2 |
b | banana | 1 |
1 | SELECT uid, SUM ( count ) FROM logs GROUP BY uid |
通过explain命令可以查看执行计划:
1 | EXPLAIN SELECT uid, SUM ( count ) FROM logs GROUP BY uid; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ABSTRACT SYNTAX TREE: ( TOK_QUERY (TOK_FROM (TOK_TABREF (TOK_TABNAME logs))) ( TOK_INSERT (TOK_DESTINATION (TOK_DIR TOK_TMP_FILE)) ( TOK_SELECT (TOK_SELEXPR (TOK_TABLE_OR_COLuid)) (TOK_SELEXPR (TOK_FUNCTION sum (TOK_TABLE_OR_COL count ))) ) (TOK_GROUPBY ) ) |
生成的执行计划operator tree/DAG如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | STAGE DEPENDENCIES: Stage-1 is a root stage Stage-0 is a root stage STAGE PLANS: Stage: Stage-1 Map Reduce Alias -> Map Operator Tree: logs TableScan // 扫描表 alias: logs Select Operator //选择字段 expressions: expr: uid type: string expr: count type: int outputColumnNames: count Group By Operator //在map端先做一次聚合,减少shuffle数据量 aggregations: expr: sum ( count ) //聚合函数 bucketGroup: false keys: expr: uid type: string mode: hash outputColumnNames: _col0, _col1 Reduce Output Operator //输出 key ,value给reduce key expressions: expr: _col0 type: string sort order : + Map-reduce partition columns: expr: _col0 type: string tag: -1 value expressions: expr: _col1 type: bigint Reduce Operator Tree: Group By Operator aggregations: expr: sum (VALUE._col0) //聚合 bucketGroup: false keys: expr: KEY ._col0 type: string mode: mergepartial outputColumnNames: _col0, _col1 Select Operator //选择字段 expressions: expr: _col0 type: string expr: _col1 type: bigint outputColumnNames: _col0, _col1 File Output Operator //输出到文件 compressed: false GlobalTableId: 0 table : input format: org.apache.hadoop.mapred.TextInputFormat output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat Stage: Stage-0 Fetch Operator limit: -1 |
1. 去除查询中不需要的column
2. Where条件判断等在TableScan阶段就进行过滤
3. 利用Partition信息,只读取符合条件的Partition
4. Map端join,以大表作驱动,小表载入所有mapper内存中
5. 调整Join顺序,确保以大表作为驱动表
6. 对于数据分布不均衡的表Group by时,为避免数据集中到少数的reducer上,分成两个map-reduce阶段。第一个阶段先用Distinct列进行shuffle,然后在 reduce端部分聚合,减小数据规模,第二个map-reduce阶段再按group-by列聚合。
7. 在map端用hash进行部分聚合,减小reduce端数据处理规模。
参考文献: http://fatkun.com/2013/01/hive-group-by.html
原文网址: Hive SQL解析/执行计划生成流程分析
请我喝咖啡
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons
BY-NC-ND 3.0
相关文章推荐
- Hive SQL解析/执行计划生成流程分析
- Hive SQL解析/执行计划生成流程分析
- Impala源代码分析(2)-SQL解析与执行计划生成
- hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR
- Hive SQL执行计划深度解析
- Hive 之 SQL执行计划深度解析
- Hive SQL解析/执行计划生成流程分析
- Hive SQL执行计划解析
- Hive SQL执行计划深度解析
- Hive SQL执行计划深度解析
- Hive SQL执行流程分析
- hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR
- hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR
- Hive SQL执行计划深度解析
- hive执行流程(3)-Driver类分析1Driver类整体流程 推荐
- SQL点滴—性能分析之执行计划
- SQL执行计划分析
- [转]通过分析SQL语句的执行计划优化SQL (七)[5]
- 深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
- AutoTRACE是分析SQL的执行计划,执行效率的一个非常简单方便的工具