阅读材料: 第12部分. 数据契约:ODCS 和 dbt 契约检查

模块「第12部分. 数据契约:ODCS 和 dbt 契约检查」中第 1 / 5 节课
您正在未登录状态下查看课程。 请登录,以保存进度并参加测试。

第 12 部分. 数据契约:ODCS 与 dbt 契约检查

数据契约的存在是为了让下游消费者看到产品的承诺,而不仅仅是当前的实现。在 SDD Data 中,契约不是装饰性的 YAML。它是产品承诺与 SQL 之间可被验证的一层。

契约的两个层面

ODCS 负责数据产品的技术契约:schema、质量、SLA 以及破坏性变更。dbt 模型契约负责具体 dbt 模型的形式。在教学示例中,我们使用 models/schema.yml、内置的 dbt 测试以及 singular 测试作为最小的契约检查;contract.enforced: true 未启用,以免在第一次教学过程中混用特定适配器的限制。在生产环境中,可以在适配器和物化方式支持的地方启用它。

契约漂移

契约漂移发生在模型发生变更而契约未随之变更时。例如,mart_customer_360 增加了新列 product_code,但 grain 仍被描述为「每个 customer_id 一行」。这比语法错误更危险:dbt 可能会通过,但消费者却获得了不同的含义。

漂移有三种类型:

  • schema 漂移:字段被添加/删除/重命名;
  • 语义漂移:字段保留,但其含义发生了变化;
  • 流程漂移:validation.md 或评审者报告未反映该变更。

契约与测试的关联

契约必须由证据覆盖。如果 ODCS 声明 risk_event_count_7d 是必填项,那么就应该至少有一个测试或人工评审事实来证明其存在以及 not_null 行为。否则契约仍然只是没有证据的承诺。

Qwen 查询

比较 specs/customer_360_contract.odcs.yaml、
specs/models/mart_customer_360.md、models/schema.yml 和
models/marts/mart_customer_360.sql。
找出契约漂移和测试覆盖的缺口。不要修改文件。

最小输出

编写一份关于契约影响的说明:

变更字段:无
破坏性变更:无
对 PII 的影响:mart 中未直接暴露 PII
对 SLA 的影响:无
检查覆盖:customer_id 的 unique/not_null、必填字段、禁用的 PII 列表
需要确认:无

对于未来的 PR,此段应作为变更说明的一部分。

给读者的解读

数据契约的存在不是为了美化 YAML。它是为了让消费者能够信赖数据表的形态和含义,而不必每次都去阅读 SQL。在常规开发中,公共 API 不能被悄无声息地改动;在数据领域情况相同,只是 API 通常看起来像一张表。列、grain、freshness 以及 PII 策略,都是接口的一部分。

ODCS、dbt 契约检查以及 schema 测试覆盖了不同的层面。ODCS 描述产品及其技术承诺。schema.yml 和测试确认了形式的一部分。Singular 测试捕获那些不适用于标准检查的规则。没有任何一层可以替代其他层。如果只保留 dbt 测试,可能会得到一个绿灯但语义错误的模型。如果只保留 ODCS,可能会得到一个漂亮的契约却缺乏证据。

契约漂移特别令人讨厌的是,它通常看起来像是有用的改进。增加了一列。扩展了明细。为了「更清晰」重命名了一个指标。每一步单独看都很小,但下游消费者可能得到不同的行集或不同的业务指标。因此,即使变更看起来是安全的,也必须描述对契约的影响。

本章的关键是学会像评审者一样阅读变更。问题不是「SQL 是否变得更好」,而是「承诺是否保持不变」。如果承诺发生了变化,就需要人工明确确认。如果承诺没有发生变化,这也必须得到证明:哪些字段保持不变、哪个 grain 保持不变、哪些 PII 未被暴露、哪些测试通过。

实践

比较 customer_360_contract.odcs.yamlmodels/schema.yml。列出必填字段,并指出它们由哪些 dbt 测试、singular 测试或人工事实所覆盖。

典型错误

认为增加一列总是安全的。即使是 nullable 列,如果它看起来像是一个新的业务指标,或者改变了 grain,也可能会改变消费者的预期。

检查问题

  1. 为什么 dbt 测试不能替代 ODCS?
  2. 什么算作破坏性变更?
  3. Qwen Code 在出现漂移时应该如何表现?
我的笔记
0 / 10000

笔记保存在当前浏览器中。在其他设备上将不会显示。

课程菜单

课程

SDD Data. 使用 Qwen Code 和 dbt 构建银行数据平台
进度 0 / 110