尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用规则引擎治理dbt配置:像ESLint一样检查你的数据管道

用规则引擎治理dbt配置:像ESLint一样检查你的数据管道 接手一个跑了半年的 dbt 项目你最想做的第一件事是什么大多数人会打开dbt_project.yml再翻几十个模型 SQL 文件靠肉眼逐个检查物化策略、unique_key、schema和tags这些配置。一开始项目小这种“人肉 review”还能忍受可当模型数量超过 50 个、100 个不同同学写出来的配置风格完全不一致问题就开始集中爆发有的增量模型漏了unique_key跑了几轮之后表里全是重复数据有的模型被物化成table却没有任何下游任务引用白白占用存储和每日重跑成本有的团队在schema.yml里写测试却不知道模型的materialized和引用关系早就互相矛盾。真正让 dbt 项目失控的往往不是 SQL 写不出来而是配置不可治理。本文要讲的 OptiPipe定位就是 dbt 管道的“基于规则的配置顾问”它用一种类似 ESLint/Checkstyle 的思路在不运行模型的情况下静态扫描整个 dbt 项目告诉你哪些配置不合理、哪些会产生重复数据、哪些模型已经变成“沉默资产”。读完这篇文章你可以理解三件事dbt 配置到底在管什么基于规则的配置顾问为什么适合解决配置治理问题以及如何把一个最小可用的规则检查器接入自己的 dbt 项目流程。1. 为什么 dbt 项目需要配置顾问dbt 把数据工程里的“转换层”变成了 SQL 和 Git这确实是一个巨大的进步。分析工程师可以像写后端代码一样管理数据模型代码评审、版本回滚、环境隔离都变得标准化。但也正因为 dbt 的工程化属性变强了模型和配置的数量会快速膨胀。1.1 配置量增长的典型路径一个新项目通常从 10 个模型开始。早期大家很谨慎写模型时都会顺手在文件头部加上config在schema.yml里补上描述和测试。数据仓库成本不高模型之间的依赖也不复杂配置问题几乎不会被讨论。半年后模型到了 80 个。staging、marts、metrics层层展开不同人负责不同模块。这时你会看到有人把所有模型都默认设成view被 20 个下游模型反复引用每次查询都触发一段复杂视图的计算有人为了性能把模型全设成table但其中一批表几乎没有下游引用纯属让调度链路白跑增量模型有的写了unique_key有的没写报表数据重复后排查半天才发现是配置缺失团队内部对schema的定义理解不一生产库里出现多种命名风格数据权限和成本治理变得困难。这些问题不是靠“提醒大家注意”就能解决的。人肉检查在模型数量小时有效模型多了以后效率低、容易漏、也没有历史记录。1.2 配置问题为什么比 SQL 问题更隐蔽SQL 写错通常会直接运行失败或者结果明显不符合预期问题暴露得快。配置问题则不同它是“缓慢变质”的视图变成大查询瓶颈时你看到的是某个模型查询变慢但不会立刻想到是物化策略选错了增量模型缺少unique_key时重复数据是累积出来的等到业务方报告数据不对已经很难清洗full_refresh被无意触发时会直接重建整张表生产环境下可能导致一段时间内数据不可用表被误建在publicschema 下权限模型被绕过安全审计时才暴露。配置问题的共同点是它们不会让任务立刻失败但会在运行成本、数据质量、可维护性三个维度上持续产生负面影响。这正是配置顾问存在的前提。1.3 配置顾问提供的价值配置顾问是一种静态分析工具。它扫描 dbt 项目中的 YAML 配置、SQL 模型头部、依赖关系把“写代码时就知道不对劲”的配置提前发现并把结果以明确规则的形式反馈给团队。核心价值有三个可解释每条建议都对应具体规则例如“增量模型必须配置unique_key”而不是泛泛的“性能不佳”。可自动化可以放在 pre-commit、CI、MR pipeline 中配置问题在合并前就被拦截。可积累规则集可以随团队认知升级持续补充形成项目专属的数据工程规范。需要强调的是配置顾问不是替代dbt test。dbt test关注“运行出来的数据是否符合预期”配置顾问关注“项目配置本身是否健康”。两者互补缺一不可。2. dbt 配置到底在管什么要理解 OptiPipe 这类工具先把 dbt 里最关键的配置项拆开看一遍。这不是基础扫盲而是因为后续规则和场景都建立在这些配置的语义上。2.1 物化策略view、table、incremental、ephemeral这是 dbt 最核心的配置。它的选择直接决定模型在数据仓库里的存储方式和每次运行时的计算开销。物化方式存储行为适合场景典型风险view不存储数据查询时实时计算轻量中间层、频繁被上层逻辑复用但计算成本低被大量下游模型反复扫描时查询变慢、费用失控table每次dbt run重建整张表语义明确、希望查询稳定的模型表结构大且没有下游引用时浪费存储和计算incremental首次全量构建后续只增量处理新数据大表、事实表、Append-only 或可去重场景缺少unique_key会导致重复数据增量逻辑写错时数据缺失ephemeral不物化只作为 CTE 被打包进下游多级中间层避免大量中间表落库使用过多会让下游模型 SQL 变得极长、调试困难一个常见的判断逻辑是如果模型只是中间过滤层考虑view如果模型是面向报表的核心宽表考虑table如果模型数据量大且每日新增较多考虑incremental。但在复杂项目中这样“大概判断”远远不够所以需要规则来避免明显不合理的组合。2.2 unique_key增量模型的数据质量底线incremental模型最重要的配套配置之一是unique_key。它决定了增量数据与目标表匹配时的去重依据。缺失unique_key即使 SQL 逻辑是对的重复执行或数据重复输入也会导致表中出现重复记录。值得注意的一个误区是unique_key并不保证“数据绝对不重复”它只保证在增量合并策略下旧数据和新数据能按这个键去重。若键本身有业务含义且随业务会变化还需要额外考虑updated_at或invalidate_hard_deletes等机制。但从配置治理角度看incremental模型不写unique_key基本都可以认定为规则违规。2.3 schema 与 custom schema数据资产的边界schema配置决定模型最终会落到数据仓库的哪个 database/schema 下。它涉及数据权限、成本归属、环境隔离。同一个 dbt 项目里如果不同模块 schema 命名不统一或者把非生产模型直接建到生产 schema运维和审计都会相当痛苦。很多团队默认使用dbt_project.yml里的schema配置少数模型单独覆盖。合理做法是staging 层统一在stgschemamarts 层统一在martsschema 或面向业务的 custom schema。如果模型 A 属于 marts却配置到rawschema这通常不是有意为之。2.4 tags、docs、tests可观测性与协作配置dbt 配置不止影响性能也影响协作。tags用于资源分组和调度策略。没有 tags 的项目后期想做按模块过滤、限时执行会很麻烦。docs即模型和列的描述问题不在多与少而是需要一致。没有描述的关键模型新人接手时会把它当黑盒。tests是数据质量检查属于 dbt 项目非常重要的一部分但它验证的是“数据结果”不是“配置是否正确”。配置顾问要盯的就是这些配置之间的一致性例如配置了incremental却没有unique_key、配置了table却没有下游引用、模型明明在 marts 层却缺少描述和测试。3. 什么是 rule-based config advisor“rule-based” 这个词容易被误解为“很死板”。实际上对配置治理场景来说rule-based 恰恰是合适的选择。3.1 为什么是“规则”而不是自动优化器一条配置建议可以来自两个方向数据驱动的成本优化或者经验驱动的规则检查。数据驱动优化很像数据库查询优化器。它需要采集每个模型的实际运行时间、扫描行数、存储消耗、查询热度然后根据历史行为给出建议。这确实很强大但实现成本高而且对 dbt 项目来说很难做到跨平台统一。不同的数据仓库Snowflake、BigQuery、DuckDB、PostgreSQL采集口径不同权限也不同一上来做自动化成本优化很多团队做不到。规则驱动则是另一条路。它不依赖历史运行数据只对配置本身做静态检查。例如“incremental模型必须包含unique_key”“table且没有下游引用的模型高概率是死模型”“ref()指向不存在的模型应当立即拦截”这些规则并不需要跑一次dbt run也不需要采集运行指标。只要项目文件存在规则就能在秒级内给出结论。从工程成本角度看这是一种更低门槛、更可落地的治理方式。OptiPipe 在标题里使用的是rule-based config advisor这个定位很准确它并不是要替代你的人工判断而是把你脑中那些“应该这样配置”的经验沉淀成可执行、可审查的规则。3.2 从一个熟悉的类比理解它如果你写过前端代码会发现 OptiPipe 对 dbt 的作用和 ESLint 对 JavaScript 的作用很像。ESLint 不会帮你写业务逻辑也不会替你做性能调优它只负责在代码提交之前把明显不符合团队规范的写法找出来。dbt 项目的“代码规范”往往散落在团队口口相传里。OptiPipe 的价值是把这些口口相传变成项目文件中的规则集。它让“配置评审”不再依赖某个资深成员的注意力而是变成每次提交时自动执行的一道关卡。3.3 规则系统解决的三个核心问题配置一致性多人协作时统一物化策略、schema、tags 的写法。配置风险提前发现会导致重复数据、全量重建、权限错乱的高风险配置。资源浪费发现长期无人引用的物化表、明显超出必要粒度的full_refresh等。同时规则系统也自带边界它不能理解业务意图。某个模型配置为table但当前没有下游引用可能只是业务方正在开发下一阶段功能。所以配置顾问给出的建议是“提醒”团队需要根据上下文决策。4. OptiPipe 的核心工作机制从项目定位可以推断OptiPipe 的工作机制应该遵循静态分析工具的标准流程解析、建模、匹配规则、输出报告。这个流程并不神秘我们完全可以用一个最小 Python 脚本模拟出来。4.1 输入dbt 项目目录dbt 项目的配置分散在多个位置dbt_project.yml全局配置、profile 指向、模型目录级配置。models/**/*.sql模型 SQL文件顶部常带有config()块。models/**/*.yml或schema.yml模型名称、描述、列级描述和测试。OptiPipe 需要把这些不同来源的信息统一读取并拼装成“模型”的内存对象。一个模型至少要记录名称、文件路径、物化类型、unique_key、下游引用列表、被哪些模型引用。4.2 核心数据结构下面用 Python 概念展示一个合理的模型结构dataclass class DbtModel: name: str path: Path materialized: str unique_key: str | None refs: set[str] field(default_factoryset) referenced_by: set[str] field(default_factoryset)看到这里你可能已经明白配置顾问做的是“读配置、建 DAG、跑规则”。真正复杂的不是数据结构而是规则的可解释性。4.3 规则引擎与输出规则引擎本质上是一组纯函数输入模型集合输出违规建议。每条建议包含严重级别、规则 ID、模型路径和说明。建议的输出可以有两种消费方式人工查看在 MR 页面上提醒开发者关注。机器判断在 CI 中遇到ERROR级别规则时阻止合并。一个建议示例[ERROR] OPT-DBT-001 | models/marts/orders_summary.sql: 增量模型必须配置 unique_key否则重复执行会产生重复数据。这种输出格式和测试框架类似开发者可以迅速定位问题文件。5. 动手实现一个最小 dbt 配置检查器下面我不依赖 OptiPipe 的内部实现而是实现一个符合同样设计思路的最小示例。它可以跑在你的 dbt 项目上帮助你理解这类工具的规则和输出。理解了它再看 OptiPipe 的文档和输出会非常自然。5.1 准备环境演示脚本使用 Python 3.10 和 PyYAML。python -m venv .venv source .venv/bin/activate pip install PyYAML如果你不想创建虚拟环境直接全局安装pyyaml也可以。这里不影响后续理解。5.2 项目目录示例假设你有这样一个 dbt 项目dbt_project/ ├── dbt_project.yml └── models/ ├── staging/ │ ├── stg_orders.sql │ ├── stg_customers.sql │ └── schema.yml └── marts/ ├── orders_summary.sql └── customer_stats.sql其中部分模型配置有问题比如orders_summary是incremental但没有unique_keycustomer_stats是table但没有任何下游引用。5.3 编写最小规则检查器创建一个optipipe_demo.py文件内容如下。#!/usr/bin/env python3 optipipe_demo.py 一个极简的 dbt 配置规则检查器用于演示 rule-based config advisor 的设计思路。 真正使用时请以目标项目如 OptiPipe的官方文档为准。 import os import re import sys from dataclasses import dataclass, field from pathlib import Path from typing import Optional import yaml # 从 SQL 文件头部提取 config(config(...)) CONFIG_BLOCK_RE re.compile( rconfig\(\s*(.*?)\s*\), re.DOTALL ) MATERIALIZED_RE re.compile( rmaterialized\s*\s*[\]([^\])[\] ) UNIQUE_KEY_RE re.compile( runique_key\s*\s*[\]([^\])[\] ) REF_RE re.compile(rref\(\s*[\]([^\])[\]\s*\)) dataclass class RuleViolation: severity: str # ERROR / WARNING / INFO rule_id: str model_path: str message: str def format(self) - str: return f[{self.severity}] {self.rule_id} | {self.model_path}: {self.message} dataclass class DbtModel: name: str path: Path materialized: str view unique_key: Optional[str] None refs: set field(default_factoryset) referenced_by: set field(default_factoryset) def parse_sql_config(sql_text: str) - dict: 从 SQL 文件头部的 config() 中解析基本配置。 result {} match CONFIG_BLOCK_RE.search(sql_text) if not match: return result config_body match.group(1) mat_m MATERIALIZED_RE.search(config_body) uk_m UNIQUE_KEY_RE.search(config_body) if mat_m: result[materialized] mat_m.group(1) if uk_m: result[unique_key] uk_m.group(1) return result def parse_sql_refs(sql_text: str) - set: 解析 SQL 文件中对其他 dbt 模型的 ref() 引用。 return set(REF_RE.findall(sql_text)) def load_dbt_models(project_root: Path) - dict: 加载项目下所有 .sql 模型并构建引用关系。 models {} sql_files list(project_root.rglob(*.sql)) for sql_file in sql_files: sql_text sql_file.read_text(encodingutf-8) model DbtModel( namesql_file.stem, pathsql_file.relative_to(project_root), ) config parse_sql_config(sql_text) refs parse_sql_refs(sql_text) model.materialized config.get(materialized, view) model.unique_key config.get(unique_key) model.refs refs models[model.name] model # 构建反向引用图 for name, model in models.items(): for ref_name in model.refs: if ref_name in models: models[ref_name].referenced_by.add(name) return models def apply_rules(models: dict) - list: 根据规则集检查模型返回违规列表。 violations [] for model in models.values(): # 规则一incremental 模型必须有 unique_key if model.materialized incremental and not model.unique_key: violations.append(RuleViolation( severityERROR, rule_idOPT-DBT-001, model_pathstr(model.path), message增量模型必须配置 unique_key否则重复执行会产生重复数据。, )) # 规则二table 模型不能完全没有下游引用 if model.materialized table and not model.referenced_by: violations.append(RuleViolation( severityWARNING, rule_idOPT-DBT-002, model_pathstr(model.path), message该模型被物化为 table但没有下游模型引用建议确认是否仍需要保留。, )) # 规则三model 不应引用不存在模型 for ref_name in model.refs: if ref_name not in models: violations.append(RuleViolation( severityERROR, rule_idOPT-DBT-003, model_pathstr(model.path), messagefref() 引用了不存在的模型: {ref_name}, )) return violations def main(): project_root Path(os.environ.get(DBT_PROJECT_ROOT, .)) if not (project_root / dbt_project.yml).exists(): print(错误当前目录不是 dbt 项目根目录请通过 DBT_PROJECT_ROOT 指定。) sys.exit(2) models load_dbt_models(project_root) violations apply_rules(models) for violation in violations: print(violation.format()) print(f\n共检查 {len(models)} 个模型发现 {len(violations)} 条配置建议。) if any(v.severity ERROR for v in violations): sys.exit(1) if __name__ __main__: main()5.4 运行与验证在 dbt 项目根目录执行python optipipe_demo.py或者指定项目目录DBT_PROJECT_ROOT/path/to/dbt_project python optipipe_demo.py预期输出[ERROR] OPT-DBT-001 | models/marts/orders_summary.sql: 增量模型必须配置 unique_key否则重复执行会产生重复数据。 [WARNING] OPT-DBT-002 | models/marts/customer_stats.sql: 该模型被物化为 table但没有下游模型引用建议确认是否仍需要保留。 共检查 4 个模型发现 2 条配置建议。如果出现ERROR级别规则脚本退出码为 1可以在 CI 的 shell 任务中直接作为失败判断如果只有WARNING退出码为 0只做提醒。这个脚本虽然简陋但它已经覆盖了工具的核心路径解析配置、构建依赖、跑规则、输出可消费的结果。你完全可以把它扩展到更多规则比如检查schema命名是否规范、检查docs缺失、检查是否存在ref循环依赖。6. 把配置顾问接入 dbt 工程流程配置顾问这类工具好用的前提是“接入得早、跑得勤”。如果只是在新项目启动时手动跑一次价值会大打折扣。下面介绍几种常见接入位置。6.1 pre-commit提交前快速拦截如果你用了pre-commit可以在本地提交前先跑配置检查。这个阶段适合跑“秒级”规则例如ref()是否存在、增量模型是否有unique_key。本地提前发现问题能减少一次 CI 往返。.pre-commit-config.yaml中增加自定义本地脚本是一个常见做法针对 Python 脚本可以这样配置repos: - repo: local hooks: - id: optipipe-demo name: OptiPipe demo check entry: python optipipe_demo.py language: system pass_filenames: false注意这里只是示例思路。真正的 OptiPipe 接入命令请以其官方文档为准。6.2 CI / MR Pipeline合并前强制规范CI 是最推荐的接入位置。它的好处是团队所有成员的提交都会经过同一道检查规则执行历史可以被保留。典型流水线顺序dbt deps拉取依赖包。dbt parse生成 manifest。运行配置顾问检查dbt_project.yml、模型 SQL 和属性 YAML。如有ERROR级别问题流水线失败阻止合并。通过后再执行dbt build --select state:modified或完整dbt build。配置检查放在dbt parse之后、正式dbt run之前可以省下大量失败的运行成本。试想如果某条配置错误会导致full_refresh重建大表还没等运行完就发现问题显然比等在仓库里跑完再报警要强。6.3 渐进式治理先 Warning 再 Error接入配置顾问最容易犯的错是一上来把所有规则都设为ERROR。老项目通常积攒了大量历史问题如果一次性全拦截团队会非常痛苦甚至会绕开检查。更稳妥的策略是第一周先以WARNING级别扫描生成一份项目健康报告。团队 review 每条规则确认合理后针对新代码生效。对存量问题建立基线允许项目在期限内逐步修复。基线清零后把某条规则正式升级为ERROR。这种渐进式治理逻辑和代码规范 lint 工具的落地思路一致。6.4 和 dbt test 的分工很多团队会问有了配置顾问还需要dbt test吗答案是两者完全不同。dbt test是运行期检查它要真正执行 SQL验证数据是否满足字段约束、业务规则。配置顾问是静态检查它只分析项目配置和依赖图不运行 SQL。举个典型例子unique测试运行失败说明表里确实有重复值而配置顾问检查unique_key是在“还没有产生重复值之前”先发现风险。前者是“事后验证”后者是“事前预防”。两者配合才是完整的质量保障。6.5 定制团队专属规则每个团队的 dbt 规范不同。例如金融团队可能要求所有核心表必须开启incremental而不是table。数据分析平台团队可能要求所有模型都必须在schema.yml中写description。成本敏感型业务可能要求禁止对超大表每日full_refresh。OptiPipe 这类工具值得投入的地方就是它能让你把团队规范固化成规则文件。规则不是写给人“提醒”的而是让机器在每次提交时自动检查的。实践中可以把规则集文件放到rules/目录并用语义化的 ID 命名便于 reviewrules/ ├── materialization.yaml ├── unique_key.yaml ├── schema_naming.yaml ├── docs_coverage.yaml └── dag_structure.yaml每个规则文件内部建议包含规则 ID、级别、适用对象、检查逻辑、修复建议。这样的规则文件本身就是团队数据工程规范的“可运行版本”。7. 常见问题与排查方法配置顾问接入过程中会遇到一些典型问题。下面以排查表格的形式整理方便直接对照处理。问题现象可能原因排查方式解决方案大量模型被误报为“无下游引用”规则没有识别ref()动态拼写或 macro 调用检查规则引擎是否只做正则匹配未解析 manifest改用dbt parse生成的manifest.json作为引用事实来源复杂 Jinja 配置解析失败config()块中包含var()、target()等函数查看解析器的 AST 能力是否足够使用 dbt 的官方 manifest 或限制静态规则只检查可解析部分incremental模型没有unique_key但设计上确实不需要使用了deleteinsert、snapshot等特殊策略查看模型 SQL 和增量策略在规则白名单中按模型名或 tags 排除CI 中配置检查失败阻塞了发布历史存量问题太多规则一次性全开查看失败规则的严重级别分布先降为WARNING建立基线逐步修复规则检查和dbt test结果看起来重叠两者都检查数据唯一性或模型依赖查看具体规则和执行时机明确分工配置顾问跑静态dbt test跑数据检查速度慢大型 monorepo 无法接受全项目扫描且每次重新解析所有文件观察扫描耗时和文件数量只扫描变更模型或基于 manifest 做增量扫描配置顾问报告太多WARNING团队麻木规则没有按严重级别分级检查规则配置中的级别字段将规则按 severity 划分ERROR控制总量WARNING作为提醒在这些问题中“基于 manifest 解析”是最重要的改进方向。因为 dbt 官方提供了manifest.json里面包含完整的模型列表、依赖关系、配置项比自己写正则解析可靠得多。规则引擎如果只做纯字符串解析很容易被复杂 Jinja 和宏调用误导。另一个容易被忽略的问题是规则检查结束后如果工具只给出“有问题”的结论却没有给出“怎么改”的建议团队的修复成本会很高。好的配置顾问一定要输出可操作的修复建议至少应指出目标配置项和推荐值。例如[WARNING] OPT-DBT-002 | models/marts/customer_stats.sql: 该模型被物化为 table但没有下游模型引用。 建议如果该模型暂时不服务报表可改为 view或补充说明后加入白名单。这种带“为什么”和“怎么做”的提示才能真正帮助开发者决策。8. dbt 配置治理的最佳实践结合 OptiPipe 的定位和配置顾问的通用经验下面给出几条可直接落地的建议。8.1 先在项目里建立配置基线不要期待一个刚接手的老项目能瞬间达到 100% 配置规范。先把当前所有配置扫描一遍把结果保存为基线确认哪些是历史包袱哪些是真实风险。然后从风险最高的问题开始修。常见优先级排序是会导致数据重复的配置例如增量模型缺unique_key。会导致数据丢失或重建风险的操作例如意外的full_refresh。会导致权限问题的 schema 配置。会导致运行资源浪费的物化策略。影响可维护性的描述、tags 缺失。8.2 规则要有 ID、级别和负责人团队自定义规则时建议每条规则都有唯一 ID 和明确负责人。例如OPT-DBT-001由数据平台组负责OPT-MARKET-002由业务分析组负责。这样当规则产生误报或需要调整时团队知道找谁。规则文件本身也要走代码评审。规则变更会影响整个项目的审查标准不能由一个人默默改完就提交。8.3 配置检查要放在 dbt run 之前前面提到过配置检查的黄金位置是在dbt build/dbt run之前。这样可以避免因配置错误导致的任务失败、全表重建和资源浪费。如果你用了dbt Cloud可以考虑在 CI job 的最前面加入一道“配置预检”而不是直接进入调度。8.4 规则要分层不要一刀切按作用范围分层全局规则适用于所有模型例如ref()必须有效。层内规则只针对 staging/marts 层的规则例如 marts 层必须配置描述。标签规则只针对带某类 tags 的模型例如critical标签模型必须启用增量。分层规则能避免团队因规则冲突而陷入无休止的争论。8.5 定期 review 规则集配置治理不是一次性的。随着数据仓库演进、业务复杂度上升团队会不断遇到新的配置问题。建议每季度 review 一次规则集把近期踩过的坑固化成新规则把不再适用的规则删除。规则集的演进其实就是团队数据工程认知的演进。9. 总结与后续学习方向OptiPipe 给 dbt 生态带来的一个重要启发是dbt 项目的工程质量不应该只靠dbt test来兜底配置本身也应该成为被审查、被治理的一等公民。基于规则的配置顾问用相对低的成本解决了“配置不一致、高风险配置扩散、资源浪费”这三类问题而且因为规则透明、可解释非常适合工程团队长期维护。如果你准备在自己的 dbt 项目中实践可以参考下面的路径先跑一个最小规则检查器理清项目里有哪些明显配置风险。把高风险问题先修掉例如补齐增量模型的unique_key。把配置顾问接入 CI先以WARNING级别运行一周。与团队一起 review 规则挑选最必要的规则升级为ERROR。持续沉淀自定义规则把团队踩过的坑变成自动化检查。值得继续深入的方向包括如何基于 dbt 官方的manifest.json做更可靠的解析如何在增量模型上进一步验证unique_key和增删改策略的配合如何把配置顾问的结论与数据血缘、成本数据打通生成更全面的模型健康报告。配置治理这件事听起来不像写 SQL 那么有成就感但它决定了 dbt 项目在半年后是依然清爽还是变成谁也改不动的大泥球。越早把规则沉淀成工具后续的维护成本就越低。
返回列表