dbt
问题
什么是 dbt?它如何改变数据转换的工作方式?
答案
什么是 dbt
dbt(data build tool)是现代数据栈中的数据转换工具,核心理念:用 SQL + Jinja 模板在数仓内做转换,把分析工程变成软件工程。
dbt 核心功能
| 功能 | 说明 |
|---|---|
| SQL 模型 | 每个 .sql 文件就是一个模型(表/视图) |
| ref 引用 | 模型间通过 ref() 引用,自动生成依赖 |
| Jinja 模板 | 支持变量、循环、条件,SQL 复用 |
| 数据测试 | 内置 not_null、unique、accepted_values 测试 |
| 文档 | 自动生成数据字典和血缘图 |
| 增量更新 | incremental 物化方式,只处理新数据 |
模型示例
models/staging/stg_orders.sql
-- 配置模型
{{ config(materialized='view') }}
-- 从 ODS 层清洗
SELECT
id AS order_id,
user_id,
CAST(created_at AS DATE) AS order_date,
CASE status
WHEN 1 THEN 'pending'
WHEN 2 THEN 'paid'
WHEN 3 THEN 'shipped'
WHEN 4 THEN 'completed'
ELSE 'unknown'
END AS status,
amount
FROM {{ source('raw', 'orders') }}
WHERE amount > 0
models/marts/fct_daily_revenue.sql
{{ config(materialized='table') }}
SELECT
order_date,
COUNT(DISTINCT order_id) AS order_count,
SUM(amount) AS total_revenue,
COUNT(DISTINCT user_id) AS buyer_count
FROM {{ ref('stg_orders') }}
WHERE status = 'completed'
GROUP BY order_date
dbt 测试
models/staging/schema.yml
version: 2
models:
- name: stg_orders
columns:
- name: order_id
tests:
- not_null
- unique
- name: status
tests:
- accepted_values:
values: ['pending', 'paid', 'shipped', 'completed', 'unknown']
- name: amount
tests:
- not_null
dbt 项目结构
dbt_project/
├── dbt_project.yml # 项目配置
├── models/
│ ├── staging/ # 贴源层(view)
│ │ ├── stg_orders.sql
│ │ └── schema.yml
│ ├── intermediate/ # 中间层
│ │ └── int_order_items.sql
│ └── marts/ # 集市层(table)
│ ├── fct_daily_revenue.sql
│ └── dim_users.sql
├── tests/ # 自定义测试
├── macros/ # 可复用 SQL 宏
└── seeds/ # 静态 CSV 数据
常见面试问题
Q1: dbt 和 Spark SQL 有什么区别?
答案:
| 对比 | dbt | Spark SQL |
|---|---|---|
| 定位 | 转换编排工具 | 计算引擎 |
| 执行 | 生成 SQL 推给数仓执行 | 自己执行计算 |
| 适用 | 云数仓(Snowflake/BQ) | Hadoop 生态 |
| 工程化 | ✅ 测试、文档、版本控制 | 需要自己实现 |
Q2: dbt 的 materialized 有哪些选项?
答案:
view:创建视图,每次查询实时计算table:创建物理表,dbt run 时全量刷新incremental:增量更新,只处理新数据ephemeral:不创建物理对象,内联为 CTE
Q3: dbt 怎么做增量更新?
答案:
{{ config(materialized='incremental') }}
SELECT * FROM {{ ref('stg_events') }}
{% if is_incremental() %}
-- 只处理上次运行之后的新数据
WHERE event_time > (SELECT MAX(event_time) FROM {{ this }})
{% endif %}
相关链接
- Airflow - dbt 与 Airflow 配合调度
- ETL vs ELT - dbt 是 ELT 模式的核心工具
- 数仓工具对比 - dbt 在现代数据栈中的位置