把 dbt 想成一家连锁餐厅的中央厨房管理系统。你家餐厅每天要接待上百桌客人,后厨食材堆积如山——这就是原始数据。过去传统做法(ETL)是:先在外面把菜全部做好,再端进餐厅,上菜快但味道易变、改菜单成本极高。而 dbt 的哲学(ELT)是:把所有食材先堆进宽敞的仓库冷库,客人点什么,厨师现洗现切现炒。dbt 就是那位“总厨”,拿着菜谱(SQL)指挥食材(数据)变成一道道标准菜(模型),还要负责试菜(测试)、留菜谱(文档)、记录改良(版本控制)、自动化出餐(CI/CD)。这篇文章就带你从零认识这位总厨,看看一个数据团队如何用工程化方法把数据仓库经营得井井有条。
掌握 dbt 工程化,意味着你不再只是“会写 SQL 的取数工”,而是能用分层建模、自动化测试、文档与 CI/CD 管理公司核心数据资产的数据工程师——这是数仓团队规模化协作的分水岭。
目录
可视化演示
展示dbt模型分层设计、数据血缘DAG、测试覆盖率和CI/CD流水线,点击按钮切换不同工程化视图
本节配有交互动效(进入视口后自动加载,约 3KB)。
模型分层设计 staging清洗标准化 intermediate业务逻辑 marts维度建模 逐层依赖编译执行 staging→intermediate→marts分层
工具定位:从 ETL 到 ELT 的厨房革命
想象你是一家连锁餐厅的后厨老板。过去厨房的做法是:客人在前台点单之前,后厨就提前把几十道菜全部做好、盛盘、放在保温柜里。客人点什么就直接端什么,上菜快,但菜放久了会变味,菜单改一次就要把整套菜重做一遍——这就是传统 ETL 的尴尬。而如今更聪明的方式是:把买回的食材先全部存进大冷库,客人点什么菜,厨师马上洗切炒,几分钟出锅,新鲜又灵活。
dbt(data build tool)就是帮你在“大冷库”(数据仓库)里高效做菜的那位总厨。它不负责买菜(数据抽取),也不负责修冷库(数据加载),只专注一件事:把库里现成的食材加工成客人要的菜——也就是 ELT 中的 Transform(转换)。你只需要把每道菜的菜谱写清楚,即写一段 SQL select 语句交给 dbt,总厨会自动判断先洗菜还是先切肉,最终把菜端到出餐口。
dbt 的核心是把每条转换规则封装成一个“模型”(model),模型之间通过 ref() 函数声明依赖,dbt 自动构建依赖图谱并安排执行顺序。它的核心特性包括:纯 SQL 建模、依赖自动解析、内置测试与文档、支持增量构建。适用场景覆盖企业数仓分层建设、数据湖上的分析层建模、BI 指标口径统一。生态方面,dbt Core 开源免费,dbt Cloud 提供托管调度,dbt Hub 上有大量可复用的宏包。
有了 dbt 这位总厨,后厨终于从“提前做好一堆菜”升级为“点单一律现做”。食材新鲜、口味可控、菜谱改起来也快——这就是 ELT 时代数据团队想要的灵活与确定性。
- Extract(抽取)把业务系统的原始数据搬运到临时缓冲,相当于从菜市场采购食材回厨房。
- Load(加载)将缓冲数据原封不动灌入数据仓库,相当于食材不处理直接进冷库。
- Transform(转换)在数仓内部完成清洗、加工与聚合,相当于厨师按菜谱现做现卖。
项目搭建:铺好灶台才能开火
新主厨上任的第二天,不会急着颠勺炒菜,而要先看灶台布局、确认调料架在哪、数一数冰箱里有什么存货。dbt 项目搭建也是如此——先搭骨架,再谈建模。一个干净的项目结构,决定了后续团队协作时“东西该放哪儿”的共识。
一条 dbt init 命令会生成标准项目骨架,里面最核心的两份配置是 dbt_project.yml(总菜谱目录,声明模型目录与物化策略)和 profiles.yml(设备清单,声明数据库地址、账号与目标环境)。此外,sources.yml 负责定义源数据的“供货商名单”,让模型通过 source() 引用上游表而不是硬编码表名。
一个标准 dbt 项目包含这些目录:models 放 SQL 模型,macros 放可复用逻辑(Jinja 宏),seeds 放需要导入库中的静态小数据(如国家代码表),snapshots 用时间快照记录维度表的历史变化,tests 放自定义测试。依赖方面,packages.yml 声明从 dbt Hub 安装的宏包,dbt deps 一键拉取。环境配置上,profile 里可以同时配 dev 和 prod 两套 target 指向不同数据库,避免开发污染生产。
锅台码整齐了,火才能烧得稳。项目结构标准化是 dbt 工程化所有实践的起点——新同事入职第一天,看到目录就知道该往哪儿写代码。
- models(菜谱集)所有 SQL 模型文件存放的地方,决定后厨能做出哪些菜。
- macros(厨具)用 Jinja 封装的复用 SQL 片段,相当于多功能料理机。
- seeds(小料)随仓库提交的静态小文件,导入后供模型 join 使用。
- snapshots(冷藏保鲜)快照维度表的历史版本,便于回溯“食材当初的样子”。
- tests(试菜清单)声明式校验规则存放地,自动化把关数据质量。
模型分层:水台、砧板、灶台三道工序
一家正规餐厅的后厨,绝不会让一个人同时洗菜、切菜、炒菜。标准厨房分三条线:水台把菜洗净去泥,砧板负责切配腌制,灶台负责调味出锅。每个岗位职责清晰、互不越界,后厨再忙也不会乱。dbt 的模型分层设计正是这个思路。
最接近源数据的一层叫 staging,只做“洗菜”:列裁剪、去脏数据、统一数据类型、表名规范化,保持和源表一一对应。中间层叫 intermediate,做“切配”:把多张 staging 表 join 起来,做业务口径的预聚合,产出可复用的中间表。最上层叫 marts,是“出菜口”:面向业务方产出宽表、维度表和指标表,指标口径在这里最终固化。
分层带来的好处肉眼可见:staging 出问题可快速定位到源头;多团队共享 intermediate 避免重复开发;marts 层表结构稳定,下游报表不会频繁改动。命名规范与分层配套:源表 tp_orders 对应 stg_tp_orders,中间加工表叫 int_orders_agg,最终表按用途分为 dim_customer(维度表)和 fact_orders(事实表)。
后厨分层清清楚楚,一百道菜同时在做也不会乱套。数据团队上百人协作时,这套分层就是彼此的默契与边界。
- source(原始食材)数据仓库里来自源头系统的原始表。
- staging(水台洗净)去重、去空、类型修正,得到干净的贴源视图。
- intermediate(砧板切配)多表关联、业务预聚合,得到半成品表。
- marts(灶台出品)最终面向业务的宽表与指标表。
测试自动化:出锅前的试菜质检
餐厅向连锁分店统一发菜谱,最怕什么?分店厨师手一抖多放一勺盐,或者食材过期了还照常出锅。所以必须设置“试菜师”岗位——每道菜端给客人之前过一道质检。dbt 工程化也内置了完整的“试菜”体系:dbt test 一条命令,把项目里的质量校验全部跑一遍。
测试分两类。singular test(单次测试)是手写一段 SQL 断言,期望返回 0 行,只要返回了行就说明数据有问题;generic test(通用测试)是声明式的,在 schema.yml 里配置即可,常见的有 unique(唯一性)、not_null(非空)、accepted_values(取值枚举)、relationships(外键完整性)。前者像专门为某道菜定制口味标准,后者像统一的后厨卫生规范。
除了数据内容测试,还有 freshness(新鲜度检查)用于监控“食材是否过期”:给源表设置加载时限,例如订单表最多落后 2 小时,超时自动报警。工程上,测试必须和模型一起设计——每个 marts 层表都要配套“指标不出现负数、订单量不为 0”这类业务断言,测试全部通过才能进入生产环境。
有了试菜师,后厨才敢承诺“味道标准化”。数据团队也才能在业务面前拍胸脯:这份数据是过了测试才上桌的。
- 单个测试对数据集 D 执行第 i 项校验,返回通过或不通过。
- 全部通过所有测试结果取逻辑与,任何一项失败则整体失败。
- 测试设计通用规则加业务规则共同组成完整测试集。
文档生成:写清每道菜的菜谱
餐厅开连锁,光靠总厨脑子里记菜谱是不够的。今天这个分店问“宫保鸡丁的糖放多少”,明天那个分店问“这道菜什么口味”,总厨得回答一百遍。所以必须把菜谱写下来,挂到每个分店厨房的墙上——数据仓库也一样,光有代码没有说明,后来者只能靠猜。
dbt 把“写菜谱”融进了建模流程。每个模型和字段都可以在 schema.yml 里写 description(业务描述),例如 fact_orders.order_amount 注明“支付成功订单的实付金额,含税”。dbt 还支持 doc block,把大段说明文字集中管理,模型文件中用 {{ doc('orders_desc') }} 引用,避免在 SQL 里堆长篇注释。
dbt docs generate 会自动生成一个静态文档站点,包含模型描述、列信息、测试覆盖情况,最亮眼的是 lineage(数据血缘)图——清晰展示每张表从 staging 到 marts 的依赖链。配合 dbt docs serve 本地起服务,分析师和数据工程师都能在浏览器里查“这张表的数据从哪来、被谁使用”。机器生成加人工描述结合,数据资产终于有了可读的说明书。
菜谱挂上墙,新来的厨师一周就能上手。文档不是写给别人看的负担,而是数据团队的“交接保险”。
- 分子已有完整描述文档的模型数量。
- 分母项目中的模型总数,代表全部待说明对象。
- 覆盖率比值越高,说明数据资产透明度越高,团队越容易接手。
版本控制:厨房的改良记录册
每家餐厅都会改良菜品,但绝对不能今天改盐量、明天改火候却不留记录。要是顾客说“上周的宫保鸡丁更好吃”,后厨得能一键回到上周的配方。dbt 工程化的版本控制,就是给数据模型做一本“改良记录册”。
dbt 项目本质上全是代码和配置文件,天然适合用 Git 做版本控制。推荐的协作流程是:每个数据工程师开 feature 分支开发模型,提交后发起 Pull Request,经过代码评审(code review)通过后再合并到主干。每一次合并都是数据模型的“官方改良记录”,谁在什么时候改了哪张表,翻开 Git 历史一目了然。
环境管理是版本控制的延伸。常见做法是 dev / staging / prod 三套环境,通过 dbt 的 target 机制指向不同数据库 schema,开发者在自己的沙箱 schema 里随意试验,不影响生产数据。变更追踪还体现在模型版本上:发布时可以给主干打 tag,例如 v1.2.0;一旦生产出问题,回滚代码就能恢复到上一个稳定版本。
改良记录册越详细,餐厅试错成本越低。数据团队最怕“谁动过这张表没人知道”,Git 恰恰让每个操作都有据可查、有路可退。
- 提交(commit)一次对模型 SQL 或配置的变更快照。
- 版本累积当前版本等于所有历史提交的并集,保证可回溯到任意时刻。
- 回滚能力基于版本并集可恢复任意历史状态。
CI/CD 集成:中央厨房自动流水线
中央厨房的终极形态是全自动化:顾客手机下单,订单自动传到后厨,机器自动备料,炒菜机器人按菜谱翻炒,出锅自动送到出餐口——中间不需要人扯着嗓子喊“三号桌鱼香肉丝”。dbt 与 CI/CD 结合,就是把“手动跑数”升级成“自动出餐”。
常见做法是在 GitHub Actions 或 GitLab CI 里配置流水线:当开发者把分支推送到远程时自动触发——dbt deps 安装依赖 → dbt seed 加载种子数据 → dbt run 在临时 schema 构建模型 → dbt test 跑全部测试 → dbt docs generate 生成最新文档。任何一步失败,流水线亮红牌,阻止代码合并。
生产发布环节可以加一道人工审批:流水线先生成预览环境的数据验证报告,数据负责人确认后点击发布,dbt build --target prod 把全链路跑一遍并写入线上 schema。如果发布后发现上游数据异常,回滚策略通常是 Git revert 代码,再用上一个 tag 重新构建受影响的模型,而不是手工去改生产表。
从点单到出餐全自动,后厨节奏彻底稳定。数据团队不再当“消防员”随时救火,而是把规则写进流水线,让机器守门。
- run(先构建)流水线最先执行模型构建,从 SQL 生成数据表。
- test(再测试)构建完成后执行质量校验,拦截问题数据。
- deploy(后部署)只有测试通过才将产物发布到生产环境。
运行与运维:厨房每天的开门营业
中央厨房开张后,每天要面对的是例行公事:早上检查冰箱食材新不新鲜,午市高峰盯着哪道菜出得最慢,晚上复盘今天有没有菜品被退单。dbt 项目上线之后,日常运维围绕四件事展开:增量模型、任务调度、性能优化、监控告警。
增量模型(materialized='incremental')避免每天全量重建大表,只处理上次运行之后新增的数据,如同不过夜地把当日新菜加工好、老菜原封不动。调度可以由 dbt Cloud 定时作业、Apache Airflow、Dagster 或普通 cron 承担,通常凌晨跑全量维度表、白天跑高频增量表。性能优化方面,可以调整模型的物化策略(视图、表、增量)、对大表按时间分区、优化 join 顺序。监控告警则在流程中配置:测试失败立即通知,freshness 超时告警,运行日志集中收集,让异常在上游就暴露。
餐厅开门营业,拼的不是开业那一刻的阵仗,而是日复一日的稳定出餐。数据仓库同样如此:运行与运维做得扎实,业务方每天早上才能看到准点的数据早餐。
- 上次运行时刻模型最近一次成功构建的时间点,是增量任务的起点。
- 当前时刻调度器准备运行新一批数据的时间,是增量任务的终点。
- 增量窗口只处理窗口内的新数据,降低构建成本。
AI 应用场景
场景 1:企业数仓分层建设
阶段:数据工程与建模
解决的问题:几十条业务线的几百张源表散落各处,报表口径五花八门。传统方式靠人工写 SQL 临时取数,效率和一致性都差。dbt 用 staging / intermediate / marts 三层模型统一加工,配合命名规范,让“谁负责哪一层、表放哪个目录”一目了然。
具体案例:某电商公司数仓团队用 dbt 将订单、用户、商品三域模型化。staging 层直接映射业务库表,intermediate 层完成订单明细与用户维度的 join,marts 层产出 fact_orders 与 dim_customer。新同学入职一周就能通过血缘图定位“销售额对不上”的问题出在中间层哪张表。
场景 2:数据质量门禁
阶段:数据质量与自动化测试
解决的问题:脏数据进入报表后,业务方基于错误数据做决策,代价极高。传统方式靠人工抽查,滞后且覆盖不全。dbt 内置测试与 freshness 机制,把质量检查前置到发布环节。
具体案例:某金融科技公司每天凌晨跑批,流水线中 dbt test 自动校验订单金额非负、客户 ID 唯一、外键关联完整;freshness 检测到支付流水表超过 30 分钟未更新就触发告警。测试失败时流水线自动阻断,数据负责人收到通知后第一时间排查上游。
场景 3:数据资产目录与血缘审计
阶段:数据治理与团队协作
解决的问题:数仓表越来越多,业务方不知道该信哪张表,合规审计也要求追溯数据来源。传统方式靠维护 Excel 文档,更新不及时。dbt 自动生成文档站和血缘图,让数据资产“可读、可查、可追溯”。
具体案例:某零售集团用 dbt docs generate 搭建内部数据目录,分析师在浏览器中搜索“毛利率”就能找到口径说明与上游依赖;季度审计时,合规团队通过血缘图快速输出“某指标数据来自哪些源系统”的报告,审计准备时间从两周缩短到一天。
Python 演示
# -*- coding: utf-8 -*-"""dbt 工程化核心流程迷你模拟器: 分层 -> 构建 -> 测试""" ORDERS_RAW = [ {"oid": "o1", "uid": 101, "date": "2026-01-05", "amount": 120.0, "status": "paid"}, {"oid": "o2", "uid": 102, "date": "2026-01-06", "amount": None, "status": "paid"}, {"oid": None, "uid": 103, "date": "2026-01-07", "amount": 80.0, "status": "refunded"}, {"oid": "o3", "uid": 101, "date": "2026-01-08", "amount": 210.0, "status": "paid"}, {"oid": "o4", "uid": 104, "date": "2026-02-01", "amount": 45.5, "status": "paid"},] def stage(raw_rows): """staging: 清洗去杂, 保留有效支付订单""" cleaned = [] for r in raw_rows: if r["oid"] is None or r["amount"] is None: continue if r["status"] != "paid": continue cleaned.append(r) return cleaned def intermediate(staged): """intermediate: 业务加工, 提取年份与月份维度""" out = [] for r in staged: out.append({ "oid": r["oid"], "uid": r["uid"], "date": r["date"], "amount": r["amount"], "year": int(r["date"][:4]), "month": int(r["date"][5:7]), }) return out def marts(inter_rows): """marts: 面向业务的月度订单指标表""" agg = {} for r in inter_rows: key = (r["year"], r["month"]) if key not in agg: agg[key] = {"order_count": 0, "total_revenue": 0.0} agg[key]["order_count"] += 1 agg[key]["total_revenue"] += r["amount"] return [ {"year": k[0], "month": k[1], "order_count": v["order_count"], "total_revenue": v["total_revenue"]} for k, v in sorted(agg.items()) ] def run_tests(table, tests): """dbt test: 逐条执行断言, 返回 (用例名, 结果) 列表""" results = [] for name, fn in tests.items(): try: fn(table) results.append((name, "PASS")) except AssertionError: results.append((name, "FAIL")) return results def dbt_build(raw_rows): """dbt build: 按 staging -> intermediate -> marts 依序构建并测试""" st = stage(raw_rows) mid = intermediate(st) mart = marts(mid) tests = { "order_count_non_negative": lambda t: all(r["order_count"] >= 0 for r in t), "revenue_positive": lambda t: all(r["total_revenue"] > 0 for r in t), } print("== dbt build 流水线输出 ==") print("staging 清洗后行数:", len(st)) print("intermediate 加工后行数:", len(mid)) print("marts 月度指标:") for row in mart: print(" ", row) for name, status in run_tests(mart, tests): print("test %s: %s" % (name, status)) return mart if __name__ == "__main__": dbt_build(ORDERS_RAW)
def stage(raw_rows):staging 对应洗菜环节,只做最小清洗,剔除无效订单。if r["oid"] is None or r["amount"] is None:跳过缺关键字段的脏数据,保证下游不拿到残缺的“食材”。"year": int(r["date"][:4]),intermediate 层从日期字符串提取年份月份,属于典型的业务维度加工。agg[key]["total_revenue"] += r["amount"]marts 层按(年,月)分组聚合订单金额,产出面向业务的月度指标。def run_tests(table, tests):测试框架:把每个断言看作一条 dbt test,逐条执行并记录 PASS/FAIL。"revenue_positive": lambda t: all(r["total_revenue"] > 0 for r in t),业务断言:月度营收必须为正,等价于 schema.yml 里配置的 accepted_values 或自定义规则。dbt_build(raw_rows)一个函数对应dbt build:按依赖顺序完成三层构建并执行测试,失败时结果中会出现 FAIL。
常见误区
误区初学者刚接触 dbt 时,看到它既能建模又能测试、还能定时跑,以为这就是个“全家桶”工具,项目里干脆把 Airflow 也撤了,所有调度全交给 dbt。
正解dbt 只负责 ELT 里的 T(转换)。它不会帮你去业务库抽数,也不会替你管理跨系统的复杂编排。项目内部的模型依赖它可以自动排序,但全公司级别的跨调度器任务编排,仍然要交给 Airflow、Dagster 或 dbt Cloud 的作业功能。比喻:总厨只负责后厨做菜,买菜入库和排班是其他岗位的事。
为何常见:因为 dbt 确实自带简单的调度与执行编排能力,初学者容易把“能做一点”误解成“全能替代”。
误区有人习惯把 join、聚合、业务口径判断全部堆进 staging 层,觉得 SQL 写在哪儿都一样,少写几个中间表还能省事。
正解staging 层的黄金法则是“贴源、轻量、一一对应”。它只做最小清洗,一旦把业务 join 塞进来,源表映射关系就被破坏,出了问题很难判断是源数据脏还是加工逻辑错。join 和指标计算应放到 intermediate 与 marts 层,让每一层职责单一。
为何常见:刚上手时觉得少分层、少写 ref 能加快开发,但维护期会发现改一处导致全线崩,排查成本翻倍。
误区很多人建完模型补几个 not_null 和 unique 测试,就觉得质量保障完成了。实际上这些内置测试只覆盖了“字段有没有值”的底线,业务口径完全没验。
正解通用测试只是地基,真正有价值的是业务断言:订单金额必须大于 0、退款率不能超过阈值、外键关系必须完整。测试要跟着模型分层设计,marts 层每个指标表都应有配套断言,并在发布到生产前作为门禁。
为何常见:dbt 官方示例里最常见的就是 not_null 和 unique,照着模板写完后容易误以为这就是测试体系的全部。
误区有的团队上了 CI/CD 流水线,觉得机器能跑测试、能构建、能发布,Pull Request 评审就随便看两眼甚至直接合并。
正解CI 只能保证“构建通过、测试绿”,但无法判断模型口径是否正确、命名是否规范、分层设计是否合理——这些必须靠人来判断。比喻:流水线是自动出餐的机器人,但菜好不好吃、菜谱要不要改,仍然要主厨拍板。
为何常见:看到自动化流程常产生“机器都检查过了”的错觉,忽略了代码评审在知识传递和设计把关上的价值。
面试题
Q1. dbt 在 ELT 流程中主要负责哪一步?
- A.数据抽取(Extract)
- B.数据加载(Load)
- C.数据转换(Transform)← 正确答案
- D.数据可视化(View)
答案:C。dbt 的全称是 data build tool,专注 ELT 最后的 T。A 是抽取、B 是加载,通常由 Airflow 或 Fivetran 等工具完成,D 是 BI 层的事。比喻:dbt 是后厨里负责加工食材的厨师,不负责采购和上菜。
Q2. dbt 模型最常见的实现方式是什么?
- A.一段 SQL select 语句← 正确答案
- B.一段 Python 脚本
- C.一份 JSON 配置文件
- D.一次 API 数据请求
答案:A。dbt 最核心的模型就是写 SQL select,dbt 负责把它物化成表或视图。虽然 dbt 也支持 Python 模型,但纯 SQL 建模才是主流和默认方式。JSON 是配置,API 是数据获取,都不是模型本体。
Q3. staging 层最主要的职责是什么?
- A.直接对接源表做清洗← 正确答案
- B.面向业务方提供宽表
- C.跨域关联多个业务表
- D.承担最终的指标聚合
答案:A。staging 层紧贴源表,做去重、去空、类型修正等轻量清洗,保持与源表一一对应。B 是 marts 层、C 和 D 是 intermediate 层的事。比喻:staging 只是水台洗菜,不做切配和调味。
Q4. generic test 与 singular test 的主要区别是什么?
- A.前者声明式配置、后者手写查询← 正确答案
- B.前者运行更慢、后者运行更快
- C.前者只用于生产、后者只用于开发
- D.前者只能测非空、后者只能测唯一
答案:A。generic test 在 schema.yml 里声明即可复用,如 not_null、unique;singular test 则需要手写 SQL 断言。C 和 D 都是错误限制,两类测试开发和生产都能用,能力也不限于某一种检查。
Q5. dbt docs generate 生成的内容中不包含哪一项?
- A.模型描述与列信息
- B.表与表之间的血缘图
- C.数据库实时监控告警← 正确答案
- D.测试覆盖率统计
答案:C。docs generate 生成的是静态文档站,包含模型描述、列信息、血缘和测试覆盖,但它不做实时监控,那是运维告警系统的工作。比喻:菜谱上写了原料和步骤,但不会实时告诉你冰箱里菜坏了没有。
Q6. 关于增量模型(incremental),以下说法正确的有哪些?
- A.只处理上次运行后的新数据← 正确答案
- B.首次运行会全量构建← 正确答案
- C.可以完全替代全量刷新
- D.需要设计时间窗口条件← 正确答案
答案:ABD。增量模型的核心是只加工 Δt 窗口内的新数据,首次运行时因为没有历史基线所以全量构建,但后续仍需定期全量或按需刷新来修正历史数据,不能完全替代全量刷新。D 是增量模型的必备条件,没有窗口就没法判断哪些是新数据。
Q7. dbt_project.yml 的典型作用是什么?
- A.配置项目目录与物化策略← 正确答案
- B.存储数据库查询结果
- C.声明 dbt 的版本来源
- D.定义任务调度的时间
答案:A。dbt_project.yml 是项目的总配置,声明模型目录、物化策略、变量等。数据库连接在 profiles.yml 里配置,任务调度则由 dbt Cloud 或 Airflow 负责,都不是这个文件的工作。
Q8. 在 CI/CD 流水线中,dbt 通常参与的环节有哪些?
- A.依赖安装与种子数据加载← 正确答案
- B.模型构建与数据测试← 正确答案
- C.数据库服务器硬件采购
- D.文档生成与发布← 正确答案
答案:ABD。CI 流水线里 dbt 的典型动作是 deps、seed、run、test、docs generate,覆盖 A、B、D。C 属于基础设施采购,与 dbt 的代码流水线无关。比喻:自动出餐流水线包含备料、翻炒、质检和拍照上传菜单,但不包含装修厨房。
Q9. 关于 dbt 的数据血缘(lineage),下列说法准确的是?
- A.展示模型间依赖,为排查影响提供依据← 正确答案
- B.血缘图是数据库物理存储结构图
- C.只有 marts 层才有血缘关系
- D.血缘关系在编译阶段无法生成
答案:A。dbt 通过 ref() 和 source() 在编译期解析模型依赖,生成从 staging 到 marts 的血缘图,帮助定位“改动这张表会影响谁”。B 是物理存储概念,C 错误,血缘跨越所有层,D 错误,血缘恰恰在编译阶段生成。
Q10. 关于 dbt 的环境管理,下列做法正确的有哪些?
- A.dev 与 prod 使用不同 target 配置← 正确答案
- B.每次开发用独立的临时 schema← 正确答案
- C.生产环境直接执行未经测试的代码
- D.通过 profile 指向不同数据库← 正确答案
答案:ABD。环境隔离是 dbt 工程化的基本要求:dev 和 prod 用不同 target,个人开发用独立临时 schema 互不干扰,profile 配置决定了每个环境连接哪个数据库。C 是危险做法,生产代码必须经过 CI 测试和评审才能上线。