接了一个新需求:需要做数据仓库的血缘关系。正所谓兵来将挡水来土掩,那咱就动手吧。

  血缘关系是数据治理的一块,其实有专门的第三方数据治理框架,但考虑到目前的线上环境已经趋于稳定,引入新的框架无疑是劳民伤财,伤筋动骨,所以就想以最小的代价把这个事情给做了。目前我们考虑做的血缘关系呢只是做输入表和输出表,最后会形成一张表与表之间的链路图。这个东西的好处就是有助于仓库人员梳理业务,后面可能还会做字段之间的血缘关系等,后面做了再说,今天只是记录一下输入表和输出表的血缘关系。

  我们线上的环境用来做etl的是hive sql和spark sql,所以想到的就是将hive sql和spark sql都拦截下来,然后通过语法解析,解析出其中的输入表和输出表。搞完这个这事就算是大功告成了。

  首先第一步是拦截hive sql和spark sql,这个呢我们是直接在hive和spark的源码中切入了一小段代码用来拦截sql,然后将拦截到的sql存入到mysql中,这个暂且不做记录,后续补充,这里的重点是sql的解析。

  其实做hive的血缘关系分析在源码中是有一个类可以参考的:org.apache.hadoop.hive.ql.tools.LineageInfo, 不过呢,这个例子不全面,不能覆盖到我们线上的情况。比如 hive中的with语法,create table语法就不能覆盖到,好巧不巧,跟仓库的同事聊过之后,with这种语法也是用的很多的,所以只需要在这个例子上加上一些东东,就基本可以满足我们的需求啦。

  总结一下:其实做表与表之间的血缘关系只需要考虑到下面几种语法就差不多了:with, create table , insert, select; 可能我说的不全面,但我目前了解的情况大概就是这些。下面是hive的解析的核心代码:

  

public class LineageUtils implements NodeProcessor {// 存放输入表TreeSet<String> inputTableList = new TreeSet<String>();// 存放目标表TreeSet<String> outputTableList = new TreeSet<String>();//存放with子句中的别名, 最终的输入表是 inputTableList减去withTableListTreeSet<String> withTableList = new TreeSet<String>();public TreeSet getInputTableList() {return inputTableList;}public TreeSet getOutputTableList() {return outputTableList;}public TreeSet getWithTableList() {return withTableList;}public Object process(Node nd, Stack stack, NodeProcessorCtx procCtx, Object... nodeOutputs) throws SemanticException {ASTNode pt = (ASTNode) nd;switch (pt.getToken().getType()) {//create语句case HiveParser.TOK_CREATETABLE: {String createName = BaseSemanticAnalyzer.getUnescapedName((ASTNode) pt.getChild(0));outputTableList.add(createName);break;}//insert语句case HiveParser.TOK_TAB: {// System.out.println(pt.getChildCount() + "tab");String insertName = BaseSemanticAnalyzer.getUnescapedName((ASTNode) pt.getChild(0));outputTableList.add(insertName);//  System.out.println("insertName  " + insertName);break;}//from语句case HiveParser.TOK_TABREF: {ASTNode tabTree = (ASTNode) pt.getChild(0);String fromName = (tabTree.getChildCount() == 1) ? BaseSemanticAnalyzer.getUnescapedName((ASTNode) tabTree.getChild(0)) : BaseSemanticAnalyzer.getUnescapedName((ASTNode) tabTree.getChild(0)) + "." + tabTree.getChild(1);inputTableList.add(fromName);break;}// with.....语句case HiveParser.TOK_CTE: {for (int i = 0; i < pt.getChildCount(); i++) {ASTNode temp = (ASTNode) pt.getChild(i);String cteName = BaseSemanticAnalyzer.getUnescapedName((ASTNode) temp.getChild(1));withTableList.add(cteName);}break;}}return null;}public void getLineageInfo(String query) throws ParseException, SemanticException {ParseDriver pd = new ParseDriver();ASTNode tree = pd.parse(query);while ((tree.getToken() == null) && (tree.getChildCount() > 0)) {tree = (ASTNode) tree.getChild(0);}inputTableList.clear();outputTableList.clear();withTableList.clear();Map<Rule, NodeProcessor> rules = new LinkedHashMap<Rule, NodeProcessor>();Dispatcher disp = new DefaultRuleDispatcher(this, rules, null);GraphWalker ogw = new DefaultGraphWalker(disp);ArrayList topNodes = new ArrayList();topNodes.add(tree);ogw.startWalking(topNodes, null);}//进行测试,sql语句是瞎写的,但是语法是对的public static void main(String[] args) throws IOException, ParseException, SemanticException {//String query = "insert into qc.tables_lins_cnt partition(dt='2016-09-15') select a.x from (select x from cc group by x) a left  join yy b on a.id = b.id left join (select * from zz where id=1) c on c.id=b.id";// String query ="from (select id,name from xx where id=1) a insert overwrite table  dsl.dwm_all_als_active_d partition (dt='main') select id group by id insert overwrite table  dsl.dwm_all_als_active_d2 partition (dt='main') select name group by name";String query = "with q1 as ( select key from src where key = '5'), q2 as ( select key from with1 a inner join with2 b on a.id = b.id) insert overwrite table temp.dt_mobile_play_d_tmp2 partition(dt='2018-07-17') select * from q1 cross join q2";LineageUtils lep = new LineageUtils();lep.getLineageInfo(query);System.out.println("Input tables = " + lep.getInputTableList());System.out.println("Output tables = " + lep.getOutputTableList());System.out.println("with tables = " + lep.getWithTableList());}
}

  上述代码的运行需要引入maven依赖:

  <dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>1.1.0</version>
  </dependency>

  这样核心的解析基本上就大功告成啦,spark sql虽然与hive sql有些差别,但是核心的解析还是照样可以用到这个类的,只不过有些地方需要注意,后面会继续进行记录。

  注:这个类只是进行解析的工具类,还有一些细节需要进行考虑,比如sql语句中没有带 database,也就是如果sql中的表不是 database.tablename的形式,该怎么处理?这个时候就需要考虑上下文中的切库(比如 use temp)处理了, 不过这不是什么大问题,是可以解决的。我们想到的解决步骤就在拦截sql的那一层进行的处理,如果有切库的操作,就先把库记录下来,等sql解析完成之后,再去遍历哪些表没有带数据库,将没有带库的表面拼接上先前记录的库即可。

转载于:https://www.cnblogs.com/wuxilc/p/9326130.html

hive血缘关系之输入表与目标表的解析相关推荐

  1. (二)ODS层更新:源表和目标表,没有last_update,比对取增量,却重复抽到某部分数据,怎么解决?

    源表和目标表,比对的时候,某部分数据,每次比对都被认为是"新数据",然后每次抽取比对都会被过滤到目标表,从而造成目标表有很多重复数据,是什么原因呢?原因是该表的多个字段" ...

  2. python对比excel两列数据_python 对比excel表格数据表-python实现两个excel表列数据对比若源表与目标表存......

    在数据分析方面,比起python,excel的局限性在哪 data3 = pandas.merge(data1, data2, on=['名称'], how='inner') inner:内连接,取交 ...

  3. Mysql 数据血缘关系图_hive血缘关系之输入表与目标表的解析

    接了一个新需求:需要做数据仓库的血缘关系.正所谓兵来将挡水来土掩,那咱就动手吧. 血缘关系是数据治理的一块,其实有专门的第三方数据治理框架,但考虑到目前的线上环境已经趋于稳定,引入新的框架无疑是劳民伤 ...

  4. 搜狐 Hive SQL 血缘关系解析与应用

    1. 研究背景 随着企业信息化和业务的发展,数据资产日益庞大,数据仓库构建越来越复杂,在数仓构建的过程中,常遇到数据溯源困难,数据模型修改导致业务分析困难等难题,此类问题主要是由于数据血缘分析不足造成 ...

  5. 【文末有惊喜!】Hive SQL血缘关系解析与应用

    本文字数:7860字 预计阅读时间:20分钟 + 1 研究背景 随着企业信息化和业务的发展,数据资产日益庞大,数据仓库构建越来越复杂,在数仓构建的过程中,常遇到数据溯源困难,数据模型修改导致业务分析困 ...

  6. flink批量写入oracle,批量写入目标表存在重复写入问题

    测试场景 源表字符串类型数据存储到目标表整型数据类型,批量写入,发现有重复写入目标表问题 测试的时候发现:当批量写入抛出异常的时候,产生2个结果,1.写入部分数据 2.程序转到处理异常的代码块,在异常 ...

  7. mysql++快速复制大表_MySql数据库表快速复制

    表索引操作 这里之所以写索引的操作主要原因在于:在导入数据前删除索引能大大提升导入速度. DDL语句获取现有索引1show create table t_question_bak; 获取所有索引 获取 ...

  8. 推荐两则基于解析SQL的表间血缘关系工具

    推荐两则基于解析SQL的表间血缘关系工具 基于大数据脚本,可以用Apache Atlas做元数据的血缘关系分析,很多金融机构仍然在使用老的遗留系统,比如老版本的Hive.数据库存储过程,如何反查表间的 ...

  9. 解析SQL的表间血缘关系工具

    一.sqllineage SQL Lineage Analysis Tool powered by Python 源码地址:https://github.com/reata/sqllineage 安装 ...

最新文章

  1. linux 文本行倒叙,Linux基础(4)之文本处理
  2. rock-paper-scissors
  3. 实战SSM_O2O商铺_31【商品】商品添加之View层的实现
  4. 在ubuntu用arm ds-5社区版配合linaro交叉编译工具开发android linux应用
  5. 鸿蒙系统下拉菜单,鸿蒙的js开发部模式17:鸿蒙的系统能力的应用模块
  6. 深海迷航创造模式火箭怎么飞_深海迷航被玩成养鱼游戏 奇葩玩家的养殖之路...
  7. Java:JDK、JRE和JVM的关系(图示详解,一眼就能看明白!)
  8. Xcode和macOS对应关系查询网址
  9. Luogu3431 [POI2005]AUT-The Bus
  10. html5回到顶部代码,JS返回顶部实例代码
  11. 如何去掉CAD教育版打印戳记
  12. Linux命令大全(超详细版)
  13. 关于dijistra算法的理解
  14. EOS与ESD的区别
  15. java程序员面试笔试宝典4.1基本概念
  16. 2022年全球市场颈椎按摩仪总体规模、主要生产商、主要地区、产品和应用细分研究报告
  17. 基于搜狗微信爬取微信公众号的文章
  18. 连接tcp服务器出现的问题及解决方法
  19. 银河麒麟V10 SP1服务版虚拟机安装
  20. 【MCAL_CANDriver】-1.2-Can Mailbox邮箱,Hardware Object,HOH,HRH,HTH之间的关系

热门文章

  1. android studio outline,AndroidStudio常用设置
  2. mysql 正则 换行符_MySQL 正则表达式
  3. php配合jade使用,详解基于模板引擎Jade的应用
  4. 使用迁移学习后使用微调再次提高模型训练的准确率
  5. Java判定1到4可以组成多少个互不相同且无重复的三位数
  6. 超有意思的代码注释_程序员搞笑的代码注释:谁的代码注释我都不服,就服你的...
  7. css背景图毛玻璃,css实现背景图片的毛玻璃效果
  8. mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目
  9. Transformer、BERT细节基础知识点
  10. 视频讲解(RCNN,FasterRCNN,FPN,MaskRCNN)