2、数据血缘基础回顾
聊 Schema 变更之前,我觉得有必要先把数据血缘这玩意儿掰扯清楚。很多同学一上来就谈「血缘分析」「影响分析」,但真问起血缘到底存成啥样、粒度怎么分,反而含糊了。我见过不少项目,血缘工具上了半年,最后查个字段来源还得翻半天文档——说白了,就是基础没打牢。
这一节,咱们把数据血缘的三个核心问题过一遍:它是什么、粒度怎么分、存哪最合适。
2.1 数据血缘的定义
数据血缘,英文叫 Data Lineage。听起来高大上,其实就一句话:记录数据从哪来、经过谁、变成啥、到哪去。
举个例子。你有个订单表 orders,里面有个 total_amount 字段。这个字段是从 price * quantity 算出来的,而 price 来自商品表 products,quantity 来自前端下单接口。整个过程经过了一个 ETL 任务 etl_order_summary,最后落到报表里。
数据血缘要干的,就是把这条「数据生命线」完整画出来。它不只是画个 DAG 图,更重要的是记录上下游依赖关系和转换逻辑。
核心要点:数据血缘 ≠ 数据地图。地图只告诉你「有什么」,血缘告诉你「怎么来的」。没有血缘,你根本不敢动任何一个表结构。
我个人习惯把血缘分成两类:
- 物理血缘:真实的数据流动路径,比如 SQL 里的
INSERT ... SELECT、ETL 任务的输入输出。 - 逻辑血缘:业务层面的依赖关系,比如「这个报表依赖那个指标」,不一定有直接的 SQL 映射。
做治理的时候,物理血缘是基础,逻辑血缘是上层应用。我建议先从物理血缘抓起,否则后面全是空中楼阁。
2.2 数据血缘的粒度
粒度这个词,说白了就是「细到什么程度」。我遇到过不少团队,一上来就想做字段级血缘,结果发现连表级依赖都没理清楚。你想想看,连哪个表依赖哪个表都不知道,怎么可能精确到字段?
常见的血缘粒度分三级,我整理了一张表:
| 粒度 | 描述 | 典型场景 | 实现难度 |
|---|---|---|---|
| 字段级 | 精确到每个字段的上下游映射 | 字段溯源、影响分析、数据质量根因 | 高 |
| 表级 | 记录表与表之间的依赖关系 | ETL 调度依赖、数据链路梳理 | 中 |
| 任务级 | 记录任务(Job/ETL)之间的上下游 | 任务调度、运维排障 | 低 |
字段级血缘
这是最细的粒度,也是最有价值的。比如你改了 orders.total_amount 的计算逻辑,字段级血缘能告诉你:哪些下游报表、哪些数据产品会受影响。我曾经在一个金融项目中,就因为字段级血缘没做全,改了一个字段导致三个风控模型跑出来的结果全错了——嗯,那次教训挺深刻的。
字段级血缘的难点在于:SQL 解析要足够准,尤其是遇到 CASE WHEN、子查询、窗口函数这些复杂语法。很多工具解析到一半就放弃了,直接标个「未知来源」。
表级血缘
表级血缘相对好做。你只需要知道 table_a 的数据流向了 table_b,至于具体是哪个字段,暂时不管。大部分数据仓库的调度系统都能自动生成表级依赖。
我个人的经验是:表级血缘是底线。如果连表级血缘都没有,那数据治理基本是空谈。至少你得知道,删了一张表,会炸掉多少个下游任务。
任务级血缘
任务级血缘最粗,但最实用。它关注的是任务之间的执行顺序和依赖关系。比如 job_a 跑完才能跑 job_b,job_b 失败了 job_c 就得重跑。
任务级血缘通常由调度系统(比如 Airflow、DolphinScheduler)自动维护。它不关心数据内容,只关心执行顺序。做运维排障的时候,任务级血缘是救命稻草。
我的建议:不要一上来就追求字段级。先搞定表级和任务级,跑通了再逐步细化到字段。步子迈太大,容易扯着蛋。
2.3 数据血缘的存储方式
血缘数据存哪,这是个老生常谈的问题。我见过用 Excel 存的(别笑,真有),也见过用 Neo4j 搭全套的。选型没有银弹,关键看你的场景和规模。
目前主流的存储方式有三种:
- 图数据库:比如 Neo4j、JanusGraph。适合复杂关系查询,比如「从字段 A 出发,所有受影响的下游节点」。
- 关系型数据库:比如 MySQL、PostgreSQL。适合结构化存储,查询灵活,但多层关联查询性能堪忧。
- 元数据存储:比如 Atlas、DataHub、Marquez。专门为元数据设计,内置血缘模型,开箱即用。
我画了一张对比图,帮你快速理解:
图数据库
图数据库天生适合血缘场景。因为血缘本身就是一张图——节点是表、字段、任务,边是依赖关系。用 Neo4j 查「从字段 A 出发,所有受影响的下游节点」,一条 Cypher 语句就搞定,性能还贼好。
但图数据库也有坑。我记得有个项目,团队把全量血缘都塞进 Neo4j,结果节点数到了 10 万级,写入性能直线下降。后来加了分片和索引才稳住。所以我的建议是:图数据库适合查,不适合写。写入要批量,别一条一条插。
关系型数据库
关系型数据库存血缘,最常见的方式是建三张表:table_lineage、field_lineage、job_lineage。结构清晰,查询灵活,但一旦涉及多层关联(比如查 5 层以上的上下游),SQL 写起来想哭。
举个例子,查一个字段的完整链路,可能要 JOIN 七八次,性能直接崩。所以关系型数据库适合表级和任务级,字段级慎用。
元数据存储
这是目前最主流的方式。像 Apache Atlas、DataHub、Marquez 这些工具,内置了血缘模型,你只需要把元数据喂进去,它自动帮你建图、做查询、展示血缘链路。
我比较推荐 DataHub,它的血缘模型设计得很干净,支持字段级,而且有现成的 UI 可以看血缘图。Atlas 也不错,但部署和维护成本高一些。Marquez 轻量,适合小团队。
避坑提醒:我曾经见过一个团队,用 MySQL 存字段级血缘,结果每次查链路都要跑 30 秒,最后不得不迁移到 Neo4j。选型的时候,一定先评估你的数据规模和查询模式。别等上线了才发现性能扛不住。
小结
这一节咱们把数据血缘的基础过了一遍。定义上,它记录数据的全生命周期;粒度上,字段级最细也最难,表级和任务级是底线;存储上,图数据库、关系型数据库、元数据平台各有优劣,选型要结合场景。
这些基础打好了,后面聊 Schema 变更对血缘的冲击,你才能理解为什么一个小小的字段改名,能引发一场「数据海啸」。