1. 研究背景
随着企业信息化和业务的发展,数据资产日益庞大,数据仓库构建越来越复杂,在数仓构建的过程中,常遇到数据溯源困难,数据模型修改导致业务分析困难等难题,此类问题主要是由于数据血缘分析不足造成的,只有强化血缘关系,才能帮助企业更好的发挥数据价值。
SQL 血缘关系是数据仓库模型构建的核心依赖。通过对 SQL 语句进行梳理与解析,得到各个业务层表之间依赖关系和属性依赖关系,并进行可视化展示,形成数据表和属性血缘层次关系图,充分展示了原始字段数据与数据模型的映射关系。拥有良好的 SQL 血缘关系系统,不仅有利于数据分析师对业务场景的梳理,还极大帮助对其数仓分层的构建,同时对企业数据质量控制方面起到很好的朔源作用,对构造数据链路图,监控数据变化起到很好的辅助作用。
市场存在一系列血缘关系解析工具,如 Druids,但由于只支持对 MySQL 语句的解析,且解析力度不够,不支持复杂的 SQL 逻辑等问题,导致无法在企业中得到广泛使用。同样 Hive 自身的血缘解析往往在 SQL 执行之后,才可得到解析结果,如果 SQL 执行比较耗时,导致血缘关系无法快速展现,同时造成没有办法提前进行元数据安全和权限认证等问题,在企业真实应用中有一定的限制。
本文结合公司自身业务,研究 Hive 血缘关系解析源码,并进行优化,首先简化 SQL 语句剪枝和对包含CTE 别名数据表的识别与剔除,降低 SQL 解析的复杂性,提高血缘解析性能;其次,提供元数据信息服务模块,既保证元信息的完整性,又提供安全的数据表权限认证,维护数据表的操作权限,保证操作的安全性;然后,将 postExecuteHook 前置,即在 SQL 执行物理优化前即可获得 SQL 的血缘关系,极大提高了获取 SQL 血缘关系的效率,后续将对这些优化策略进行逐一展开。
2. 相关技术介绍
2.1 SQL 血缘关系介绍
在数据仓库构建的过程中,SQL 血缘关系体现了各个数据表以及相关属性的依赖关系。SQL 血缘关系即是对业务流程涉及到的模型表进行梳理,包含了集群血缘关系、系统血缘关系、表级血缘关系和字段血缘关系,其指向数据的上游来源,向上游追根溯源。通过简单的 SQL 语句展现各个表之间的数据关系。
INSERT overwrite TABLE ads_shmm_wap_homepage_s3_nu_retention_1d_di PARTITION (dt=${SYSTEM_BIZDATE})
SELECT
a.source_first_id,
a.source_second_id,
a.source_third_id,
b.vst_cookie
FROM (
SELECT
source_first_id,
source_second_id,
source_third_id,
vst_cookie
FROM ads_shmm_wap_homepage_s3_new_cookie_di
WHERE dt=$[yyyyMMdd-2]
) a
JOIN (
SELECT vst_cookie
FROM ads_shmm_wap_homepage_cookie_di
WHERE dt=${SYSTEM_BIZDATE}
) b
ON a.vst_cookie = b.vst_cookie;
通过SQL血缘关系解析,得到的对应的血缘关系依赖图,如下图所示:
对应字段关系示意图如下所示:
血缘关系一般是指表级和字段级,其能清晰展现数据加工处理逻辑脉络,快速定位数据异常字段影响范围,准确圈定最小范围数据回溯,降低了理解数据和解决数据问题的成本。同时数据血缘关系可与数据质量监控系统进行完美的整合,重要数据质量检测异常结果可通过数据血缘关系直接定位影响范围。
2.2 ANTLR 技术介绍
Atlas 是 Apache 开源的元数据治理方案。Hook 执行中采集数据(如hivehook),发送 Kafka,消费 Kafka数据,生成 Relation 关系保存图数据库 Titan,并提供 REST 接口查询功能,支持表血缘,列级支持不完善。
Durid 虽在 SQL 解析中发挥很大的作用,但主要支持 MySQL 语法,对 Hive SQL 仅仅是支持一些简单的操作。
Antlr 作为一个强大的解释器,用来读取,处理,执行或翻译结构化文本或二进制文件。通过 Antlr 可以构造出相应的词法分析器 (Lexer)、语法分析器 (Parser) 和树分析器 (TreeParser)。自动构建解析树的解析器,用于表示语法如何匹配输入的数据结构;自动生成树遍历器,遍历 AST 树的节点以执行特定于应用程序的代码。现通过 ANTLR Works 展示词法分析与语法分析的处理过程,举例如下:
INSERT INTO b SELECT c FROM a
经词法分析,识别字符串中单词,并对字符串进行分类,得到 Token 集合,具体流程如下图所示:
通过 SQL 词法分析,将 SQL 按照词法关键词进行匹配,并按照词性进行分组,最终组装成一个词法树,通过词法树,直观展示 SQL 中相关词所属的组,便于后续抽象语法树的形成。
词法分析之后,经语法分析得到对应抽象语法树,如下图所示:
经过语法分析,初步将 SQL 分解成源表,目标表以及 Query 字段等组,已经初步形成 SQL 血缘脉络。
综上述词法分析与语法分析举例可知,词法分析将 SQL 中涉及到所有词进行识别,并依据相关规则,需将所有的规则进行比对,并对字符串进行分组分类,初步得到词法分析树;语法分析,将 Token 集合简化,找出关键的 TOK 进行组装,更直观的反映出 SQL 的解析逻辑,TOK_QUERY
,TOK_SELECT
,TOK_DESTINATION
以及TOK_TABLENAME
和TOK_INSERT
等,直观的反映出SQL 中数据表的依赖关系。
查询语句和 Insert 语句是 Hive SQL 的核心语句,由上述分析可得查询语句和 Insert 语句语法结构相似,都具有相同的根节点TOK_QUERY
,且都包括 FROM 数据源和 TOK_INSERT
两部分,Insert 部分包含目的数据源、Select 和 body 等部分,简单归纳如下图所示。
词法分析与语法分析之后,将遍历 AST 树,并进行语义分析。此外 ANTLR 提供了监听者模式和访问者模式。由于 Visitor 访问者模式是一种可以控制遍历方式的方式,并且可通过显示调用 visit 方法,完成对叶子节点的访问,使用者可选择性的主动遍历树,从而控制遍历的顺序,因此在血缘解析具有很好的灵活性,因此 SQL 血缘解析采用 Visitor 访问者模式完成对 AST 树的遍历。
2.3 Hive SQL 解析流程介绍
通过以上对 SQL 解析关键过程的概述,现总结 Hive SQL 解析流程如下图所示:
由上图所示流程可知, HQL 解析(生成 AST 语法树) => 语法分析(得到 QueryBlock) => 生成逻辑执行计划(Operator) => 逻辑优化(LogicalOptimizer Operator) => 生成物理执行计划(TaskPlan) => 物理优化(Task Tree) => 构建执行计划(QueryPlan) => 执行引擎执行。
具体展开如下:
- Hive 根据 Antlr 定义的词法、语法规则完成词法、语法分析将 HQL 解析为 AST Tree 即抽象语法树;
- 深度遍历抽象语法树进行语义解析,得到相应的查询的基本组成单元 Query Block;AST Tree 生成QueryBlock 的过程是一个递归的过程,先序遍历 AST Tree,遇到不同的 Token 节点,保存到相应的属性中,主要包含以下几个过程:
- TOK_QUERY =>创建 QB 对象,循环递归子节点
- TOK_FROM => 将表名语法部分保存到 QB 对象的 aliasToTabs 等属性中
- TOK_INSERT=> 循环递归子节点
- TOK_DESTINATION=> 将输出目标的语法部分保存在 QBParseInfo 对象的 nameToDest 属性中
- TOK_SELECT=> 分别将查询表达式的语法部分保存在 destToSelExpr、destToAggregationExprs、destToDistinctFuncExprs三个属性中
- TOK_WHERE=> 将Where部分的语法保存在QBParseInfo对象的destToWhereExpr属性中
- 遍历 Query Block,解析为操作树 OperatorTree,生成逻辑执行计划;
- 逻辑优化器进行操作树变换,合并多余的 ReduceSinkOperator,减少 shuffle,即对应的列剪枝、分区剪枝以及 Join 顺序优化等操作;
- 遍历 Operator Tree,将操作树转变为对应的 MapReduce 任务,生成物理执行计划;
- 物理优化器进行 MapReduce 任务变换,针对最后生成 DAG 图进行优化,生成最终的执行计划。
- 逻辑计划执行;
通过以上对 Hive SQL 解析流程描述,血缘解析以此为基础进行展开。同时注意到传统 Hive SQL 解析流程相对比较繁琐,递归次数多,自定义函数无法识别,以及 Hive Schema 不能支持企业级应用等问题,在血缘解析中进行调整与优化,充分支撑企业数仓级应用。
3. Hive SQL血缘关系解析
结合企业自身业务,对 Hive SQL 血缘关系解析流程进行了一下优化,具体流程如下图所示。
由上图所示,Hive SQL 血缘关系解析主要包括表级别的血缘关系解析以及字段级别的血缘关系解析,并依赖元数据管理模块服务,完成了 SQL 血缘解析,先将从表级和字段级别分别对优化策略进行描述。
3.1 表级别血缘关系解析优化
表级别血缘解析是 HIVE SQL 解析的基础,通过 SQL 快速定位到 SQL 语句中的源表和目标表以及相关条件,通过 DAG 图展示源表与目标表的关系。进一步直观展现数据表的流传。特别是在复杂的 SQL 逻辑下,涉及到多张表部分数据的 Join、Union 等连接形式,通过 DAG 图展示给数据分析师或 ETL 数仓工程师,对企业数据仓库的构建以及数据监控起到重要支撑作用。
表级别血缘关系解析流程如下:
- 【1】对 Hive SQL 进行词法分析和语法分析,获取对应的 AST 原始的抽象语法树。
- 【2】抽象语法树验证与优化
- 语法树有效性验证,通过验证,辅助 ETL 工程师判定书写 SQL 的正确性;
- AST 语法树剪枝优化,减少遍历次数,提高语义解析的效率,具体主要做两方面的优化:
- 针对 Token 中涉及到的无效解析节点进行删除,如 order by,distributedby,cluster by,sort by 以及limit,代码如下:
- 针对 token_where/having 的子查询,在保证 SQL 语法正确性以及语义完整性的前提下,采用 1=1 等价策略进行等价替换,降低了血缘关系解析的复杂性;
- 通过以上两种剪枝操作,既可以减少 SQL 语句的复杂性,又可以降低 AST 语法树的层级,进一步减少了遍历 AST 树递归次数,降低血缘分析的复杂性,提高了语句解析效率;
- 【3】遍历 AST 获取上游表名(TOK_TAB)和下游表名(TOK_TABREF),在 SQL 语句中存在大部分 SQL 语句片段即 CTE。由于其在血缘关系解析中不起关键作用,且对 SQL 解析带来很大困扰,因此血缘关系解析需对 CTE 类型进行识别,并进行替换与删除,具体代码如下。
以上是 Hive SQL 对表级别的血缘关系梳理。通过表血缘关系梳理,直观地展示出了ETL业务中各层数据表的流转,便于ETL工程师或数据分析师清楚的看到一张表的上下游,更方便地查找表关系,对ETL数据仓库的构建起到很好的辅助作用。
3.2 字段级别血缘关系解析优化
字段级别的血缘关系梳理是 Hive 解析中具有重要环节,并支撑血缘关系 DAG 的核心作用:
- 有利于数据分析师回溯数据问题。数据表由 ods 层流转到 dwd 层后,通过对比结果差异很大,需要人工核对分析指标纬度信息,如数据指标来源,经过哪些清洗条件或逻辑,进而找出相应的处理问题;
- 有利于报表分析问题的排查。基础表由于字段类型的改变或精度的改变,需要评估对数仓的影响,通过血缘可以快速定位原始字段和目标字段的数据,便于分析师及时调整处理策略。
- 有利于数据质控阶段监控数据质量变化。如数据表的字段的空值率,重复率以及是否满足数据逻辑率等方面快速监控 ods 数据质量问题,并及时反馈给应用层,进行数据问题的排查。在数据风控环节,某一个手机设备访问率呈现指数型增加,并不断刷去金币,以达到套现目的。针对此问题通过字段血缘可以快速企业业务场景,反馈给后台应用研发,达到快速对问题排查的能力。
字段级别血缘解析贯穿到 Hive SQL 语义解析之后,结合企业数仓应用的需求,如需支持 UDF 自定义函数解析,丰富 Hive 元数据信息,Hive 数据表等权限认证,支持 Hook 监听策略等需求进行改进,具体改进方式如下。
3.2.1 注册UDF
注册UDF自定义函数,便于血缘关系提取时,标记识别特殊函数,保证血缘关系解析的准确性,代码注册如下;
3.2.2 重构 SemanticAnalyzer
重构 SemanticAnalyzer,重写 SQL 解析主要逻辑。SemanticAnalyzer 类作为 Hive SQL 解析的核心工具类,用于遍历 AST 树,并将其转化为 Query Block。然而血缘关系解析时,需要元数据管理模块获取数据表的基本信息如表信息以及字段信息,以及数据表验证,表与字段信息的填充,因此为方便对血缘关系的梳理,特重构 SemanticAnalyzer 类并继承 BaseSemanticAnalyzer 类型,完善对列字段血缘关系的提取;
3.2.3 逻辑计划生成和逻辑计划优化
逻辑计划生成和逻辑计划优化,此过程主要依据操作树,推到出结果集 schema,并初始化逻辑计划和物理计划依赖的配置信息,保证血缘关系分析的基础配置信息的完整性,同时对操作树进行优化,合并操作符,减少 mapreduce job 的 stage 数量,提高血缘关系解析的执行效率;
3.2.4 元数据管理
Hive 血缘解析会涉及到 getMetaData() 方法对元数据信息的提取来完善解析,血缘解析中采用公司自研的 Hive 元数据管理模块,替代默认的元数据模块,提供更完整的元数据信息。
元数据管理模块是 Hive 架构中主要组成部分,然而 Hive 自身的元数据存在一定的局限性,如数据表的生命周期控制,数据表的权限控制等模块的缺乏,导致数据管理模块并没有发挥其核心价值,通过对企业相关的元管理模块梳理与参考,发现缺少对应血缘关系的支持,导致元数据模块相对比较薄弱,并且对元数据模块的应用需要模糊,仅仅提供元信息的保存,并没有在企业级应用中发挥重要作用。
为了能够在血缘解析中对元数据管理模块的支撑,形成元数据与血缘关系做到有机的结合。采用自主研发的元数据信息服务,不仅提供完整的 Hive Schema 信息,而且维护完整的数据表权限认证,同时,保证了SQL执行时数据的安全性。
血缘关系解析中,采用单独封装 getTableSpec 方法实现了元数据信息的切换,通过其方法获取相关 Hive 表 Schema,分区信息以及表权限信息。
Hooks 是一种事件和消息机制,可以将事件绑定在内部 Hive 的执行流程中,用于监听 Hive 的各种事件,如表创建,更新等操作,通过对 postExecHook 的配置与调用,可以 Hive 列级别血缘管理封装到LineageContext 中。
3.2.5 添加postExecHook
添加 postExecHook,执行 LineageLogger 获得 LineageContext. 在血缘关系解析中,将此步骤前置到执行逻辑计划之后,由 LineageLogger 类调用执行 SQL 逻辑计划,获取到字段级别的血缘信息封装到Lineage Context中。
3.2.6 表与字段血缘关系
读取LineageContext信息,组装数据表与字段血缘关系信息。通过对AST树进行血缘解析之后,具体的字段血缘信息存储LineageContext中,通过得LineageContext的索引对象,便可获取列字段血缘关系,通过LineageContext.index信息,将源头和目标用向量连接起来,形成列字段边信息,同时将各个边的节点连接起来,形成列的有向五环图。具体代码如下:
3.2.7 表血缘关系
结合具体应用,将表级别和字段级别的血缘关系信息进行组装得到表血缘关系。并存储在元数据管理模块中,便于更好的追溯表结构信息。血缘关系整合之后,存入数据表中,具体展开如下所示:
应用层展示 Hive SQL 血缘关系如下:
4. 血缘关系总结与展望
本文主要介绍 Hive SQL 血缘关系解析流程的整体介绍,针对固有的 SQL 解析进行优化,最后得到表级别的血缘关系信息以及字段级别的血缘关系信息,并针对此两部分血缘信息进行组装,然后得到整体的血缘信息,并在元数据管理模块中进行可视化展示。
通过对 Hive SQL 血缘关系工具开发,并成功应用到企业内部数据资产管理哦平台中。通过其在企业数据仓库中的应用,充分满足企业业务需求,给数据组同事带来很大的遍历。通过对SQL血缘关系构建,具有一下核心意义:
- 形成完成数据流向DAG图,便于数据问题溯源,便于对数据问题的排查;
- 将血缘关系融入到hive元数据管理模块,在SQL执行中,充分将元数据权限控制应用到血缘解析中,保证数据的完整性和安全性;
- 通过血缘关系,在数据质量监控方面带来极大的便利。通过企业监控平台,针对数据完整性,数据字段空值率,重复率以及不满足逻辑率等问题进行快速感知,并及时进行处理,辅助对问题的及时排查,保证企业业务正常顺利的执行。
当前企业资产管理平台支持数据组同事根据输入的业务sql,完成了相关sql的血缘关系梳理和入库,并可视化展现在元数据管理模块中,唯一不足的是目前血缘关系展现主要展示数据表之间的关系,字段级别的血缘目前只是存储在血缘关系表中。
通过血缘关系梳理,做到企业数据可溯源,挖掘企业数据价值,同时对数据质量得到很好的评估。