第 11 部分. 数据验证:validation.md
在 SDD 中,验证不是「数据正确」这句话。它是一组事实。在数据项目中,事实必须关联规范、SQL 和证据。如果某个事实无法通过命令、SQL 查询或评审员的手动步骤来执行,那么它尚未就绪。
验证事实示例
### F1 — Customer 360 grain
- 命令: `dbt test --profiles-dir . --select mart_customer_360`
- 期望: `customer_id` unique 且 not_null。
- 状态: 已接受。
### F2 — PII 未进入 mart
- 命令: `dbt test --profiles-dir . --select assert_customer_360_no_direct_pii`
- 期望: 测试返回 0 行。
- 状态: 已接受。
自动事实与手动事实
自动事实通过命令运行。手动事实需要阅读变更或业务确认。两种类型都是必需的。dbt 并不知道「活跃客户」的定义是否正确,除非这一点已写入规范。
一个好的手动事实:
评审员确认,添加 `product_code` 会改变 grain,因此不在本阶段范围内。
一个不好的手动事实:
看起来没问题。
validation 应存放在哪里
在教学示例中,验证笔记位于 specs/validation/。这不一定是唯一的位置,但规则是:validation.md 必须是可版本化的,并且在 /clear 之后仍可读。如果某个事实只存在于聊天中,它就不能作为发布证据。
Qwen 查询
为 mart_customer_360 创建 validation.md 草稿。
使用 specs/models/mart_customer_360.md、ODCS、ODPS 和 models/schema.yml。
不要修改 dbt 模型。
最小输出
一个 mart 的最小 validation.md 应包含:
- 一条关于 grain 的事实;
- 一条关于 PII 的事实;
- 一条关于合约必填字段的事实;
- 一条关于 lineage 或输入模型列表的事实;
- 一条手动事实:未经批准,变更不会修改合约字段。
如果事实无法验证,请将其重写为命令、SQL 查询、dbt 测试或评审员步骤。
读者解读
validation.md 是教材刻意变得严谨的地方。只要一个事实没有命令、SQL 查询或评审员的手动步骤,它就只是一个愿望。「数据正确」这句话保护不了什么:智能体可能把没有执行错误视为正确,分析师可能把没有空值视为正确,产品负责人可能把保留 grain 视为正确。验证事实消除了这种歧义。
并非所有事实都需要自动化。在数据领域,有些决策需要阅读变更并理解合约。例如,dbt 可以证明 customer_id 是唯一的,但它无法决定在 Customer 360 中加入 product_code 是否可接受。这样的事实最好保留为手动的,并明确指定评审员。手动不等于弱;只有当未指明阅读什么以及应得出什么结论时,它才会变弱。
一个好的验证笔记会关联多个层级:模型规范、ODCS、models/schema.yml、singular 测试和评审员报告。如果其中某个层级发生变更,validation.md 应指明需要重新审视哪些事实。这让数据变更更像一个工程过程,而不是一组零散的 SQL 补丁。
读者应该习惯于在编写 SQL 之前先写 validation.md。第一次这样做会让人不习惯。之后,验证事实会开始提供帮助:它们限制了解决方案的规模,提示需要哪些测试,并为评审员提供现成的评分标准。如果 validation.md 在 SQL 之后才写,这个文件通常会变成对已完成工作的辩解。
练习
选择一个像「检查数据质量」这样的薄弱项,并将其重写为三种形式:dbt 命令、SQL/singular 测试和评审员的手动事实。
常见错误
写「检查数据质量」。这不是事实。事实应该是这样的: 「customer_id 在 mart_customer_360 中唯一,命令 dbt test --select mart_customer_360 返回退出码 0」。
自检问题
- 验证事实与愿望有何区别?
- 哪些事实无法完全自动化?
- 为什么评审员应该在变更前阅读 validation.md?