自定义hivehook(二)-解析血缘-转载
转载:https://www.jianshu.com/p/30eb687e0b94
上一篇关于hivehook的转载博文已经可以拿到任务执行的SQL,但是任务的上下游血缘还是需要依赖druid来解析实现。
其实根据hivehook的插入阶段来看,我们是可以拿到hive的执行计划的。
本次就从这个执行计划下手,在hook中实现血缘的解析。
-
Pre-semantic-analyzer hooks:在Hive在查询字符串上运行语义分析器之前调用。
-
Post-semantic-analyzer hooks:在Hive在查询字符串上运行语义分析器之后调用。
-
Pre-driver-run hooks:在driver执行查询之前调用。
-
Post-driver-run hooks:在driver执行查询之后调用。
-
Pre-execution hooks:在执行引擎执行查询之前调用。
-
Post-execution hooks:在查询执行完成之后以及将结果返回给用户之前调用。
-
Failure-execution hooks:当查询执行失败时调用。
public class LineageHook implements ExecuteWithHookContext { private static final HashSet<String> OPERATION_NAMES = new HashSet<String>(); private static final HashSet<String> INPUTS = new HashSet<String>(); private static final HashSet<String> OUTPUTS = new HashSet<String>(); static { OPERATION_NAMES.add(HiveOperation.QUERY.getOperationName()); OPERATION_NAMES.add(HiveOperation.CREATETABLE_AS_SELECT.getOperationName()); OPERATION_NAMES.add(HiveOperation.ALTERVIEW_AS.getOperationName()); OPERATION_NAMES.add(HiveOperation.CREATEVIEW.getOperationName()); OPERATION_NAMES.add(HiveOperation.LOAD.getOperationName());//在原有基础上,开放load语句 } @Override public void run(HookContext hookContext) throws Exception { INPUTS.clear(); OUTPUTS.clear(); QueryPlan plan = hookContext.getQueryPlan(); LineageCtx.Index index = hookContext.getIndex(); SessionState ss = SessionState.get(); if (ss != null && index != null && OPERATION_NAMES.contains(plan.getOperationName()) && !plan.isExplain()) { System.out.println(plan.getOperationName()); //输出 for (WriteEntity output : plan.getOutputs()) { Entity.Type entityType = output.getType(); if (entityType == Entity.Type.TABLE || entityType == Entity.Type.PARTITION || entityType == Entity.Type.LOCAL_DIR //放行LOCAL_DIR || entityType == Entity.Type.DFS_DIR //放行DFS_DIR ) { Table trgTb = output.getTable(); String trgTbName = null; if (trgTb!=null) { trgTbName = trgTb.getDbName()+"."+trgTb.getTableName(); }else { trgTbName = output.getD().toString(); //hdfs://master:8020/tmp/hive/admin/27808155-878a-4446-9c4e-a2f3388301fc/hive_2020-06-19_16-47-52_939_789950828629061887-1/-mr-10001 if (trgTbName.matches("hdfs://.+/tmp/hive/.+")) {// 过滤MR中间临时落地数据的路径 continue; } } // System.out.println("target table "+trgTbName);l if (OUTPUTS.contains(trgTbName)) { continue; }else { OUTPUTS.add(trgTbName); } break; } } if (OUTPUTS.size()==0) {//如果没有输出,不获取输入,相当于屏蔽了无输出的简单Query return; } //输入 for (ReadEntity input : plan.getInputs()) { Entity.Type entityType = input.getType(); if (entityType == Entity.Type.TABLE || entityType == Entity.Type.PARTITION || entityType == Entity.Type.LOCAL_DIR || entityType == Entity.Type.DFS_DIR ) { Table srcTb = input.getTable(); String srcTbName = null; if (srcTb!=null) { srcTbName = srcTb.getDbName()+"."+srcTb.getTableName(); }else { srcTbName = input.getD().toString(); if (srcTbName.matches("hdfs://.+/tmp/hive/.+")) { continue; } } INPUTS.add(srcTbName); //用HashSet装输入源名称,因为多分区输入时会有多个ReadEntity 这些Entity表名是相同的 // System.out.println("src table "+srcTbName); } } System.out.println("INPUT="+String.join(",",INPUTS)); System.out.println("OUTPUT="+String.join(",",OUTPUTS)); } } }
项目依赖跟上一篇hivehook一样。
一次性执行在hive命令行可以执行下面两条命令。但会话结束就结束了。
add jar /opt/module/hive-hook-1.0-SNAPSHOT.jar
set hive.exec.post.hooks=cc.eslink.hook.LineageHook;
永久生效的话,上传jar包,添加jar包到hive-lib,修改hive-site.xml
/opt/cloudera/parcels/CDH/lib/hive/lib
这样就进一步拿到了血缘关系。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南