01学完你能做到
- 区分来源记录、上游溯源、下游影响分析和表级、列级血缘。
- 为一次数据处理记录输入、输出、代码、口径和版本。
- 说清 W3C PROV 与 OpenLineage 在数据治理中的作用。
02这课解决什么问题
当一个汇总数字与其他来源不一致,怎样解释它来自哪份输入、使用哪版代码和口径;当上游数据更正时,怎样快速找到受影响的表和接口?
03核心概念
来源(provenance)是数据的出生记录:谁、何时、通过什么过程、用哪些输入产生了它。W3C PROV 把核心对象抽象为实体(Entity)、活动(Activity)和代理(Agent)。
血缘(lineage)把这些记录连成数据家谱。向上追溯回答“这个数从哪来”,向下追溯用于影响分析。表级血缘只能说“日 K 来自 Tick”,列级血缘还能说到“close 来自 price 字段,并取当天时间最晚的一笔”。
版本同样重要:输入文件哈希、表快照 ID、代码提交号、配置版本和规则版本,都能帮助区分“数据变了”还是“代码变了”。
OpenLineage 是记录数据作业运行元数据的开放标准。一次运行通常关联 Run、Job、输入 Dataset 和输出 Dataset,并可用 facet 扩展记录 schema、版本、列级血缘和质量指标。真实系统应优先使用已有集成,不要依赖手写图长期维护。
04一个最小记录
import hashlib, uuid
from datetime import datetime, timezone
def file_version(path):
return hashlib.sha256(open(path, "rb").read()).hexdigest()[:16]
run = {
"run_id": str(uuid.uuid4()),
"job": "daily.market_turnover",
"started_at": datetime.now(timezone.utc).isoformat(),
"input": {"name": "daily_bars", "version": file_version("bars.csv")},
"code_version": "git-commit-or-script-hash",
"rules_version": "quality-rules-v3",
"output": {"name": "market_turnover", "version": "computed-after-run"},
"column_lineage": {
"turnover_total": "sum(input.turnover) grouped by market"
},
}生产环境还要记录运行状态(成功、失败或中止)、行数、时间范围、参数、数据质量结果和修正原因。血缘记录应由作业自动产生,并可被查询。
05在行情链路中的位置
原始行情 → 日 K → 复权日 K → 市场汇总 → API / 工具
└──────── 每次作业运行都记录输入、输出、版本和口径 ────────┘血缘不是数据流本身,而是伴随数据流产生的元数据。它既服务排障,也服务复现、修数和用户解释。
06常见误区
- 只画表级血缘,无法回答具体字段是怎么算出来的。
- 只记表名,不记输入版本、代码版本和口径。
- 靠人手维护一张静态图,作业一多就过时。
- 直接覆盖修正后的历史数据,不保留旧版本或变更原因。
- 把血缘只当合规材料,忽略它对排障和用户信任的价值。
07延伸阅读
08一分钟讲给别人
试着用自己的话讲一遍数据血缘就是数据的家谱。往上查,知道一个数来自哪些原始数据、经过什么计算;往下查,知道一份错误会影响哪些表和接口。最小实践不是画一张漂亮的图,而是每次作业自动记录 run ID、输入版本、代码版本、输出版本和关键列的计算方式。
5 道自测
先在心里答一遍,再展开对照。能说清理由,比答对数字更重要。
01W3C PROV 的三类核心对象是什么?
02溯源和影响分析分别回答什么问题?
03为什么列级血缘比表级血缘更适合排查口径问题?
04两次输出不同,优先比较哪些版本?
05OpenLineage 主要记录什么?
已看 0/5 题
练动手练习
任务:给一个“按市场汇总成交额”的作业加运行记录。第一次只修改代码,第二次只修改输入文件,比较两次的输入版本、代码版本、输出版本和 run ID,判断差异来源。
完成这一课
读完讲义、看完自测答案,这一课就算学完了。
- 读完讲义
- 看完全部自测
本课为投资者教育内容,案例数字均为示意,不构成任何投资建议,也不承诺收益。规则和费率会变,实际操作前请以交易所、监管机构和产品的最新公告为准。