第 9 部分. Raw 与 Bronze 落地
Raw 和 Bronze 负责入口的可复现性。在教学示例中,raw 是由 scripts/generate_data.py 生成的 CSV 文件。在生产环境中,raw 可以是对象存储中的着陆区、Kafka 主题、CDC 表或外部源。但原则相同:不能在第一步改变数据的含义。
Raw
Raw 层回答的是「收到了什么」这个问题。它不应该:
- 重命名业务字段;
- 删除行;
- 隐藏 PII;
- 在没有证据的情况下修改值;
- 进行聚合。
如果源包含空的 revoked_at,raw 就保留空的 revoked_at。「空值表示同意有效」这个决定出现在更晚的 staging 规范中。
Bronze
Bronze 增加最小的技术规范化:文件格式、基础类型处理、加载元数据、lineage。在 dbt-duckdb 教学示例中,几乎没有独立的 bronze 层,因为 CSV 直接由 staging 模型读取。但在文中重要的是要理解这个边界:bronze 不应做出产品决策。
可验证性
Raw/Bronze 验收事实:
- 源文件存在;
- 标题符合预期;
- 合成数据的生成是可复现的;
- 空值和
null的语义在清单中已描述; - 在策略批准之前,PII 没有丢失。
为读者解析
Raw 和 Bronze 常被低估,因为那里「还没有业务」。但正是在那里决定着团队以后能否解释数据的来源。如果为了通过测试而重写了源文件,错误只是表面上消失了:同时消失的还有源发送了含糊值这一证据。在银行场景中这尤其糟糕,因为争议往往不是今天发生,而是过了一个月,当需要还原计算的时候。
Raw 层应该是无聊且诚实的。它保存输入。Bronze 可以增加最小的技术规范化:文件位置、源名称、加载日期、基础类型化、存在性检查。但 Bronze 也不应该解决属于产品的问题。如果空的 revoked_at 表示同意有效,这应该记录在规范和 staging 逻辑中,而不是隐藏在手动修改 CSV 中。
读者应该区分数据修正和数据描述。在教学示例中诱惑很大:打开 CSV,把空字符串替换成日期,得到
绿色的 dbt build。但这条路径教会的是错误的行为。正确的路径是:记录收到的内容;描述 staging 如何处理空值;添加检查;在检查记录中写下为什么做出这个决定。
Raw/Bronze 是 SDD Data 守护未来对话的地方。当审查者问「为什么有效同意是这么计算的」,答案不应该是「文件清理后就这样了」。答案应该追溯到 raw、清单、规范、staging 和测试。这条证据链越短,对数据集市的信任就越少。
实践
在 raw 源中找一个具有空值二义性语义的字段。记录它应该在哪里保存为 raw 事实、在哪里类型化、在哪里转换为业务规则。
Qwen 查询
检查 book3/examples/bank-lakehouse/raw 中的 raw 源。
将标题与领域地图中预期的源进行比较。
列出源事实和待解决问题清单。
不要修改 dbt 模型。
最小产出
本章之后:
- raw 文件可以通过命令生成;
- 教学示例至少包含两个源的清单备注,而
其余源作为练习来处理;
- 有争议的值标记为待解决问题;
- 没人把 raw 清理与业务建模混为一谈。
典型错误
修改 raw 数据以让「dbt build 通过」。如果 dbt build 因空日期而失败,应修复 staging 契约或类型处理,而不是从 raw 中抹去源信号。
自检问题
- 为什么 raw 不应删除 PII?
- 应该在哪里决定空的
revoked_at表示有效同意? - raw/bronze 层有哪些验收事实?