第3部分:测试、文档与部署 🚀

发布: (2026年2月17日 GMT+8 06:46)
9 分钟阅读
原文: Dev.to

抱歉,我需要您提供要翻译的具体文本内容才能进行翻译。请把文章的正文(除代码块和链接外)粘贴在这里,我会按照要求将其翻译成简体中文并保留原有的格式。

数据工程 Zoomcamp

#dbt #AnalyticsEngineering #DataModeling

Macros – 可复用的 SQL 函数 🔧

没有宏(重复代码)

-- ❌ Repeated everywhere
CASE 
    WHEN payment_type = 1 THEN 'Credit card'
    WHEN payment_type = 2 THEN 'Cash'
    WHEN payment_type = 3 THEN 'No charge'
    WHEN payment_type = 4 THEN 'Dispute'
    WHEN payment_type = 5 THEN 'Unknown'
    ELSE 'Unknown'
END AS payment_type_description

使用宏(一次编写)

-- macros/get_payment_type_description.sql
{% macro get_payment_type_description(payment_type) %}
    CASE {{ payment_type }}
        WHEN 1 THEN 'Credit card'
        WHEN 2 THEN 'Cash'
        WHEN 3 THEN 'No charge'
        WHEN 4 THEN 'Dispute'
        WHEN 5 THEN 'Unknown'
        ELSE 'Unknown'
    END
{% endmacro %}

在任意模型中使用

-- models/staging/stg_green_tripdata.sql
SELECT
    payment_type,
    {{ get_payment_type_description('payment_type') }} AS payment_type_description
FROM {{ source('staging', 'green_tripdata') }}
语法用途示例
{{ }}输出表达式{{ ref('my_model') }}
{% %}逻辑/控制流{% if is_incremental() %}
{# #}注释{# This is a comment #}

软件包 – 重用他人构建的宏和模型

PackageWhat it Does
dbt_utils常用的 SQL 辅助工具(代理键、透视等)
dbt_codegen自动生成 YAML 和 SQL
dbt_expectationsGreat Expectations 风格的测试
dbt_audit_helper在重构时比较模型输出

创建 packages.yml

packages:
  - package: dbt-labs/dbt_utils
    version: 1.1.1

安装软件包

dbt deps

使用软件包中的宏

-- 使用 dbt_utils 生成代理键
SELECT
    {{ dbt_utils.generate_surrogate_key(['vendorid', 'pickup_datetime']) }} AS trip_id,
    *
FROM {{ source('staging', 'green_tripdata') }}

Tests – Ensure data meets expectations

1️⃣ Generic Tests (most common)

Add them in a schema YAML file:

# models/staging/schema.yml
version: 2

models:
  - name: stg_green_tripdata
    columns:
      - name: trip_id
        tests:
          - unique       # No duplicate values
          - not_null     # No null values

      - name: payment_type
        tests:
          - accepted_values:
              values: [1, 2, 3, 4, 5, 6]  # Allowed values only

      - name: pickup_location_id
        tests:
          - relationships:               # Referential integrity
              to: ref('dim_zones')
              field: location_id
TestDescription
unique列中没有重复值
not_null列中没有 NULL 值
accepted_values值必须在指定列表中
relationships值必须存在于另一张表中

2️⃣ Singular (custom) Tests

Place a .sql file in the tests/ folder:

-- tests/assert_positive_fare_amount.sql
-- Test FAILS if any rows are returned
SELECT
    trip_id,
    fare_amount
FROM {{ ref('fct_trips') }}
WHERE fare_amount < 0

Fact table containing all taxi trips (yellow and green).
One row per trip with fare details and zone information.

Generate & serve docs

dbt docs generate   # Build the site
dbt docs serve      # Open in a browser

The site includes:

  • Model descriptions
  • Column definitions
  • Dependency graph (visual DAG)
  • Source information

常用 dbt 命令

命令功能
dbt run构建所有模型(创建视图/表)
dbt test运行所有测试
dbt build同时运行模型测试(推荐)
dbt compile生成 SQL 而不执行
dbt debug检查连接和项目配置
dbt seed加载 seed CSV 文件
dbt deps安装包
dbt docs generate生成文档
dbt docs serve本地提供文档服务
dbt retry重试失败的模型

选择特定模型

# Single model
dbt run --select stg_green_tripdata

# Model + all upstream dependencies
dbt run --select +fct_trips

# Model + all downstream models
dbt run --select stg_green_tripdata+

# Both directions
dbt run --select +fct_trips+

# All models in a folder
dbt run --select staging.*

# Multiple models
dbt run --select stg_green_tripdata stg_yellow_tripdata

# Development (default target)
dbt run

# Production target
dbt run --target prod

物化(Materializations)— dbt 如何持久化模型

类型创建内容典型使用场景
viewSQL 视图(查询已存储,访问时执行)暂存模型,逻辑经常变化
table物理表(数据已存储)最终数据集市,大数据集,性能关键查询
incremental仅追加新数据超大表,事件式数据
ephemeral不创建(在下游作为 CTE)辅助模型,中间步骤

在模型文件中设置物化

{{ config(materialized='table') }}

SELECT *
FROM {{ ref('stg_trips') }}

或在 dbt_project.yml 中全局设置

models:
  my_project:
    staging:
      materialized: view
    marts:
      materialized: table

快速决策助手

┌─────────────────────────────────────────────────────────────┐
│               Should I use a view or a table?             │
└─────────────────────────────────────────────────────────────┘

当底层逻辑经常变化,或数据集足够小,以至于在每次查询时重新计算成本低廉时,使用 view
当您需要持久化数据以提升性能、供下游使用,或数据集庞大且重新计算成本高时,使用 table

Decision Flow


┌──────────────────────────┐
│ Is the query expensive?  │
└──────────────────────────┘
       │            │
      Yes          No
       │            │
       ▼            ▼
 ┌─────────┐   ┌─────────┐
 │  TABLE  │   │  VIEW   │
 └─────────┘   └─────────┘

使用 VIEW 的情况

  • 暂存模型(简单转换)
  • 逻辑经常变更
  • 存储成本是考虑因素

使用 TABLE 的情况

  • 最终数据集经常被查询
  • 复杂的连接/聚合
  • 查询性能很重要

项目概览 – NYC 出租车数据

┌──────────────────────────────────────────────────────────────┐
│                      RAW DATA                                 │
│  green_tripdata (GCS/BigQuery) │ yellow_tripdata (GCS/BigQuery)│
└───────────────────┬─────────────────────┬────────────────────┘
                    │                     │
                    ▼                     ▼
┌──────────────────────────────────────────────────────────────┐
│                    STAGING LAYER                              │
│  stg_green_tripdata    │    stg_yellow_tripdata               │
│  (cleaned, renamed)    │    (cleaned, renamed)                │
└───────────────────┬─────────────────────┬────────────────────┘
                    │                     │
                    └──────────┬──────────┘


┌──────────────────────────────────────────────────────────────┐
│                  INTERMEDIATE LAYER                           │
│                   int_trips_unioned                           │
│            (green + yellow combined)                          │
└───────────────────────────────┬──────────────────────────────┘


┌──────────────────────────────────────────────────────────────┐
│                      MARTS LAYER                              │
│  ┌─────────────┐  ┌───────────────┐  ┌─────────────────────┐ │
│  │ dim_zones   │  │   fct_trips   │  │ fct_monthly_zone_rev │ │
│  │ (dimension)│  │    (fact)     │  │      (report)        │ │
│  └─────────────┘  └───────────────┘  └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘

模型目录

ModelTypeDescription
stg_green_tripdataStaging已清洗的绿色出租车数据
stg_yellow_tripdataStaging已清洗的黄色出租车数据
int_trips_unionedIntermediate合并的黄色 + 绿色行程
dim_zonesDimension区域查找表
fct_tripsFact每次行程对应一行
fct_monthly_zone_revenueReport按区划分的月度收入

本地开发(DuckDB)

优点: 免费,无需云账户
缺点: 受限于机器资源

# 1. Install dbt with the DuckDB adapter
pip install dbt-duckdb

# 2. Clone the project
git clone https://github.com/DataTalksClub/data-engineering-zoomcamp
cd data-engineering-zoomcamp/04-analytics-engineering/taxi_rides_ny

# 3. Create `profiles.yml` in `~/.dbt/`
# 4. Test the connection
dbt debug

# 5. Build the project
dbt build --target prod

云端开发(dbt Cloud + BigQuery)

优点: 强大,团队协作,调度器
缺点: 需要 GCP 账户(提供免费层)

  1. 创建一个 dbt Cloud 账户(免费)。
  2. 将其连接到你的 BigQuery 项目。
  3. 在 dbt Cloud IDE 中克隆仓库。
  4. 运行:
dbt build --target prod

常见问题排查 🔍

“未找到配置文件”

  • 验证 dbt_project.yml 中的 profile 名称与 profiles.yml 中的名称一致。
  • 确保 profiles.yml 位于 ~/.dbt/ 目录下。

“未找到来源”

  • 检查 sources.yml 中的数据库/模式名称。
  • 确认数据已加载到数据仓库。
  • 查找 ref() 调用中的拼写错误,并确保被引用的模型存在。

可选的内存调优(profiles.yml):

settings:
  memory_limit: '2GB'

关键概念

  • Analytics Engineering 将数据工程和数据分析连接起来。
  • dbt 将软件工程的最佳实践引入 SQL 转换。
  • Dimensional modeling 将数据组织为 facts(事件)和 dimensions(属性)。
  • 三层结构:staging(原始副本)、intermediate(转换层)、marts(最终可消费表)。
  • ref()source() 是构建模型依赖的主要函数。
  • Testing 确保数据质量——使用 uniquenot_nullaccepted_valuesrelationships
  • 文档由 YAML 描述自动生成。
  • dbt build 按依赖顺序运行并测试所有内容。

附加资源 📚

建模愉快! 🚀

0 浏览
Back to Blog

相关文章

阅读更多 »