老周刚调到水利局时,领导交给他一个任务:三天之内画出一张全城水系图。老周一开始以为要去测量每座水库有多大、每个池塘有多深,忙了两天才发现,真正有价值的根本不是哪个水池的容量,而是“水从哪里来、流经过哪些沟渠、最终供给哪些农田”——这份水与水的连接关系,才是水系图。后来老周靠着这张图,解决了防汛调度、污染溯源、农田灌溉一大堆难题。 数据世界也是这样。平台里有订单表、清洗任务、宽表、报表看板,数据从埋点日志诞生,经过一道道加工计算,最终成为决策依据。可一旦报表数字对不上、模型效果突然变差,我们最想追问的是:这份数据的“水”到底从哪个源头来?中间经过了哪些加工?如果我动它一下,下游会有多少“农田”遭殃?数据血缘(Data Lineage) 干的就是这件事——把数据从产生、加工、流转到消费的完整链路记录成一张可查询、可分析的“数据水系图”。 本文将以老周治水的故事串起整个知识体系:从血缘的定义与图谱,到自动发现、可视化、影响分析与溯源,再到 MLOps 中的实际落地,让你像水利工程师熟悉河道一样,看穿数据流动的全貌。

岗位关联

学会数据血缘,你就掌握了数据平台的“水系图”绘制能力,无论是数据治理、故障排查还是模型上线评估,都能快人一步定位问题,是 MLOps 工程落地的核心技能。

目录
  1. 可视化演示
  2. 血缘是什么——数据世界的“水系图”
  3. 血缘图谱构建——如何画这张水系图
  4. 血缘自动发现——不再人工画图
  5. 血缘可视化——把水系图变成交互地图
  6. 影响分析——下游江水的涟漪效应
  7. 数据溯源——顺着河流找回源头
  8. 应用场景——水系图的三大用途
  9. 落地挑战——治水路并非一帆风顺
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示数据血缘DAG图谱构建、上游变更影响分析传播、以及AI特征血缘从原始数据到模型的完整链路。

本节配有交互动效(进入视口后自动加载,约 3KB)。

数据血缘DAG图谱 数据从源头经ETL加工流向消费端,形成有向无环图 Source→ETL→Sink 血缘图谱记录数据全生命周期流转关系

血缘是什么——数据世界的“水系图”

老周刚画水系图时,满脑子都是“水库容量”“水深数据”,直到老师傅点醒他:水系图最重要的,是所有湖泊、沟渠、农田之间“连不连、往哪流”。把连接关系画清楚,城市调水的决策才有依据。数据血缘干的事也一样——它关心的不是某张表里存了多少行数据,而是这张表和另一张表之间“有没有数据流动、怎么流动”。

数据血缘(Data Lineage)描述数据从产生、加工、流转到消费的全链路关系。一个典型的血缘事实是:“订单明细表的 amount 字段,来自支付事件日志,经过清洗任务过滤后,聚合进宽表的销售额。” 血缘三要素缺一不可:上游谁来、下游谁去、中间经过什么转换。它和价值有三个关键词:信,给数据消费者提供来源证据,建立信任;断,改动之前判断下游受多大影响;判,出问题之后顺藤摸瓜判定根因。

数学上,一张血缘图可以简洁地表示为:

老周最终明白,水系图的价值不在于“画水库”,而在于“画河连着河”。数据血缘同样如此:它不是一份表清单,而是一张关系网,只有把关系织出来,后续的治理与排查才有地图可用。

G=(V,E)G = (V, E)
一张血缘图谱 G,就是由节点集合 V 和边集合 E 组成的“水系图”:节点是数据实体,边是流转关系。
  1. V(节点集合)血缘图中的一个个“水池”,代表数据表、字段、文件等实体。
    V={表、视图、字段、文件}V = \{\text{表、视图、字段、文件}\}
  2. E(边集合)连接水池的“河道”,代表数据从一个实体流向另一个实体。
    E={(生产者,消费者)}E = \{(\text{生产者}, \text{消费者})\}
  3. G(整个图谱)把全部节点和边组合在一起,就能回答“数据的水系全貌”。
    G=(V,E)G = (V, E)

血缘图谱构建——如何画这张水系图

老周画图时,光画两条河是不够的。他还要标出河道的粗细代表流量、闸门的位置代表泵站、哪段是饮用河道哪段是泄洪河道。这些“图例”让水系图真正可用。数据血缘图谱也一样,必须定义清楚节点、边、属性三类元素。

节点是数据实体:一张表、一个字段、一个模型特征。边是数据流向:一条血缘边表示上游的数据经过某种方式到达下游。为了让边可解释,还要挂上元数据属性——操作类型(读取、写入、复制)、任务 ID、调度时间、转换逻辑摘要。这样一条边就不再只是“有关联”,而是“某时某分,某个任务,把 A 过滤后写成了 B”。

血缘还分三个粒度:架构级只画系统之间的流转,比如消息队列 → 数据仓库 → 报表平台;表级细化到表与表,比如订单表 → 宽表 → 看板;字段级最精细,能追溯到“amount 字段经过 SUM 变成 total_amount”。粒度越细,定位问题的能力越强,构建成本也越高。血缘边可以用三元组表达:

老周在图旁标注“雨季水深三米、大坝建于2008年”,数据工程师也在血缘边旁标注“过滤已支付订单、调度每天凌晨两点”。这份属性越完整,血缘图越能回答“为什么”。

e=(u,v,attr)e = (u, v, \text{attr})
一条血缘边 e,由上游节点 u、下游节点 v、边的属性 attr 三部分构成。
  1. u(上游节点)数据的源头,像河道上游的水源地。
    u∈V, 例如订单表u \in V,\ \text{例如订单表}
  2. v(下游节点)数据的去向,像河道下游的农田。
    v∈V, 例如聚合宽表v \in V,\ \text{例如聚合宽表}
  3. attr(血缘属性)边的“运行参数”,回答什么时候、用什么操作、经过什么任务。
    attr=(操作类型,时间,任务ID,转换逻辑)\text{attr} = (\text{操作类型}, \text{时间}, \text{任务ID}, \text{转换逻辑})

血缘自动发现——不再人工画图

老周手绘水系图累到颈椎病复发,后来买了无人机航拍加水质传感器,几十条河道一天摸完。数据血缘要是靠人工记录,表一多准会“画崩溃”。自动发现就是给平台装上无人机:让系统自动读取数据流经的痕迹,拼出血缘图。

自动发现有三条主流路径。SQL 解析是最核心的手段:数据平台里绝大多数加工逻辑都以 SQL 形式存在,系统把 SQL 解析成抽象语法树(AST),从 FROM / JOIN 子句里提取输入表,从 INSERT INTO / CREATE TABLE AS 里提取输出表,一条血缘边就浮现了。日志采集补充“谁在几点跑了哪个任务、读写了哪些分区”。元数据把物理路径映射回逻辑表名,把散落的线索串成完整链条。从一条 SQL 提取血缘关系可写成:

无人机航拍也有盲区——藏在涵洞里的暗渠拍不到。SQL 解析同样会漏掉存储过程、动态 SQL 和 Python 脚本里的隐式读写。所以自动发现之后,还需要人工校准关键路径,两条腿走路。

Lineage(Q)⊇{(src,dst)∣src∈FROM(Q), dst∈WRITE(Q)}\text{Lineage}(Q) \supseteq \{ (\text{src}, \text{dst}) \mid \text{src} \in \text{FROM}(Q),\ \text{dst} \in \text{WRITE}(Q) \}
给定一条 SQL 语句 Q,血缘识别至少能发现:Q 读了哪些表(src),写了哪些表(dst),由此构成表级血缘。
  1. FROM(Q)从 SQL 的 FROM 和 JOIN 子句识别出的输入表集合,即“读了谁”。
    FROM(Q)={订单表,用户表}\text{FROM}(Q) = \{\text{订单表}, \text{用户表}\}
  2. WRITE(Q)从 INSERT INTO 等写语句识别的输出表集合,即“写了谁”。
    WRITE(Q)={清洗表}\text{WRITE}(Q) = \{\text{清洗表}\}
  3. (src, dst)一条从输入到输出的血缘边。
    (订单表,清洗表)(\text{订单表}, \text{清洗表})
  4. ⊇(超集符号)真实血缘可能比规则识别的更多,复杂嵌套 SQL 不一定全部捕获。
    已识别血缘⊆真实血缘\text{已识别血缘} \subseteq \text{真实血缘}

血缘可视化——把水系图变成交互地图

老周交的第一版水系图是张死板的 PDF,领导看半天找不到自己的辖区。后来换成 GIS 地图,图“活”了:滚轮放大能看某条支流的细节,点一下水闸能显示它控制的农田,勾选“只看饮用河道”其他河道就变暗。可视化的力量不是画得漂亮,而是让人更容易看透复杂关系。

血缘可视化面对的现实是“图太大、人眼装不下”:一个中型平台几百张表、几万条边,全部平铺是一团乱麻。所以血缘浏览器普遍采用三个手段:分层展示——概览层只显示表级血缘,下钻后才显示字段级;过滤聚焦——按时间范围、数据域、责任人把不关心的链路收起;交互探索——点击节点查看一跳上下游,再沿边逐级展开。可视化的本质是对图谱做过滤投影:

其中:

老周后来学会了按“汛期/非汛期”过滤水系图。数据工程师也按“最近变更的管道”过滤血缘图,让真正需要关注的问题浮出水面。

G′=(V′,E′)G' = (V', E')
V′={v∈V∣cond(v)},E′=E∩(V′×V′)V' = \{v \in V \mid \text{cond}(v)\}, \quad E' = E \cap (V' \times V')
血缘可视化中,一次“聚焦”操作就是保留满足条件的节点 V',同时只保留两个端点都在 V' 中的边 E'。
  1. cond(v)过滤条件,例如“只保留销售域的表”或“只保留最近 7 天更新的表”。
    cond(v): v 属于销售域\text{cond}(v):\ v\ \text{属于销售域}
  2. V'(过滤后节点)满足条件的节点被保留下来。
    V′={销售订单,销售宽表,销售看板}V' = \{\text{销售订单}, \text{销售宽表}, \text{销售看板}\}
  3. E'(过滤后边)只要有一个端点被过滤掉,这条边就不显示。
    E′=E∩(V′×V′)E' = E \cap (V' \times V')

影响分析——下游江水的涟漪效应

市里要在上游建水电站,老周的活来了:大坝合龙后水位变动,下游哪些农田会被淹、哪些水厂要换水源、哪些湿地生态会受影响?他不能只看大坝下游一公里,而要沿着每条支流走到入海口。影响分析(Impact Analysis) 就是数据世界的“泄洪评估”。

影响分析从一个数据节点出发,沿血缘边向下游做可达性遍历。只要存在一条路径,路径上的所有节点都是潜在受影响的“农田”。注意,影响不只是直接下游——一级下游加工完的数据还会喂给二级三级下游,报表异常往往发生在链路深处。工程实现上通常用 BFS 或 DFS 遍历,同时用 visited 集合防止环路导致死循环。给边加权后,还能算出“受影响表数量”“涉及核心报表深度”等风险指标,输出高、中、低风险清单。影响集的定义:

老周提交泄洪报告时,会把影响分成“直接淹没区、水位波及区、生态长远影响区”三档。数据工程师做变更评估时,也该把下游分成“直接任务失败、数据延迟、质量指标波动”三档,按风险级别决定是否先做兼容改造。

Impact(v)={u∣∃ path v⇝u}\text{Impact}(v) = \{ u \mid \exists\ \text{path } v \rightsquigarrow u \}
Impact(v) 是从节点 v 出发,沿血缘边方向能到达的所有下游节点集合——包括直接下游和间接下游。
  1. path v ⇝ u从 v 出发沿下游方向存在一条有向路径。
    path: v→v1→v2→u\text{path}:\ v \rightarrow v_1 \rightarrow v_2 \rightarrow u
  2. ∃(存在)只要存在一条路径,u 就算受影响节点。
    ∃ path v⇝u\exists\ \text{path } v \rightsquigarrow u
  3. Impact(v)v 的全部下游影响集合。
    Impact(清洗表)={宽表,看板,特征表}\text{Impact}(\text{清洗表}) = \{\text{宽表}, \text{看板}, \text{特征表}\}

数据溯源——顺着河流找回源头

某天郊区农户反映水稻发黄,老周带着检测仪沿灌溉渠逆流而上,跨过三条支流、两个水闸,最后在一家化工厂排口抓到污染源。他感慨:如果只查最近一截水渠,永远找不到凶手。数据溯源(Data Provenance) 要找回的正是“最终源头”。

数据溯源与影响分析方向相反:影响分析从改动点看下游,溯源从问题产物查上游。报表数字对不上、模型评分异常、字段出现 NULL,借助溯源可以一层层往上追,直到原始日志表。工程实现上是“反向 BFS”——血缘系统在存边时,不仅存下游邻接表,还同步存一份上游邻接表(“谁生了我”)。查询时从目标节点出发,逆着水流方向遍历,再把每条边的转换属性串起来,还原完整加工链。溯源集定义:

老周查完污染源后开了一份“水质溯源报告”。数据工程师修完数据也应把“根因备忘”挂到血缘分之上:下次出现同样症状,直接翻图谱就能定位,不用再跑断腿。

Provenance(x)={s∣∃ path s⇝x}\text{Provenance}(x) = \{ s \mid \exists\ \text{path } s \rightsquigarrow x \}
Provenance(x) 是所有能通过血缘路径到达 x 的上游节点集合——即 x 的完整数据来源。
  1. s(候选源头)图中任何可能的上游节点。
    s∈V, 例如埋点日志s \in V,\ \text{例如埋点日志}
  2. path s ⇝ x从 s 出发沿下游方向能走到 x。
    path: 埋点日志→ODS表→x\text{path}:\ \text{埋点日志} \rightarrow \text{ODS表} \rightarrow x
  3. Provenance(x)x 的所有上游来源的并集。
    Provenance(销售看板)={订单库,用户表,区域维表}\text{Provenance}(\text{销售看板}) = \{\text{订单库}, \text{用户表}, \text{区域维表}\}

应用场景——水系图的三大用途

水系图不是挂在墙上好看的,老周靠它干了三件大事:给农田规划灌溉、给城防做洪水预警、给环保局找排口。数据血缘也有三个主舞台:数据治理、MLOps、数据资产。

在数据治理中,报表指标对不上时,血缘让“指标口径由谁加工、来自哪些源表”一目了然;删除或脱敏敏感数据前,影响分析能列出所有下游副本,满足合规要求。在 MLOps 中,模型训练特征表的口径一变,模型精度就可能断崖下跌;血缘让特征像水流一样被追踪——哪个上游改动导致特征分布偏移,几分钟就能定位;上线新特征前也能评估它会影响哪些模型和看板。在数据资产中,血缘让每张表自带“来源与去向”,消费者找表时能顺着血缘判断它是否新鲜、可信、是否涉及敏感字段。有一类常见需求是评估“指标 M 到底依赖哪些源头字段”,公式如下:

老周的水系图让城市规划更科学。数据平台的这张“数据水系图”则让数据治理、模型迭代、资产盘点都有据可依,不再靠“某个老师傅的大脑”。

Contrib(M)=⋃f∈fields(M)Provenance(f)\text{Contrib}(M) = \bigcup_{f \in \text{fields}(M)} \text{Provenance}(f)
指标 M 的完整上游来源,等于 M 涉及的每个字段各自上游来源的并集。
  1. fields(M)指标 M 用到的所有字段。
    fields(销售额)={amount,currency}\text{fields}(\text{销售额}) = \{\text{amount}, \text{currency}\}
  2. Provenance(f)每个字段的完整上游溯源结果。
    Provenance(amount)={支付流水,汇率表}\text{Provenance}(\text{amount}) = \{\text{支付流水}, \text{汇率表}\}
  3. ⋃(并集)把每个字段的来源合并,去重后得到指标的全量上游。
    Contrib(销售额)={支付流水,汇率表,渠道维表}\text{Contrib}(\text{销售额}) = \{\text{支付流水}, \text{汇率表}, \text{渠道维表}\}

落地挑战——治水路并非一帆风顺

老周的水系图理想很丰满,现实却处处卡壳:无人机航拍遇雨雾遮挡、老城区地下的管道图纸残缺、河道改道后图没跟上。数据血缘落地同样不是画完图就万事大吉。

第一个挑战是采集完整性。生产环境大量存在存储过程、动态 SQL、Python 脚本和手工导表,SQL 解析器难以覆盖全部。血缘图只能覆盖“已见河道”,还有许多暗流未被记录。第二个挑战是语义漂移:上游表把字段含义从“人民币”改成“美元”,血缘边还在,语义已经变了;图谱需要记录版本与口径变更,防止“数字是新的,含义是旧的”。第三个挑战是性能规模:全量血缘图动辄百万级节点,每次影响分析做全图遍历成本极高,需要分层索引、按日期切片缓存。此外还有组织协作问题——血缘元数据要有人持续维护校正,必须纳入开发流程与验收规范。衡量血缘系统完整度,最直接的指标是覆盖率:

老周后来把水系图建成了“活图”:河道改造自动更新,每年组织一次全城踏勘。数据血缘也一样,它从来不是一份静态文档,而是需要持续演进、渐进完善的基础设施。

Coverage=∣E^∣∣E∣\text{Coverage} = \frac{\left|\hat{E}\right|}{|E|}
血缘覆盖率 = 已发现血缘边数 ÷ 真实血缘边总数。它度量的是这张“水系图”画全了没有。
  1. Ê(已捕获边集合)血缘系统实际发现并记录的边。
    E^={已识别的血缘关系}\hat{E} = \{\text{已识别的血缘关系}\}
  2. E(真实边集合)数据管道中真实存在的全部血缘关系。
    E={真实血缘关系}E = \{\text{真实血缘关系}\}
  3. Coverage(覆盖率)取值在 0 到 1 之间,越接近 1 越接近全貌。
    Coverage∈[0,1]\text{Coverage} \in [0,1]

AI 应用场景

数据治理:报表口径大排查

阶段:数据监测与治理

解决的问题:某公司月度经营报表的 GMV 连续两月异常偏低。传统方式靠几位工程师熬夜翻脚本、逐一对比十几张中间表,效率极低且容易漏掉链路深处的根因。引入数据血缘后,从 GMV 字段反向溯源,几分钟定位到“埋点日志的订单状态过滤条件被误改”,修复后指标立刻恢复。

具体案例:电商平台数仓团队用血缘平台将订单明细表的全链路完整还原,每条边标注负责人和数据质量规则;当规则命中异常时,自动通过血缘通知下游每个看板的负责人,把“事后人工排查”变成了“事中自动感知”。

MLOps:模型特征血缘追踪

阶段:模型训练与监控

解决的问题:风控模型的 PSI 指标突然异常,特征工程师想调整特征存储结构,却说不清会影响哪些模型和报表。血缘平台把特征表、特征加工管道、模型服务全部纳入图谱,一次影响分析直接列出所有依赖该特征的模型与离线任务,避免了“改一处、崩一片”。

具体案例:某团队把“客户活跃度特征”从每日更新改为每周更新,血缘平台自动标红依赖该特征的两个在线模型,提示可能产生特征滞后。团队据此延后上线并补做兼容测试,避免了一次模型事故。

合规审计:GDPR 删除权响应

阶段:数据合规审计

解决的问题:用户行使“被遗忘权”时,需要删除该用户在所有副本里的数据。人工排查往往漏掉离线备份和分析宽表。用血缘图谱提供反向溯源与影响分析,可以列出包含用户 ID 字段的所有下游表,生成待删除清单并留存审计日志。

具体案例:一家跨国电商收到删除请求后,借助字段级血缘在 30 分钟内生成涉及 12 张表、40 个分区的清理计划,并完整记录操作流水,用于监管审计,把合规响应从“以周计”缩短到“以分钟计”。

Python 演示

python55 行
from collections import defaultdict, deque  class LineageGraph:    def __init__(self):        self.nodes = set()        self.edges = []        self.downstream = defaultdict(list)        self.upstream = defaultdict(list)     def add_edge(self, src, dst, transform=""):        self.nodes.add(src)        self.nodes.add(dst)        self.edges.append((src, dst, transform))        self.downstream[src].append(dst)        self.upstream[dst].append(src)     def impact_downstream(self, node):        visited = set()        queue = deque([node])        while queue:            cur = queue.popleft()            for nxt in self.downstream[cur]:                if nxt not in visited:                    visited.add(nxt)                    queue.append(nxt)        return visited     def trace_upstream(self, node):        visited = set()        queue = deque([node])        while queue:            cur = queue.popleft()            for prev in self.upstream[cur]:                if prev not in visited:                    visited.add(prev)                    queue.append(prev)        return visited  def main():    g = LineageGraph()    g.add_edge("订单库", "清洗任务", "过滤已支付订单")    g.add_edge("清洗任务", "聚合宽表", "按城市日期聚合")    g.add_edge("聚合宽表", "销售看板", "SUM(amount)")    g.add_edge("用户表", "聚合宽表", "LEFT JOIN 用户维度")     print("影响分析: 清洗任务改字段会波及哪些下游")    print(sorted(g.impact_downstream("清洗任务")))    print("数据溯源: 销售看板的数据来自哪些上游")    print(sorted(g.trace_upstream("销售看板")))  if __name__ == "__main__":    main()
目的:用有向图模拟一个最小数据血缘系统,演示影响分析(下游遍历)和数据溯源(上游遍历)两个核心操作。运行后将输出“清洗任务”波及的下游表,以及“销售看板”的完整上游来源。
  1. self.downstream = defaultdict(list)正向邻接表:记录每个节点“流向谁”,相当于水系图的下游分支。
  2. self.upstream[dst].append(src)反向邻接表:记录每个节点“谁流向我”,让溯源不必每次全图扫描。
  3. g.add_edge("订单库", "清洗任务", "过滤已支付订单")声明式注册一条血缘边,第三个参数是转换说明。
  4. def impact_downstream(self, node):影响分析入口:从该节点沿下游方向出发。
  5. for nxt in self.downstream[cur]:逐条访问当前节点的下游邻居。
  6. if nxt not in visited:用 visited 集合防止环导致死循环。
  7. def trace_upstream(self, node):溯源入口:换成上游邻接表,逆流而上。
  8. print(sorted(g.impact_downstream("清洗任务")))输出影响集,验证“清洗任务”改动会影响哪些下游表。

常见误区

误区我认为血缘就是记录表结构、字段名、数据类型、负责人这些元数据的文档。只要把元数据管好了,血缘自然就有了。

正解数据字典回答“这张表里有什么”,血缘回答“这张表从哪来、到哪去”。水系图不是标出所有湖泊的面积和深度——那是水文台账;水系图画的是湖泊之间的河道关系。血缘的核心是“边”,数据字典只关注“点”。

为何常见:很多元数据工具里也展示依赖关系,初学者容易把表结构文档直接等同于血缘,忽略了“关系”这个关键维度。

误区平台就几十张表,建个 Excel 人工记录每张表的来源去向,每周更新一次,够用了。

正解表少的时候可行,但表一多、管道一改,人工记录立刻失真。真实平台每天几十个任务上线,一条 SQL 改写就可能牵出几十条新血缘。自动发现才是常态,人工核对只用于关键链路校准。

为何常见:初期规模小,人工维护的成本被低估;一旦规模上来,人工维护的滞后性和漏记很难审计。

误区我改一张表,只要下游直接引用它的任务不出错,就万事大吉了。

正解数据链路是链式的,一级下游的结果可能继续喂给二级、三级下游。影响分析必须沿血缘边递归遍历,否则会漏掉“间接影响”——报表异常往往发生在第二三级节点。就像水坝泄洪,下游五百公里处的农田一样会被淹。

为何常见:人眼一次只能处理一跳关系,直接下游最显眼,链路更长的间接消费方容易被忽略。

误区血缘系统上线必须把全平台所有表的血缘都采集全,缺一张都不行,否则没法用。

正解复杂 SQL、存储过程、手工导表永远存在,追求 100% 会让系统永远无法上线。合理路径是先把核心链路覆盖到 80%,再对高风险场景人工补录,用覆盖率指标持续优化。血缘的价值在于“能回答关键问题”,而不是“一张不落的完美地图”。

为何常见:刚接触血缘时容易把它当成“全知图”,忽略了工程落地中成本与收益的平衡。

误区血缘图画完就固定了,平时不用再管,半年看一次就行。

正解数据管道每月都在变,血缘图必须随任务调度、SQL 变更实时更新,历史版本还要留痕。过期的血缘比没有血缘更危险——它让你产生“已掌控”的错觉。水系图每年要修测,血缘图每次管道变更都要刷新。

为何常见:人们习惯把图谱当成一份文档产物,而忽略血缘本质上是运行时元数据的持续快照。

面试题

Q1. 关于数据血缘,下列描述最准确的是?

单选题 · easy

  • A.记录数据值的内存快照
  • B.描述数据流转关系的图谱← 正确答案
  • C.数据备份的历史记录
  • D.数据库的索引结构

答案:B。数据血缘描述的是“数据从哪来、到哪去”的流转关系,本质是一张有向图。数据值快照是数据本身的内容,备份记录是恢复手段,索引是查询加速结构,三者都与血缘无关。

Q2. 血缘图谱中的“边”主要表示什么?

单选题 · easy

  • A.表之间的外键约束
  • B.数据从上游节点流向下游节点← 正确答案
  • C.用户访问数据的权限
  • D.任务调度的先后时间

答案:B。血缘边的核心含义是“一份数据流向了另一份数据”,外键约束描述关联关系但不等同于数据血缘,权限和调度时间属于元数据属性,不是边的核心语义。

Q3. 从 SQL 中自动发现表级血缘时,最常关注哪些子句?

单选题 · mid

  • A.WHERE 和 GROUP BY 子句
  • B.INSERT INTO 和 SELECT FROM 子句← 正确答案
  • C.ORDER BY 和 LIMIT 子句
  • D.HAVING 和 DISTINCT 子句

答案:B。表级血缘要找“读了哪些表、写了哪些表”,SELECT FROM 提供输入表,INSERT INTO 提供输出表。WHERE、GROUP BY、ORDER BY 等描述的是行级过滤和聚合逻辑,不直接决定表级流向。

Q4. 运行影响分析时,正确的做法是?

单选题 · mid

  • A.只查询直接下游表
  • B.递归遍历所有可达下游节点← 正确答案
  • C.反向查询所有上游表
  • D.只检查当前节点自身字段

答案:B。影响分析是沿血缘边向下游递归遍历,收集所有可达节点。只看直接下游会漏掉链路深处的间接影响;反向查询上游是溯源做的事;只看自身字段无法评估传播效应。

Q5. 数据溯源与影响分析的区别是?

单选题 · mid

  • A.溯源向后查来源,影响分析向前查影响← 正确答案
  • B.两者完全相同
  • C.溯源只查字段,影响分析只查表
  • D.影响分析只涉及实时数据

答案:A。两者方向相反:溯源从产物查上游源头,影响分析从改动点查下游影响。两者都可作用于表和字段,也不限于实时数据,因此 B、C、D 都不正确。

Q6. 血缘边上的属性一般不包括?

单选题 · hard

  • A.转换逻辑与过滤条件摘要
  • B.数据产生时间与操作类型
  • C.表在集群中的物理存储位置← 正确答案
  • D.上下游节点的唯一标识

答案:C。血缘边属性描述“这条数据流如何发生”,包括转换逻辑、时间、操作类型、任务 ID、上下游标识。物理存储位置是数据实体本身的元数据,通常挂在节点属性而非边属性上。

Q7. 血缘可视化中“分层下钻”的主要作用是?

单选题 · easy

  • A.让图谱在视觉上更美观
  • B.先看总体概览再细看局部细节← 正确答案
  • C.减少数据存储空间
  • D.替代 ETL 调度功能

答案:B。分层下钻解决“图太大、人眼装不下”的问题:概览层看表级关系,下钻层看字段级细节。它不改变存储,也不替代调度,美观只是附带效果。

Q8. 数据血缘自动发现的常用手段有哪些?

多选题 · mid

  • A.解析 SQL 的抽象语法树← 正确答案
  • B.抓取调度平台的执行日志← 正确答案
  • C.读取元数据中心的表信息← 正确答案
  • D.人工为每条管道写注释

答案:ABC。自动发现依靠 SQL 解析、执行日志、元数据采集三驾马车,分别回答“读写谁、何时跑、物理路径是什么”。人工注释不属于自动发现手段,且无法规模化。

Q9. 数据血缘在 MLOps 中的典型价值有哪些?

多选题 · hard

  • A.定位特征工程异常的上游根因← 正确答案
  • B.评估重新训练模型时的影响范围← 正确答案
  • C.自动生成模型训练代码
  • D.满足模型上线前的合规审计← 正确答案

答案:ABD。血缘帮算法工程师从特征反查源头定位异常,也能在模型变更前评估下游影响,还能为审计提供特征来源证据。血缘本身不生成训练代码,那是代码生成工具的任务。

Q10. 某张表经过多条路径到达下游报表,删除该表前最稳妥的评估方式是?

单选题 · extreme

  • A.只查它的直接下游节点
  • B.忽略血缘,直接通知应用方自查
  • C.计算所有可达下游路径并逐个通知← 正确答案
  • D.只删除不评估,遇到报错再回滚

答案:C。多条路径意味着多个下游会在不同深度受影响,必须做完整可达性分析并逐个通知。只看直接下游会漏掉间接依赖;忽略血缘和出问题再回滚都是高风险做法。