欢迎光临
我们一直在努力

dbt+SQLServer构建数据仓库(2):与传统方案对比及迁移决策

dbt+SQLServer构建数据仓库(2):与传统方案对比及迁移决策

本文接上篇的 dbt 定位与工作流程, 讲述:dbt 和 SQL Server 上传统数仓开发相比有哪些范式差异和取舍。

一、引言

上篇我们弄清了 dbt 是什么、一个 dbt 项目怎么跑起来。但"dbt 好不好"是个伪命题——好坏是相对的,得有参照系。这个参照系就是团队现在用的 SQL Server 传统数仓栈。

所以本文先描绘传统方案的典型形态和真实痛点,再从六个维度与 dbt 系统对比,最后给决策矩阵和迁移建议。本文不站队,目标是把两种范式的差异讲透,让你能根据团队情况做判断。

二、传统 SQL Server 数仓项目长什么样

2.1 典型技术栈

层工具作用
ETL SSIS (SQL Server Integration Services) 抽取、加载、转换一体化
转换 存储过程 (T-SQL) 复杂业务逻辑
调度 SQL Server Agent 定时跑 SSIS 包 / 存储过程
OLAP SSAS (Analysis Services) 多维模型 / 计算
报表 SSRS / Power BI 报表与可视化
IDE SSMS (SQL Server Management Studio) 主要开发环境
版本控制 数据库项目 + SSDT(可选) 较弱,很多人不用

2.2 典型开发流程

一个新需求的传统流程:

  • 需求分析 → 确认指标定义、粒度、来源
  • 设计 → 画 ER 图、定表结构、写设计文档
  • 建表 → 在 SSMS 里 CREATE TABLE …,DDL 散落各处
  • 写存储过程 → 一个 sp_dim_customer_build 之类的过程,几百上千行 T-SQL
  • 写 SSIS 包(如果需要跨源) → 拖拽式设计器,生成 .dtsx XML
  • 配 Agent Job → 设置调度、告警、重试
  • 手工测试 → 跑一遍,肉眼看数据对不对
  • 部署 → 把存储过程脚本拿去 QA/Prod 库执行,SSIS 包导入 msdb
  • 文档 → 单独写 Word/Confluence,很快和代码脱节
  • 2.3 传统方案的真实痛点

    这些不是理论问题,是项目里实打实遇到的:

  • 依赖关系靠人记:存储过程 A 依赖 B 和 C,只有跑挂了才知道。改 B 之前要全公司发邮件问"谁在用 B"。
  • 测试基本靠肉眼:除了偶尔写 IF EXISTS 检查,数据质量靠业务方投诉发现。
  • 版本控制形同虚设:存储过程改在 SSMS 里直接 ALTER,历史靠数据库备份。SSIS 的 .dtsx 是二进制 XML,diff 几乎不可读。
  • 环境不一致:Dev 库的存储过程版本和 Prod 不一样,迁移靠"复制粘贴 + 祈祷"。
  • 文档秒级腐烂:Word 文档写完就过时,没人敢信。
  • 重用靠复制:同样的逻辑在十个过程里复制十遍,改一处要改十处。
  • 新人上手慢:理解一个数仓要先读 N 个存储过程的调用链,一周才能改一个字段。
  • 三、对比分析:dbt vs 传统 SQL Server 方案

    下面从六个维度系统对比。每个维度都给出两者的具体形态和取舍。

    3.1 范式差异:声明式 vs 命令式

    这是最根本的差异。

    传统存储过程(命令式):

    CREATE PROCEDURE sp_build_dim_customer AS
    BEGIN
    TRUNCATE TABLE dim_customer;

    INSERT INTO dim_customer (customer_id, first_name, last_name, ltv)
    SELECT c.id, c.first_name, c.last_name, SUM(p.amount)
    FROM raw_customer c
    LEFT JOIN raw_order o ON c.id = o.user_id
    LEFT JOIN raw_payment p ON o.id = p.order_id
    WHERE p.status = 'completed'
    GROUP BY c.id, c.first_name, c.last_name;

    — 手动写日志
    INSERT INTO etl_log (proc_name, rows_affected, run_at)
    VALUES ('sp_build_dim_customer', @@ROWCOUNT, GETDATE());
    END

    你显式控制每一步:清表、插入、记日志、报错处理。灵活,但样板代码多,每个过程都要重复。

    dbt model(声明式):

    — models/marts/dim_customers.sql
    with customers as (select * from {{ ref('stg_customers') }}),
    payments as (
    select customer_id, sum(amount) as ltv
    from {{ ref('stg_payments') }}
    where status = 'completed'
    group by customer_id
    )
    select c.customer_id, c.first_name, c.last_name,
    coalesce(p.ltv, 0) as ltv
    from customers c
    left join payments p on c.customer_id = p.customer_id

    # dbt_project.yml 里声明物化
    models:
    my_project:
    marts:
    +materialized: table # dbt 自动处理 truncate + insert

    你只声明转换逻辑和物化意图,dbt 负责:清表、建表、依赖顺序、日志、错误处理。

    取舍:

    • 声明式省心,但失去对细节的控制(如自定义事务、特殊锁提示)
    • 命令式灵活,但样板代码膨胀,易出错
    • dbt 仍可写 pre-hook/post-hook 注入命令式逻辑,两者并非水火不容

    3.2 工程化能力对比

    能力传统方案dbt
    版本控制 SSDT 数据库项目(弱采用)或裸脚本 原生 git,每个 .sql/.yml 都是文本
    依赖管理 人工维护调用链 ref() 自动解析 DAG
    单元/数据测试 手写 IF EXISTS 检查 内建 unique/not_null/relationships/accepted_values + 自定义
    CI/CD 几乎没有,靠手动部署 GitHub Actions/GitLab CI 跑 dbt build,PR 自动验证
    文档 Word/Confluence,与代码脱节 dbt docs 从代码生成,含 DAG 血缘图
    环境隔离 鄙视链:Dev < QA < Prod,迁移靠脚本 –target dev/prod + profile 切换,schema 前缀天然隔离
    代码复用 复制存储过程,或写标量函数(性能差) macro 复用,编译期内联,无运行时开销
    可重现性 同样的脚本在不同库可能跑出不同结果 同样的代码 + 同样的 seed → 完全一致

    这一栏是 dbt 最大的优势所在。传统方案不是不能做这些事,而是每件都要自己搭:自己写测试框架、自己写文档生成器、自己搞 CI 脚本。dbt 开箱即用。

    3.3 开发体验对比

    维度传统方案 (SSMS + 存储过程)dbt (CLI + 任意编辑器)
    编辑器 SSMS(只能 Windows) VS Code / Vim / 任意编辑器(跨平台)
    反馈速度 改完 → 部署 → 等调度 → 看结果(分钟~小时) dbt run –select x(秒级)
    调试 PRINT 语句 + 临时表 dbt compile 看生成的 SQL + dbt show –inline
    改动范围 全文搜索存储过程名找调用方 dbt ls –select x+ 一键列出所有下游
    学习材料 MSDN 文档 + 公司内部 Wiki 官方文档 + 社区 + 大量博客/课程
    团队协作 锁对象、合并冲突难 git 标准 workflow,PR review

    开发体验的差异是最直观的。dbt 让数据工程师能像软件工程师一样工作——这是它能在创业公司和云原生团队迅速普及的根本原因。

    3.4 性能与调度对比

    维度传统方案dbt
    调度器 SQL Server Agent(成熟、企业级、UI 全) 不内置,需外接(Airflow/dbt Cloud/cron)
    并发执行 Agent Job 多步串行为主 threads: N 并发跑独立节点
    增量加载 存储过程 + MERGE/IDENTITY 手写 materialized=incremental + unique_key 声明式
    事务 完整 T-SQL 事务控制(默认) 默认 auto-commit,需 flag 启用 BEGIN/COMMIT
    性能调优 索引、分区、列存、内存优化表全可控 同样可控,但需通过 post-hook/原生 SQL 注入
    资源隔离 Agent Job 可绑 CPU/内存 依赖数据库侧的资源池

    结论:

    • 调度成熟度:传统方案胜。SQL Server Agent 是企业级调度器,dbt 调度需外接
    • 转换性能:两者本质都是跑 T-SQL,差异不大。传统方案对底层控制更细
    • 增量加载:dbt 声明式更省心,但复杂增量场景(如多源 MERGE + 自定义逻辑)传统方案更灵活

    3.5 SQL Server 方言适配

    这是我曾经踩过的坑,值得单独提。

    传统方案:直接写 T-SQL,方言就是方言,无适配问题。

    dbt-sqlserver:dbt-core 是方言无关的,适配器层负责翻译。但 dbt-sqlserver 有几个 legacy 行为与 dbt-core 默认不一致:

    行为dbt-core 默认dbt-sqlserver 默认启用标准行为的 flag
    schema 拼接 target.schema + '_' + custom custom 直接用(丢前缀) dbt_sqlserver_use_default_schema_concat: true
    事务 emit BEGIN TRAN/COMMIT auto-commit,失败不回滚 dbt_sqlserver_use_dbt_transactions: true
    字符串类型 STRING → VARCHAR(MAX) STRING → VARCHAR(8000) dbt_sqlserver_use_native_string_types: true

    我在实际使用的时候,就因为第一个坑(schema 拼接)第一次 dbt run 报错。解决方案是在 dbt_project.yml 加:

    flags:
    dbt_sqlserver_use_default_schema_concat: true

    启示:跨适配器迁移时,generate_schema_name 这类 macro 是高风险点,务必审阅 dbt 输出的所有 WARNING。

    3.6 学习曲线与团队适配

    维度传统方案dbt
    前置知识 T-SQL + SSIS + Agent(都是微软生态) SQL + Jinja + YAML + 命令行
    学习曲线 SSIS 拖拽上手快,深水区深 dbt 本身简单,Jinja/macros 是进阶难点
    团队背景匹配 DBA / 数据库开发熟悉的工具链 数据分析师 / 软件工程师熟悉的工具链
    招聘 国内 SQL Server DBA 池子稳定但缩水 dbt 人才稀缺但增长快
    培训成本 老团队零成本 老团队需 1-2 个月过渡
    生态惯性 已有 SSIS 包 / Agent Job 的历史包袱 新项目零负担

    关键判断:如果团队是 DBA 主导、已有大量 SSIS 资产,全面迁移 dbt 不现实;如果是数据工程师/分析师主导、新项目起步,dbt 几乎是默认选择。

    四、何时选 dbt,何时选传统方案

    基于上面的对比,给一个决策矩阵:

    4.1 选 dbt 的场景

    • ✅ 新项目从零起步,没有历史包袱
    • ✅ 团队以数据分析师/工程师为主,熟悉 git/CLI
    • ✅ 数据已落库(ELT 模式),只需做 T
    • ✅ 重视工程化(测试、CI、文档、代码审查)
    • ✅ 未来可能跨云迁移(dbt 适配器机制让迁移成本可控)
    • ✅ 数据模型迭代频繁,需要快速试错

    4.2 选传统方案的场景

    • ✅ 已有大量 SSIS 包 / 存储过程,迁移成本高于收益
    • ✅ 团队是 DBA / SQL Server 老兵,dbt 学习成本高
    • ✅ 需要重度 OLAP(SSAS 多维模型,dbt 不覆盖)
    • ✅ 调度复杂度高(SQL Server Agent 的告警、重试、作业链成熟)
    • ✅ 强依赖 SQL Server 特有功能(内存优化表、列存索引、PolyBase)
    • ✅ 合规要求严格,微软官方支持更稳妥

    4.3 决策树

    是新项目吗?
    ├─ 是 → 团队背景?
    │ ├─ 数据工程师/分析师为主 → dbt
    │ └─ DBA 为主 → 传统方案 或 dbt(视学习意愿)
    └─ 否(已有资产) → 资产规模?
    ├─ 小(<50 个过程/包) → 可考虑全量迁 dbt
    ├─ 中 (50-500) → 混合方案, 新需求用 dbt, 老的留着
    └─ 大 (>500) → 传统方案维持, 仅新模块评估 dbt

    五、混合方案:现实中最常见的落地

    实际项目里,纯 dbt 或纯传统方案都少见,混合方案是主流:

    ┌─────────────────────────────────────────────────────┐
    │ 数据源 (MySQL / API / 文件) │
    └─────────────────────────────────────────────────────┘

    │ SSIS / Airbyte 做 E+L (老资产复用)

    ┌─────────────────────────────────────────────────────┐
    │ SQL Server 原始库 (raw schema) │
    └─────────────────────────────────────────────────────┘

    │ dbt 做 T (转换层, 新方式)
    │ dbt_project.yml + models/

    ┌─────────────────────────────────────────────────────┐
    │ SQL Server 数仓层 (staging/marts schema) │
    └─────────────────────────────────────────────────────┘

    │ SQL Server Agent / Airflow 调度 dbt

    ┌─────────────────────────────────────────────────────┐
    │ Power BI / SSRS 消费 │
    └─────────────────────────────────────────────────────┘

    落地策略:

  • 保留 SSIS 做 E+L:已经稳定的抽取逻辑没必要重写
  • 转换层切到 dbt:新需求一律用 dbt model,旧存储过程逐步迁
  • 调度用 Agent 调 dbt:Agent Job 里跑 dbt run –target prod,复用成熟告警
  • OLAP 层保持 SSAS:dbt 不覆盖多维模型,该用 SSAS 还用 SSAS
  • BI 层不变:Power BI 看到的是表,不关心是存储过程还是 dbt 产的
  • 这样既享受 dbt 的工程化红利,又不浪费已有投资。

    六、迁移建议

    如果团队决定从传统方案迁 dbt,建议:

    6.1 渐进式,不要大爆炸

    • 选一个独立的小业务域(如某个部门的报表)做试点
    • 用 dbt 重建该域的转换,与老存储过程并行运行 1-2 个月
    • 数据对齐后切换 BI,下线老过程

    6.2 先建分层,再迁逻辑

    迁移前先在 dbt 里搭好 raw / staging / marts 三层骨架。老存储过程通常是"一锅炖"——清洗、聚合、业务逻辑混在一起。迁移时趁机分层,质量会提升一档。

    6.3 把测试当一等公民

    迁一个 model 就配一个 schema.yml 测试。传统方案缺测试,迁移是补测试的最佳时机。没有测试的迁移等于没迁——你无法证明新逻辑和老逻辑等价。

    6.4 适配器 flag 一次配齐

    为避免踩 schema 拼接的坑。建议 dbt-sqlserver 项目初始就把三个 flag 配上:

    flags:
    dbt_sqlserver_use_default_schema_concat: true
    dbt_sqlserver_use_dbt_transactions: true
    dbt_sqlserver_use_native_string_types: true

    避免后续逐个踩雷。

    6.5 调度平滑过渡

    第一阶段:SQL Server Agent 调 dbt run(命令行包一层)
    第二阶段:引入 Airflow / Dagster,统一调度新老资产
    第三阶段:老存储过程逐步迁成 dbt model,最终下线 Agent Job

    七、总结

    把全文浓缩成几条:

  • dbt 不是 SSIS 的替代品,而是"转换层"的现代化方案。E+L 仍可复用 SSIS,只把 T 切到 dbt。
  • dbt 的核心价值是工程化:git / 测试 / 文档 / CI / DAG 自动解析,这些是传统 SQL Server 数仓最缺的。
  • 传统方案的核心优势是企业级调度和方言原生:SQL Server Agent、SSAS、T-SQL 全功能,在微软生态里仍难替代。
  • 混合方案是现实最优解:SSIS 做 E+L,dbt 做 T,Agent/Airflow 调度,SSAS 做 OLAP,Power BI 做展示。
  • dbt-sqlserver 有 legacy 坑(schema 拼接、事务、字符串类型),新项目务必在 dbt_project.yml 配齐三个 flag。
  • 迁移要渐进:选小域试点,分层重建,测试先行,调度平滑过渡。

  • 附:核心概念对照速查表

    维度传统 SQL Server 方案dbt 方案
    转换单元 存储过程 / 视图 model (.sql)
    依赖管理 人工维护 ref() 自动 DAG
    物化决策 手写 DDL +materialized 配置
    数据测试 手写 IF EXISTS YAML 声明 + 内建 generic tests
    增量加载 手写 MERGE materialized=incremental
    历史拉链 手写 SCD2 表 + MERGE snapshot 资源
    代码复用 复制 / 标量函数 macro (Jinja)
    调度 SQL Server Agent 外接 (Airflow / dbt Cloud)
    版本控制 SSDT(弱) git 原生
    文档 Word/Confluence dbt docs 自动生成
    IDE SSMS (Windows only) 任意编辑器 (跨平台)
    调试 PRINT + 临时表 dbt compile + dbt show
    环境隔离 多库实例 –target + schema 前缀
    方言 T-SQL 原生 适配器翻译(有 legacy 差异)
    OLAP SSAS 多维模型 不覆盖
    报表 SSRS / Power BI 不覆盖(交给 BI 工具)

    参考

    • dbt 官方文档: https://docs.getdbt.com/
    • dbt-sqlserver 适配器: https://github.com/dbt-msft/dbt-sqlserver
    • dbt 工程化实践: https://docs.getdbt.com/best-practices
    • SQL Server Integration Services: https://learn.microsoft.com/sql/integration-services/
    赞(0)
    未经允许不得转载:171主机测评 » dbt+SQLServer构建数据仓库(2):与传统方案对比及迁移决策
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址