第一次接触数据仓库,很多人都会有一种感觉: 每个字都认识,连起来完全不知道在说什么。 "先落 ODS,再清洗到 DWD。" "这个指标直接从 DWS 聚合。" "这张表粒度不对,先别做宽表。" "昨天 CDC 断了,先补数,再重跑下游 DAG。" "这个指标口径还没统一,ADS 先别出。" 听起来像中文,又像一套行业暗号。 其实数仓里的大多数术语,都围绕几个核心问题展开: 数据从哪里来?放在哪里?怎么加工?怎么组织?怎么算指标?怎么保证每天稳定产出? 很多新人觉得数仓难,往往是因为一开始就背 ODS、DWD、DWS、CDC、DAG 这些缩写,却没有先建立完整的数据链路。 如果你正在系统补数据仓库、数据集成、数据治理这块的知识,建议结合真实的数据流转过程来看:一条订单数据从业务系统产生,经过采集、清洗、建模、汇总,最后进入报表和分析应用。把这条路径串起来以后,很多所谓"黑话"自然就能找到自己的位置。
下面就把数仓里最常见、也最容易把新人绕晕的一批术语一次讲清楚。 一、ODS、DWD、DWS、ADS:数仓为什么要分这么多层? 数仓新人最先碰到的一组缩写,基本就是: ODS、DWD、DWS、ADS。 可以先记住一个规律: 数据越往后走,业务含义越明确;越靠前,越接近源系统。 ODS:原始数据层 ODS 可以理解成业务数据进入数仓后的第一站。 订单系统、ERP、CRM、WMS 里的数据先同步进来,并尽量保留原始状态。 这一层首先要保证两个问题: 数据有没有进全?后面还能不能追溯到源头? 如果源系统里有100万条订单,ODS 最终只有98万条,后面的建模、指标、报表都会跟着失真。 所以 ODS 经常和这些词一起出现: 全量同步; 增量同步; CDC; 初始化; 分区; 数据落地。 企业系统越来越多以后,接入方式也很容易越来越碎。 Oracle 一套脚本,MySQL 一套脚本,API 再单独开发,文件又走另一套流程。系统新增一次,采集链路就要跟着扩一轮。 实际建设时,FineDataLink 5.0 可以把数据库、API、文件等不同来源放到同一套数据连接和同步流程中。首次入仓时做全量初始化,后续根据更新频率继续跑增量;时效要求更高的数据,再进入实时链路。这样新增数据源时,前面的接入规则和任务管理也更容易保持统一。
DWD:明细数据层 ODS 解决了"数据进来"的问题,接下来还要处理数据质量和业务表达。 源系统中经常会出现: 字段命名不同、状态编码不同、时间格式不同、重复记录、异常值、主键冲突等情况。 DWD 会对这些数据做清洗、标准化和业务化处理。 比如源系统中: status=1 到了 DWD,可能被统一解释成: 待支付。 DWD 一般保留较细的业务粒度,因此后面的很多分析都要从这里继续往上加工。 DWS:汇总数据层 DWD 保存的是细粒度业务事实。 到了 DWS,会开始沉淀一些高频复用的汇总结果: 用户近30天消费金额; 商品日销量; 门店月收入; 客户累计订单数。 如果每张报表都从最底层明细重新计算一遍,同一套逻辑会被反复开发。 所以 DWS 最重要的关键词就是: 复用。 ADS:应用数据层 ADS 更靠近具体业务场景。 经营驾驶舱需要什么数据,财务分析需要什么数据,营销系统需要什么数据,都可以在这一层继续组织。 所以这四层可以简单记成: ODS 接原始数据,DWD 整理明细,DWS 沉淀公共汇总,ADS 面向具体应用。 实际项目里不一定四层全部存在,有些企业还会合并其中几层。 分几层没有统一答案,关键是每一层职责要稳定。
二、粒度、事实表、维度表:数仓建模到底在建什么? 数据进入数仓以后,马上会碰到第二批高频黑话: 粒度、事实表、维度表、星型模型。 其中最值得先理解的是: 粒度 粒度回答一个问题: 一行数据究竟代表什么? 比如订单表里: 一行代表一个订单, 和一行代表一个订单里的某件商品, 对应的是两种完全不同的粒度。 一个订单买了5件商品。 订单粒度可能只有1行; 订单商品粒度则可能有5行。 如果粒度没有先确定,就直接计算订单量、商品销量、销售金额,很容易发生重复统计。 所以设计事实表之前,最好先写清一句话: 这张表中的一行,代表哪一个最小业务事件? 事实表 事实表记录业务活动。 比如: 订单、支付、退款、入库、出库、点击。 里面通常会放金额、数量、成本、时长等可计算字段。
维度表 维度负责描述业务事实。 一笔订单发生以后,我们可能继续分析: 谁买的? 买了什么? 来自哪个地区? 通过哪个渠道? 在哪家门店? 这些客户、商品、地区、渠道、门店,就是典型的分析维度。 于是最基础的数仓模型关系就形成了: 事实记录业务发生,维度负责描述业务背景。 事实表放在中间,周围连接多张维度表,就形成了常说的: 星型模型。 如果维度继续向外拆分,还会出现: 雪花模型。 建模最终追求的是让业务事实有稳定结构,让客户、商品、组织、地区等公共维度能够持续复用。
三、全量、增量、CDC:数据到底怎么进入数仓? 做数据同步时,最常见的一组词就是: 全量、增量、CDC。 全量同步 逻辑很好理解: 把数据全部同步一遍。 源表100万条,就读取100万条。 数据量小时非常省心,但随着数据规模不断增加,每天全表扫描的成本会越来越高。 于是就有了: 增量同步 增量同步只处理上一次以后新增或者发生变化的数据。 最常见的做法,是根据更新时间判断: update_time > 上次同步时间 真正上线以后,麻烦往往出现在边界上。 刚好等于上次同步时间的数据算哪一批? 10点生成、10点05分才落库的数据会不会漏? 源端直接删除的数据怎么发现? 同步1000万条,跑到700万时中断,从什么位置继续? 所以增量同步真正考验的是: 如何准确识别变化范围,同时控制重复和遗漏。
CDC:Change Data Capture CDC 一般翻译成: 变更数据捕获。 它会围绕数据库发生的新增、修改、删除持续获取变化。 比如一条订单从: 未支付 → 已支付。 批量任务可能定时重新查询符合条件的数据;CDC 会更直接地关注这条记录发生了什么变化。 业务开始追求分钟级甚至秒级时效以后,实时链路的重要性就会上升。 到了这里,FineDataLink 5.0 中的实时任务、实时数据管道就能直接进入这条链路:源端发生变化后,数据持续进入同步过程,需要加工的数据继续做字段处理、过滤或转换,再写入下游数据库、数仓等目标端。 这时衡量数据链路的重点,也会从"每天有没有跑完"逐渐细化到: 源端变化产生后,多久能够到达下游。 这个时间差,就是实时数仓非常关键的指标之一。
四、ETL、ELT、T+1:数据加工为什么总在换位置? 数仓里还有一个绕不开的词: ETL。 三个字母分别代表: Extract:抽取; Transform:转换; Load:加载。 也就是: 抽取 → 转换 → 加载。
后来随着云数仓、MPP 数据库和计算平台能力增强,又出现了: ELT。 流程变成: Extract → Load → Transform。 也就是先把数据加载进去,再利用目标平台的计算能力完成处理。 ETL 和 ELT 的区别,核心落在一个问题上: 计算放在哪里完成更合理? 如果源端系统业务压力已经很大,就要减少复杂计算对生产系统的影响。 如果目标数仓拥有较强计算能力,数据也可以先加载,再集中加工。 这其实是一种架构取舍。 另外还有一个高频黑话: T+1 简单理解就是: 今天产生的数据,明天完整看到。 传统离线数仓经常在凌晨统一跑批: ODS → DWD → DWS → ADS。
整条任务链跑完以后,第二天早上再把结果交给业务。 而 T+0、小时级、分钟级、秒级,说的都是: 数据从产生到可使用,中间允许多长时间。 所以数仓设计时,时效要求一定要回到业务场景。 日报和实时风险监控,对数据延迟的要求完全不同。 时效越高,后面的计算、存储、运维和一致性处理都会更复杂。 五、宽表、指标口径、原子指标:为什么数仓越做越容易乱? 再往下就会碰到一个非常常见的词: 宽表。 所谓宽表,就是提前把分散在多张表里的字段关联起来。 比如一张订单宽表里,可能同时包含: 订单信息、客户信息、商品信息、渠道信息、门店信息。 分析人员查询起来会方便很多,不需要每次都重新关联十几张表。 问题也很容易在这里积累。 今天业务要增加一个字段。 明天运营再增加一个字段。 过半年,一张表可能有几百个字段,里面混着越来越多的业务规则。 所以宽表设计时要重点判断: 哪些字段和逻辑真的具有长期、稳定的复用价值? 继续往下,还会遇到一个更关键的概念:
指标口径 大家都说销售额。 但销售额到底指: 下单金额? 支付金额? 发货金额? 确认收货金额? 还是扣除退款后的净销售额? 如果定义不一致,同一家公司里完全可能同时出现三四个"销售额"。 因此很多数仓会继续建立指标体系: 原子指标、派生指标、复合指标。
原子指标对应比较基础的业务度量,比如: 支付金额。 增加时间、地区、组织等限定条件以后,可以形成: 本月华东区域支付金额。 再继续组合计算,就会出现: 客单价、毛利率、转化率等指标。 到了这一层,数仓已经开始沉淀企业内部对业务的共同解释。 而这些已经清洗、转换并统一规则的数据,后面还要持续流向不同应用。FineDataLink 5.0 可以把前面的数据处理链路继续串到目标端:加工后的结果按任务写入目标数据库或数仓,再供报表、分析平台以及其他业务应用使用。公共数据先在上游处理一次,下游再围绕统一结果展开,重复取数和重复加工也会随之减少。
数仓里真正需要长期沉淀的,除了表本身,还有: 加工规则、指标定义和公共数据逻辑。 六、DAG、依赖、补数、幂等、SLA:数仓真正难的是每天稳定跑 数仓规模小时,十几个任务很好管理。 等做到几百张表、几千个任务以后,新的问题就来了: 谁先跑? 谁后跑? 上游失败以后哪些任务要暂停? 历史数据出错以后怎么重新计算? 任务重跑会不会产生重复数据? 于是又出现了一批黑话。 DAG DAG 可以理解成: 任务之间的依赖关系图。 比如: ODS订单表完成 ↓ DWD订单明细运行 ↓ DWS销售汇总计算 ↓ ADS经营数据更新。 上游结果没有生成,下游任务就缺少正确输入。 这就是: 依赖。 补数 如果昨天的数据跑错,需要重新处理历史日期,通常就叫: 补数。
补数真正麻烦的地方在于: 下游是否要一起重新计算? 原来的结果要不要先清理? 累计指标会不会受到影响? 所以补数考验的是整条任务链的可重复执行能力。 幂等 幂等可以简单理解成: 同一个任务重复执行,最终结果仍然保持一致。 昨天销售额是100万。 任务失败以后重跑一次,结果直接变成200万,这就说明任务在重复写入方面存在问题。 稳定的数据任务需要提前考虑失败、重试、补跑这些异常场景。 SLA SLA 描述的是: 数据最晚什么时候应该产出。 比如经营日报要求每天早上8点前更新。 任务上午10点才跑成功,虽然最终有结果,但已经影响业务使用。 所以数仓运维既要看: 任务有没有成功, 也要看: 结果有没有按时到达。 当任务数量越来越多以后,数据开发很大一部分工作都会落到调度和依赖管理上。 FineDataLink 5.0 里的同步任务、数据转换、SQL处理和调度可以继续按上下游关系组织起来。比如先完成 ODS 数据同步,再触发 DWD 清洗,DWD 成功后继续执行后面的汇总任务。任务之间的先后关系明确下来以后,出问题时也更容易沿着链路定位具体环节。
一个数仓项目真正上线以后,每天面对的往往就是这些问题: 数据有没有按时到? 哪一个任务失败了? 影响了哪些下游? 要不要补跑? 补跑会不会重复? 所以真正做过数仓的人,会越来越重视: 调度、重试、补数、日志、血缘、质量监控和 SLA。 架构设计只是第一步。 最后还要把整套数据链路长期跑稳。 七、最后:把黑话串成一条数据链路 看到这里,其实数仓里的黑话已经可以重新归成几类。 数据放哪里: ODS、DWD、DWS、ADS。 数据怎么组织: 粒度、事实表、维度表、星型模型、宽表。 数据怎么进来: 全量、增量、CDC、实时同步。 数据怎么加工: ETL、ELT、SQL、聚合。 数据怎么算: 口径、原子指标、派生指标、复合指标。 数据怎么稳定生产: DAG、依赖、调度、补数、幂等、SLA、血缘。
真正学数仓时,可以把这些词全部放进同一条链路里理解: 业务系统产生数据 ↓ 通过全量、增量或者 CDC 进入 ODS ↓ 清洗、统一以后形成 DWD ↓ 公共统计和聚合逻辑沉淀到 DWS ↓ 针对具体使用场景形成 ADS ↓ 最后交付给报表、分析平台和业务系统。 与此同时,建模决定数据怎么组织,指标体系决定数字怎么解释,调度和依赖保证任务按照顺序运行,质量和血缘负责发现问题、追踪来源。 所以以后再听到一句: "ODS 的 CDC 昨晚断了,DWD 没产完,下游 DWS 依赖阻塞,ADS 指标已经超 SLA,需要先补数再重跑。" 你能够马上拆出来: 源端同步出了问题 → 明细层没有正常产出 → 下游汇总被阻塞 → 最终应用数据延迟。 这时候,ODS、DWD、CDC、DAG、SLA 就已经不是几个需要死记硬背的缩写了。 它们共同描述的,是一条完整的数据生产链路。 能把这些词放回真实链路里理解,才算真正开始入门数据仓库。