编排与治理

第18课:dbt数据转换

数据工程实战课程 · 编排与治理阶段

📦 dbt数据转换

dbt是ELT范式的核心工具,让数据分析师用SQL定义转换逻辑在数仓中执行。

🐍 Python实战:核心实战

# dbt模拟引擎
import sqlite3, time, random, json
from datetime import datetime
from collections import defaultdict

conn = sqlite3.connect(':memory:')
conn.row_factory = sqlite3.Row
c = conn.cursor()

# 创建源表
c.execute('CREATE TABLE raw_orders (id INTEGER PRIMARY KEY, customer_id TEXT, amount REAL, status TEXT, region TEXT, order_date TEXT)')
for i in range(1000):
    c.execute("INSERT INTO raw_orders VALUES (?,?,?,?,?,?)",
        (i+1, f"CUST_{random.randint(1,200)}", round(random.uniform(10,5000),2),
         random.choice(['pending','shipped','delivered','cancelled']),
         random.choice(['华东','华南','华北']), datetime.now().strftime('%Y-%m-%d')))
conn.commit()

class dbtModel:
    def __init__(self, name, sql, materialized='table', depends_on=None):
        self.name = name; self.sql = sql; self.materialized = materialized
        self.depends_on = depends_on or []
    def execute(self, conn):
        start = time.perf_counter()
        conn.execute(self.sql)
        conn.commit()
        ms = (time.perf_counter()-start)*1000
        return {'name':self.name,'materialized':self.materialized,'ms':ms}

class dbtProject:
    def __init__(self, name):
        self.name = name; self.models = []
    def add_model(self, model): self.models.append(model)
    def run(self):
        print(f"dbt run: {self.name}")
        executed = set()
        for model in self.models:
            if all(d in executed for d in model.depends_on):
                result = model.execute(conn)
                executed.add(model.name)
                print(f"  ✅ {result['name']} ({result['materialized']}): {result['ms']:.1f}ms")
    def test(self):
        print(f"dbt test: {self.name}")
        tests = [
            ("unique_raw_orders_id", "SELECT COUNT(*)-COUNT(DISTINCT id) FROM raw_orders"),
            ("not_null_raw_orders_amount", "SELECT COUNT(*) FROM raw_orders WHERE amount IS NULL"),
            ("accepted_values_status", "SELECT COUNT(*) FROM raw_orders WHERE status NOT IN ('pending','shipped','delivered','cancelled')"),
        ]
        for name, sql in tests:
            result = conn.execute(sql).fetchone()[0]
            status = "✅ PASS" if result == 0 else f"❌ FAIL ({result})"
            print(f"  {name}: {status}")

# 构建dbt项目
project = dbtProject("my_project")
project.add_model(dbtModel("stg_orders",
    "CREATE TABLE stg_orders AS SELECT id, customer_id, amount, status, region, order_date FROM raw_orders WHERE status != 'cancelled'",
    "table", []))
project.add_model(dbtModel("int_customer_orders",
    "CREATE TABLE int_customer_orders AS SELECT customer_id, COUNT(*) as order_count, SUM(amount) as total_amount FROM stg_orders GROUP BY customer_id",
    "table", ["stg_orders"]))
project.add_model(dbtModel("fct_daily_sales",
    "CREATE TABLE fct_daily_sales AS SELECT order_date, region, COUNT(*) as orders, SUM(amount) as revenue FROM stg_orders GROUP BY order_date, region",
    "table", ["stg_orders"]))

project.run()
project.test()

# 查询结果
print("\n客户订单汇总(前5):")
for row in c.execute("SELECT * FROM int_customer_orders ORDER BY total_amount DESC LIMIT 5"):
    r = dict(row); print(f"  {r['customer_id']}: {r['order_count']}单, ¥{r['total_amount']:,.0f}")
print("✅ 验证通过 - dbt模拟引擎运行正常")
💡 实战建议:动手实现本课代码示例,修改参数观察输出变化。生产环境还需考虑错误处理、监控告警和数据安全。

🎯 构建dbt项目

  1. 3层模型
  2. 5个Model+测试

🎯 增量模型

  1. 增量策略配置
  2. 性能对比

🏆 第18课成就解锁

🎁 下一课预告:数据质量!

📖 原理深入:数据编排与治理体系

数据编排成熟度模型

级别特征编排方式治理水平
L1cron+脚本无统一调度无治理
L2Airflow/DbtDAG编排基本质量检查
L3编排+治理一体自动依赖发现数据目录+血缘
L4AI辅助编排自适应调度主动质量治理

数据治理框架:人+流程+工具

🏆 最佳实践:数据编排与治理检查清单

🔬 深度案例:生产环境实战经验

踩坑与解决方案

在生产环境中,我们经常遇到教科书不会告诉你的问题。以下是常见的实战经验和解决方案:

监控与运维指标

指标告警阈值监控方式
管道延迟超过SLA 120%端到端时间戳追踪
数据量偏差日均偏差超过30%与历史同期对比
错误率超过0.1%错误计数/总记录数
数据新鲜度超过SLA 150%最新数据时间戳
资源利用率CPU持续>80%系统监控
⚠️ 常见反模式
💡 架构演进建议:不要一开始就追求完美架构。从MVP开始,随业务增长逐步演进。每次演进都要回答三个问题:当前瓶颈是什么?解决它的投入产出比如何?是否为后续扩展留了空间?

📚 延伸阅读与参考

推荐资源

🤔 常见问题与解答

Q1: 如何选择批处理还是流处理?

A: 根据业务延迟要求决定:秒级用流处理、分钟级用微批、小时级用批处理。大部分场景批处理足够,流处理用于实时业务场景(风控、监控、推荐)。

Q2: 数据湖会取代数据仓库吗?

A: 不会完全取代,但边界在模糊。湖仓一体(如Iceberg/Delta Lake)正在融合两者优势。未来趋势是统一存储+多引擎计算。

Q3: 初创公司如何选择数据技术栈?

A: 先用云原生服务(BigQuery/Snowflake + Fivetran + dbt + Looker),验证业务后再考虑自建。过早优化是万恶之源。

Q4: 如何说服业务方投资数据治理?

A: 用钱说话:数据质量问题的直接经济损失(错误决策、合规罚款、重复劳动)远大于治理投入。量化问题是第一步。

性能调优实战技巧

数据工程团队协作模式

角色职责交付物
数据工程师管道开发与维护数据管道、基础设施
数据分析师数据分析与报表SQL查询、BI报表
数据科学家模型与实验ML模型、实验报告
数据产品经理需求与优先级PRD、数据产品规划
数据管家数据质量与治理质量规则、数据字典
💡 职业发展建议:数据工程是一个快速发展的领域。保持学习的关键是:1)理解原理而非仅会工具;2)动手实践而非仅看文档;3)关注社区动态,了解最新趋势;4)建立个人项目,积累实战经验。