未记录事实核验 · 状态:现行内容
记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。
warning 适用边界与维护说明
本文适用于已有可运行 dbt 项目的基础文档编写、文档块复用和已声明依赖分析,不是完整生产部署方案。独立 docs 目录须纳入项目文档扫描路径;模型与字段描述中的业务规则、币种、折扣口径及更新频率是示例内容,应按实际来源和模型实现确认,订单 ID 的格式与唯一性已在正文中明确限定为示例假设。CI/CD 片段仅为发布骨架,需另备连接配置、发布权限和 Pages 站点设置,并确认真实元数据的访问范围,避免内部表结构、描述或编译 SQL 被非授权读者访问。dbt 血缘及命令输出仅覆盖已声明依赖,项目外报表、任务和消费关系须另行确认。本次仅作全文结构审阅,未进行外部事实核验或命令运行验证。
dbt 文档与数据血缘 - 让数据可解释
abstract 本文核心
"这张表是什么意思?" "这个字段从哪里来的?" "我能信任这个数据吗?" 数据文档和血缘追踪是解决这三个问题的答案。 dbt 把文档和代码绑定在一起,自动生成可视化的数据目录和血缘图。
数据文档的真实价值
设想一个场景:
你接手了一个离职同事的项目,里面有几十张表。你打开数据库一看:
fct_orders
fct_orders_v2
fct_orders_new
fct_orders_final
dim_cust
dim_customer
customer_info
customer_data_cleaned
没有任何文档,不知道用哪张表,不知道字段含义,不知道哪个是最新的。
这就是为什么文档很重要——它把隐性知识变成显性知识,减少了信息不对称带来的团队摩擦。
为什么 dbt 的文档方式更好
传统文档的问题:
- 文档和代码分离,很快就过期了
- 没有人有动力维护
- 找不到文档,或者找到的是旧版本
dbt 的做法:
- 文档就在
schema.yml里,和 SQL 代码放在一起 - 每次
dbt docs generate自动生成最新的网站 - 血缘图从代码结构自动生成,不需要手动维护
在 schema.yml 中写文档
模型级别的文档
# models/marts/core/_core_models.yml
version: 2
models:
- name: fct_orders
description: |
**订单事实表**
每行代表一个客户订单,记录订单从创建到完成的完整信息。
**粒度**:订单级别(order_id 唯一)
**数据来源**:Shopify 电商平台
**更新频率**:每小时增量更新
**数据范围**:2020-01-01 至今
**注意**:该表已过滤测试订单(financial_status = 'test')
和已取消订单(status = 'cancelled')。
如需分析退款,请查询 `fct_refunds`。
字段级别的文档
columns:
- name: order_id
description: |
订单唯一标识。
来源:Shopify orders 表的 id 字段。
格式:本示例假设为正整数、自增,且在所建模的订单数据范围内唯一;实际格式与唯一性须按来源验证,跨店铺或多来源关联需确认键空间,必要时使用组合键。
- name: customer_id
description: "客户 ID,外键,关联 dim_customers.customer_id"
- name: financial_status
description: |
订单支付状态。可能的值:
- `pending`: 已创建,等待支付
- `paid`: 已支付
- `refunded`: 已全额退款
- `voided`: 已作废(未付款取消)
- name: total_price_cents
description: "订单总金额,单位:分(避免浮点精度问题)。例:29999 表示 299.99 元"
- name: is_first_order
description: "布尔值,标识该订单是否为该客户的第一个订单"
使用文档块(Doc Blocks)复用描述
当同一段描述需要在多个地方使用时,可以用 Doc Block 复用:
<!-- docs/column_descriptions.md -->
{% docs order_id %}
订单唯一标识。
来源于 Shopify 的 `orders.id` 字段。
本示例假设该 ID 在所建模的订单数据范围内唯一;实际跨表关联前应确认各表使用相同的 ID 键空间并验证唯一性,多店铺或多来源数据可能需要组合键。
{% enddocs %}
{% docs customer_id %}
客户唯一标识。
来源于 `dim_customers.customer_id`。
通过该字段可以关联客户的所有订单、偏好、画像等信息。
{% enddocs %}
在 schema.yml 中引用:
columns:
- name: order_id
description: "{{ doc('order_id') }}" # 引用 doc block
- name: customer_id
description: "{{ doc('customer_id') }}"
tip Doc Block 的最佳用途
维度表和事实表会共享很多字段(如 customer_id)。 用 Doc Block 在一个地方维护这些字段的描述,避免多处不一致。
生成和查看文档
生成文档
# 生成文档网站(生成 target/catalog.json 等文件)
dbt docs generate
# 在本地启动文档网站(默认 http://localhost:8080)
dbt docs serve
# 指定端口
dbt docs serve --port 8888
文档网站的功能
生成的文档网站包含:
- 数据目录:所有模型、源表的列表和描述
- 字段详情:每个字段的类型、描述、测试
- 数据血缘图:可视化的依赖关系图
- SQL 查看:每个模型的编译后 SQL
数据血缘图
什么是数据血缘
数据血缘(Data Lineage)描述了数据从源头到最终产出的完整流动路径:
原始数据 → 清洗 → 关联 → 聚合 → 报表
↓ ↓ ↓ ↓ ↓
Shopify stg_ int_ fct_ BI 图表
orders orders orders orders
知道了血缘,你就能回答:
- 这张表的数据从哪里来?
- 这张表被哪些下游依赖?
- 如果我改了 staging 层,会影响哪些报表?
dbt 如何生成血缘图
dbt 从 ref() 和 source() 函数自动推断已声明的血缘关系,无需手动绘制这些模型依赖;项目外的报表消费关系等需要另行声明或纳入治理记录。
在 dbt docs 界面中,选中一个模型,点击"Lineage Graph"可以看到:
[Shopify orders] ──→ [stg_orders] ──→ [int_order_items_joined] ──→ [fct_orders]
[Shopify customers] ──→ [stg_customers] ──┘ │
└──→ [dim_customers] ────┘
在命令行查看依赖
# 查看 fct_orders 的所有上游(--select +fct_orders 中 + 在左边)
dbt ls --select +fct_orders
# 查看 stg_orders 的所有下游(+ 在右边)
dbt ls --select stg_orders+
# 查看特定层的所有模型
dbt ls --select staging
# 输出为 JSON 格式(方便程序处理)
dbt ls --select +fct_orders --output json
将血缘与数据治理结合
数据血缘不只是一张好看的图,它是数据治理的核心基础设施。
影响分析(Impact Analysis)
当你需要修改一个模型时,血缘图告诉你影响范围:
# 如果我修改了 stg_orders,哪些下游会受影响?
dbt ls --select stg_orders+
# 输出:
# my_project.staging.stg_orders
# my_project.intermediate.int_order_items_joined
# my_project.marts.core.fct_orders
# my_project.marts.core.fct_order_items
# my_project.marts.finance.fct_daily_revenue
这个列表告诉你:如果你改了 stg_orders,需要同时测试这 4 个下游模型。
根因分析(Root Cause Analysis)
当报表数据异常时,从血缘图倒推:
fct_orders 数据异常
→ 检查上游 int_order_items_joined
→ 发现 stg_orders 的 status 字段处理有误
→ 追溯到 Shopify 源数据格式变更
血缘图让问题定位从"大海捞针"变成"沿线索追踪"。这与 数据血缘追踪 中的治理方法论是相互印证的。
description 最佳实践
要写什么
# 好的文档
- name: fct_orders
description: |
订单事实表。每行代表一个完成的客户订单。
**粒度**:订单(order_id)
**数据来源**:Shopify API via Fivetran
**更新频率**:每小时增量
**重要业务规则**:
- 已取消订单不包含在此表中(如需分析取消原因,用 fct_cancellations)
- total_price_cents 包含税费和运费(商品价值用 subtotal_price_cents)
- 该表只包含 2020-01-01 之后的数据
# 不好的文档
- name: fct_orders
description: "订单表" # 废话,表名本身就是这个意思
# 更不好的:没有文档
- name: fct_orders
# description 缺失
字段描述的模板
[字段含义描述]。
来源:[来自哪个原始表/字段]。
单位:[如果是金额/数量,说明单位]。
格式:[如果是编码/枚举,列出所有可能值]。
注意:[需要特别注意的业务规则或陷阱]。
示例:
- name: discount_amount_cents
description: |
订单的折扣金额,单位:分(人民币)。
来源:Shopify orders.total_discounts,转换为分存储(原始值为元,×100)。
注意:该值恒为正数(表示折扣金额),计算实付金额时需用 subtotal 减去此值。
如果没有折扣,该字段为 0(不为 NULL)。
在 CI/CD 中发布文档
生产环境中,文档通常需要部署到内部网站供团队访问:
# .github/workflows/dbt-docs.yml
# 每次 main 分支更新时,自动重新生成并发布文档
name: Publish dbt Docs
on:
push:
branches: [main]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dbt
run: pip install dbt-core dbt-postgres
- name: Generate docs
run: |
dbt deps
dbt docs generate
env:
DBT_PROFILES_DIR: .
DB_HOST: ${{ secrets.DB_HOST }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./target
总结
| 功能 | 实现方式 | 命令 |
|---|---|---|
| 模型文档 | schema.yml 中的 description |
dbt docs generate |
| 字段文档 | columns[*].description |
dbt docs generate |
| 复用描述 | Doc Blocks(.md 文件) |
引用 {{ doc('name') }} |
| 数据血缘 | 自动从 ref() 推断 |
dbt docs serve 查看 |
| 影响分析 | dbt ls --select model+ |
命令行 |
下一步
文档和血缘搞定了,接下来学 dbt 的"超能力"——用 Jinja 模板让 SQL 更强大:
08-Jinja与宏 - 变量、条件、循环和宏,消灭 SQL 中的重复代码
最后更新:2026-10-09
#dbt #数据文档 #数据血缘 #数据治理 #数据目录
info 前置知识
- 熟悉
schema.yml的基本结构(已在测试章节中接触过),参考 测试与数据质量 - 了解数据治理中"数据目录"和"数据血缘"的基本概念
- 知道如何在命令行运行 dbt 基础命令
掌握检查
- [ ] 能在
schema.yml中为模型和关键字段写出有实际价值的description(不是废话,而是能回答"这个字段是什么、从哪来、有什么注意事项") - [ ] 能用
dbt docs generate+dbt docs serve在本地生成并查看文档网站,找到某个模型的血缘图 - [ ] 理解 Doc Blocks(
.md文件 +{{ doc('name') }})的使用场景:当多个模型共用相同字段的描述时,避免重复维护 - [ ] 知道
dbt ls --select model+命令的作用:列出某个模型及其所有下游模型(影响分析) - [ ] 能说出数据血缘图在数据变更评估中的价值:修改上游 staging 模型前,先用血缘图确认哪些下游 marts 会受到影响
实践练习
基础题:为你的 fct_orders.sql 在 schema.yml 中补充模型级别的 description(说明表的粒度、主要用途、数据时效性),以及 3 个核心字段的描述(参考本文的字段描述模板:含义、来源、单位、格式)。运行 dbt docs generate && dbt docs serve,在文档网站中验证描述是否正确显示。
进阶题:某个分析师问你"如果把 stg_orders.sql 中的 status 字段清洗逻辑修改了,会影响哪些下游模型?"。用 dbt ls --select stg_orders+ 列出 stg_orders 自身及 dbt 已声明依赖中的下游节点,识别其中受影响的模型,并在文档血缘图中核对结果;未纳入图中的外部消费关系需另行确认。说明你会如何与分析师沟通这次变更的影响范围。