4. 数据血缘解析:血缘的粒度、解析原理与构建方式
数据血缘,说白了就是数据从哪来、到哪去、中间经历了什么。很多团队做资产目录做到一半,发现字段对不上、报表数据对不齐,回头一查——血缘没打通。嗯,这块确实是硬骨头,但也是数据治理的核心能力。
我个人习惯把血缘分成三个维度来讲:粒度、解析原理、构建方式。咱们一个一个拆开看。
4.1 血缘的粒度:表级 vs 字段级
先问个问题:你需要的血缘是「知道这张表从哪来」就够了,还是必须精确到「这个字段是从哪个表的哪个字段计算出来的」?
这就是表级血缘和字段级血缘的区别。
| 维度 | 表级血缘 | 字段级血缘 |
|---|---|---|
| 粒度 | 表与表之间的依赖关系 | 字段到字段的映射与转换 |
| 典型场景 | 数据链路梳理、影响分析 | 问题溯源、合规审计、数据质量 |
| 解析难度 | 低,SQL 中提取表名即可 | 高,需要解析表达式、函数、子查询 |
| 存储开销 | 小 | 大,字段级关系可能呈指数增长 |
| 维护成本 | 低 | 高,SQL 变更后需重新解析 |
我的建议:起步阶段先做表级血缘,快速建立全局数据地图。等业务对数据质量要求上来了,再逐步下钻到字段级。我在项目中见过一上来就搞字段级血缘的团队,结果半年过去了,连表级链路都没跑通。
举个例子,一条简单的 SQL:
CREATE TABLE dws_sales_summary AS
SELECT
a.order_id,
a.amount * b.discount_rate AS final_amount,
c.user_name
FROM ods_orders a
JOIN dim_discount b ON a.discount_id = b.id
JOIN dim_user c ON a.user_id = c.id;
表级血缘只需要记录:dws_sales_summary 依赖 ods_orders、dim_discount、dim_user。
字段级血缘就要精确到:final_amount 来自 a.amount 和 b.discount_rate 的乘积,user_name 直接来自 c.user_name。
注意:字段级血缘中,如果遇到 CASE WHEN、聚合函数、窗口函数,解析复杂度会急剧上升。我曾经在一个项目中遇到 200 行的嵌套 SQL,解析出来的血缘图跟蜘蛛网一样,最后不得不人工校验了一部分。
4.2 解析原理:SQL 解析 vs 日志解析
血缘怎么来的?两种主流方式:SQL 解析和日志解析。各有各的适用场景,也各有各的坑。
4.2.1 SQL 解析
这是最直接的方式。你拿到 ETL 脚本、视图定义、报表查询,用解析器把 SQL 拆成抽象语法树(AST),然后从中提取表名、字段名、表达式关系。
常用的解析工具:
- Antlr4:通用解析器生成工具,社区有现成的 SQL 语法文件
- Druid SQL Parser:阿里巴巴开源,对 MySQL、Oracle、PG 支持较好
- Calcite:Apache 项目,适合深度解析和优化
- sqlparse:Python 轻量级库,适合快速原型
解析流程大致如下:
SQL 文本 → 词法分析 → 语法分析 → AST → 遍历 AST → 提取血缘关系
经验之谈:SQL 解析最怕什么?最怕方言。MySQL 的 LIMIT、Oracle 的 CONNECT BY、Hive 的 LATERAL VIEW,每个方言都有自己的语法糖。我建议你选解析器时,先拿自己团队最常用的 100 条 SQL 做测试,看看解析成功率能到多少。
4.2.2 日志解析
有些场景你拿不到 SQL——比如用的是商业 BI 工具、或者 ETL 工具不暴露脚本。这时候就得靠日志解析了。
原理很简单:数据库或计算引擎在执行 SQL 时,会记录审计日志、执行计划、或者 Query Profile。从这些日志里,可以反推出数据的流向。
常见的日志来源:
- 数据库审计日志:记录谁在什么时间执行了什么 SQL
- Spark / Flink 执行计划:包含完整的算子链路
- Hive / Presto 的 Query Profile:记录了输入输出表、读写字节数
- Kafka Connect / CDC 日志:记录数据在 topic 之间的流转
| 对比维度 | SQL 解析 | 日志解析 |
|---|---|---|
| 数据来源 | ETL 脚本、视图定义、查询语句 | 执行日志、审计日志、Profile |
| 解析精度 | 高,可到字段级 | 中,通常只能到表级 |
| 实时性 | 离线,脚本变更后需重新解析 | 可实时,日志产生即解析 |
| 覆盖范围 | 仅限有脚本的场景 | 所有执行过的查询都能覆盖 |
| 典型工具 | Antlr4、Druid、Calcite | Flume、Logstash、自研解析器 |
我的做法:能拿到 SQL 的地方优先用 SQL 解析,精度高、可控性强。日志解析作为兜底方案,用来补全那些「黑盒」场景。两个方式配合使用,血缘覆盖率能做到 95% 以上。
4.3 手动构建 vs 自动构建
血缘怎么建?两条路:手动画、自动跑。我见过不少团队在这上面纠结很久,其实核心就一句话——自动构建是目标,手动构建是起点。
4.3.1 手动构建
说白了就是靠人。业务分析师或者数据工程师,用 Excel、Draw.io、或者资产目录平台的手动编辑功能,一条线一条线地画出血缘关系。
适用场景:
- 数据链路简单,表数量在 50 张以内
- 核心报表或监管报送,需要人工确认血缘准确性
- 自动解析覆盖不到的自定义流程(比如人工导入导出)
我曾经踩过的坑:有个客户坚持用手动构建,画了三个月,画了 2000 多张表的关系。结果业务一调整,三分之一的关系要重画。手动构建的维护成本,会随着数据规模线性增长,甚至指数增长。
4.3.2 自动构建
自动构建就是靠解析器定时扫描 SQL 脚本、调度系统、日志文件,自动生成血缘关系并更新到资产目录中。
典型的自动构建流程:
- 采集:从 Git、调度平台、数据库审计日志中拉取 SQL 和日志
- 解析:用解析器提取血缘关系
- 去重合并:多条 SQL 可能产生相同的血缘关系,需要合并
- 版本管理:记录每次变更的时间点和版本号
- 写入图谱:将血缘关系写入图数据库或关系型存储
自动构建的成熟度可以分为几个阶段:
| 阶段 | 能力 | 典型特征 |
|---|---|---|
| L1 基础 | 表级血缘自动采集 | 能识别 INSERT、CREATE AS SELECT 中的表依赖 |
| L2 进阶 | 字段级血缘自动解析 | 能解析 SELECT 列表中的字段映射和简单表达式 |
| L3 高级 | 复杂表达式与函数解析 | 能处理 CASE WHEN、窗口函数、UDF |
| L4 智能 | 增量解析与变更感知 | 只解析变更的部分,自动识别血缘断裂 |
我的建议:别追求一步到位到 L4。先做到 L1,让团队看到自动血缘的价值,再逐步升级。我带的团队用了 6 个月从 L1 走到 L3,中间踩了不少坑,但每一步都走得扎实。
4.4 知识体系总览
下面这张图把本章的核心知识点串起来了,你可以对照着梳理自己的血缘建设思路。
4.5 落地建议
最后聊点实际的。如果你现在要从零开始构建数据血缘,我会建议你按这个顺序来:
- 先盘点:梳理现有 ETL 脚本、视图、报表查询,看看 SQL 覆盖度有多高
- 选解析器:用 100 条典型 SQL 测试解析成功率,选一个最适合你技术栈的
- 做表级血缘:快速上线,让团队看到效果,建立信心
- 补日志解析:覆盖那些拿不到 SQL 的黑盒场景
- 下钻到字段级:针对核心链路和问题频发的表,做字段级解析
- 建立变更感知:接入 CI/CD 或调度系统,SQL 变更后自动触发重新解析
记住一句话:血缘不是一次性工程,而是持续运营的能力。你不可能第一天就做到完美,但每往前走一步,数据资产的透明度就提升一分。我在多个项目中验证过这个路径,虽然慢,但稳。