数据仓库从入门到实践:ETL、分层与维度建模

发布时间:2026/10/24 10:22:14
数据仓库从入门到实践:ETL、分层与维度建模

简介:这是一份数据仓库工程师面试题及知识点汇编,以 docx 文档形式呈现,面向准备数据仓库岗位面试的开发者、数据工程师及需要系统梳理 ETL 与数仓分层知识的从业者。文档从数据仓库的定位和四大特点讲起,明确主题性、集成性、稳定性、时变性各代表的含义,接着梳理 ETL 全流程,包括抽取、转换、加载,以及执行过程日志、错误日志、总体日志的分类和出错时的警告发送方式。针对 STG、ODS、DW、Presentation 四层模型,内容逐一说明每层与源系统的关系、增量或全量策略、审计列设计,并展开 CDC 策略、mapping 文档、物理模型、数据清洗、规范化、维度表提交等实操要点,能够帮助读者快速搭建面试答题框架。资源仅 1 个 docx 文件,整体约 31KB,内容精炼却覆盖核心考点,便于随时查阅。目前已有 1709 人学习下载,适合作为面试前集中复习和查漏补缺的实用资料。

1. 数据仓库到底是什么:一间只进不出的“历史档案馆”

如果你第一次听到“数据仓库工程师”这个职位,脑子里大概率会冒出一个问题:数据不都放在数据库里吗,为什么还要专门建一个仓库?这个疑问很正常,因为“数据仓库”这个名字本身就有点误导——它不像一个存放货物的仓库,更像一个只进不出的“历史档案馆”。

通俗地说,数据仓库(Data Warehouse,缩写是 DW)就是一座专门用来“存历史、做分析”的数据集合。它把企业里散落在各个业务系统(订单系统、用户系统、物流系统等)的数据,统一抽取进来,清洗干净、整理好,然后长期保存下来,供业务方做数据分析、数据挖掘和数据报表。业务数据库解决的是“当下这笔交易怎么记”,数据仓库解决的是“过去半年我们的生意到底怎么样”。这是两种完全不同的事,也是你理解后面所有概念的地基。如果你正在准备数据仓库相关的面试,先把这一层想清楚,后面才不容易被 ETL、分层模型这些术语绕晕。

2. 为什么业务数据库不够用:收银台和档案馆的区别

2.1 业务系统要“快”,数据仓库要“全”

你可以把业务系统想象成超市的收银台:它每天处理的是“扫码、结账、打印小票”这类高频率操作,每一笔都要快、要准,不能出错,也不允许系统因为要统计历史而变慢。这种面向日常交易的数据库,在数据仓库领域有个对应的说法——它服务的是“当下”。

但问题是,当老板说“把去年所有门店的退货率按季度拉出来看看”时,收银台就傻眼了。业务库里数据是有的,但分散在几十张表里,字段口径还不统一,更关键的是,很多历史数据可能已经被覆盖或者删除。如果直接在业务库上跑复杂的统计查询,轻则慢得离谱,重则影响前台交易——这在线上系统里是不可接受的。

数据仓库存在的价值,就是把这些“算账的活儿”从业务系统里彻底剥离出来。它把散落在各个源系统里的数据汇集到一处,按照分析的需要重新组织,专门为“读”服务。业务库担心写入性能,数据仓库关心查询分析能力;业务库只要当前状态,数据仓库要保存历史快照。这就是数据仓库存在的第一个理由。

2.2 ETL:把数据搬进仓库的“搬家流水线”

数据仓库里的数据不是凭空出现的。从各个业务系统到数据仓库,要经过一条固定的流水线,这就是 ETL。ETL 是 Extract-Transform-Load 的缩写,对应三步:

  • Extract(数据抽取):从各个数据源把数据读出来。数据源可能是不同类型的数据库,也可能是 Excel 文件,甚至是一份手工维护的表格。
  • Transform(数据转换):把原始数据转换成你想要的格式和维度。比如性别字段,A 系统存的是 0 和 1,B 系统存的是 man 和 woman,得统一成 m 和 f;再比如把缺了供应商名称的脏数据过滤掉、把重复记录去掉,都属于转换环节。
  • Load(数据加载):把处理好的数据加载到目标位置,也就是数据仓库里。

打个比方,ETL 就像搬家:先把旧家里所有东西搬出来(Extract),然后按照新家的布局分门别类整理好、该扔的扔、该重新打包的打包(Transform),最后再一件件搬进新家摆好(Load)。数据仓库里的数据质量好不好,很大程度上取决于 ETL 写得好不好,这也是数据仓库工程师日常最主要的工作之一。

2.3 数据仓库的四个性格:主题性、集成性、稳定性、时变性

理解了 ETL,再看数据仓库的四个核心特点,就会顺很多。这四个特点基本是所有面试题里“数据仓库是什么”的标准答案:

第一,主题性。传统业务数据库通常是按项目或功能来组织的,比如订单库管订单、库存库管库存。数据仓库不一样,它围绕业务主题来组织数据。比如“客户”是一个主题,那数据仓库就会把客户的基本信息、订单记录、售后记录、投诉记录全部整合在一起,形成一个围绕“客户”的完整视角——这是传统业务库做不到的,因为数据散落在各系统里。

第二,集成性。数据仓库里的数据来自多个数据源,来源五花八门,必须经过抽取、清洗、转换(也就是 ETL)才能整合成一套统一的数据集合。这一步解决的是“不同系统对同一个事物的叫法不一致”的问题。比如同一个供应商,在结算系统里叫 XX0001,在另一个系统里叫 YY0001,集成性就是要把这些统一成一个编码。

第三,稳定性。数据仓库里保存的数据是一系列历史快照,一旦入库,不允许被修改。用户只能通过分析工具来做查询和分析,不能在仓库里改来改去。想想档案馆的规则:档案入库之后,你只能查阅,不能拿笔在上面改字。

第四,时变性。数据仓库会定期接收新的集成数据,反映出最新的数据变化。也就是说,仓库里的数据会随时间推移不断追加新内容——比如每天晚上定时同步昨天的订单数据。注意,“稳定”和“时变”并不矛盾:稳定说的是已入库的历史不能改,时变说的是仓库会持续接收新数据,一个是管存量,一个是管增量,这个点面试里经常有人答不清楚。

3. 数据仓库里的四层楼:STG、ODS、DW、DM

3.1 STG 层:源系统数据的“临时卸货区”

传统数据仓库一般分为四层模型,从下往上数,第一层叫 STG(Staging)层,你可以把它理解成快递分拣中心的“卸货区”。所有从外面运来的包裹(源系统数据)先堆在这里,不拆包、不分类,只是先落地。

STG 层有几个典型特征:它的表结构和源系统保持一致,支持增量抽取或全量抽取,不做数据转换,只添加审计列。什么叫审计列?就是额外加上的一些管理字段,比如源系统名称、源表名称、加载时间、加载方式,方便之后排查数据问题。因为 STG 层只是临时存放,物理模型可以去掉主键、索引、默认值这些约束,字段长度也可以统一扩宽,避免源系统和目标系统的数据库类型不同导致长度不够。

STG 层的作用主要有四个:一是减轻源系统的压力——数据先抽到 STG,后续处理不再反复读源库;二是数据备份,支持重跑——万一某次任务失败,可以从 STG 恢复;三是便于数据问题跟踪——出了问题知道数据是什么时候、从哪个源表进来的;四是做数据质量检查。

开发 STG 层的步骤大致是:先确定 CDC 策略(也就是增量变更捕获策略,根据源系统的数据变化情况选择合适的方式),然后设计 mapping 文档(字段映射关系),再设计物理模型、抽取数据、加载数据。STG 层一般只保留 7 天或一个月的数据,因为它是临时区,不需要永久保存。

下面是一个简单的 STG 表设计示例:

-- STG层订单表:结构与源系统一致,只加审计列 CREATE TABLE stg_order ( order_id VARCHAR(32), -- 源系统订单号 customer_id VARCHAR(32), -- 客户编号 order_amount DECIMAL(10,2), -- 订单金额 order_status VARCHAR(10), -- 订单状态 create_time TIMESTAMP, -- 源系统创建时间 src_system VARCHAR(50), -- 审计列:来源系统 src_table VARCHAR(50), -- 审计列:来源表名 load_time TIMESTAMP, -- 审计列:加载时间 load_type VARCHAR(10) -- 审计列:加载方式(增量/全量) );

注意看,这张表除了订单本身的业务字段,还多了四个审计列。后续如果数据出了问题,可以直接通过src_system和load_time定位到“是哪套系统、什么时候送进来的”,不用对着源库一个个查。这也是 STG 层“便于数据问题跟踪”这句话的实际落地。

3.2 ODS 层:源系统数据的“全量档案馆”

STG 层是临时卸货区,ODS(Operational Data Store)层就是正式的“全量档案馆”了。ODS 层把 STG 层的数据做历史存档,保留源系统的所有历史数据。注意,是“所有”——只要有变化就追加,不删不改。如果数据是流式的,也可以跳过 STG 层,直接实时同步到 ODS 层。

ODS 层的物理模型同样包含源系统的所有字段和审计字段,但和 STG 层最关键的区别是多了两个东西:逻辑删除标记和增量时间戳。为什么要加这个?因为很多源系统会物理删除数据,哪怕有逻辑删除标记,后台也可能人为清数据。ODS 层加删除标记后,就能知道“这条记录在源系统已经被删了”,但数据本身还留在档案里,不会凭空消失。从 STG 抽取到 ODS 时还要做数据比较,判断是否有物理删除的情况,如果有,就给对应的记录打上删除标记。

ODS 层的作用可以总结为三句话:全量存储源系统的数据、支持下游系统做实时查询服务、做数据质量检查。开发步骤和 STG 层类似:设计 mapping 文档、设计物理模型(加逻辑删除标记和增量时间戳)、从 STG 层抽取数据、加载数据并做物理删除判断。

3.3 DW 层:真正“变成数据仓库样子”的地方

前面 STG 和 ODS 层的数据都还是“源系统的模样”,从 DW(Data Warehouse)层开始,数据才开始变成数据仓库自己的样子。DW 层是一个清洗、规范化、提交一致化维度和事实的工作区,建立的是反规范化的维度模型。

先说数据清洗。数据清洗是发现数据质量问题并纠正的过程,主要步骤包括:定义数据质量要求、根据业务需求和数据剖析结果确定优先级、制定数据质量测量类型、提交数据质量测量结构表。异常数据的处理策略有四种:中断处理;把拒绝记录放到错误事件表里;只做标记,数据继续处理;纠正数据。注意这里有个原则:能中断处理就中断处理,能 ETL 处理就不推到源头,但有些问题最好在源头处理,有些则必须在源头处理——具体看问题性质。

再说规范化。数据仓库的数据来自各个业务系统,每个系统相对封闭,在命名、取值上都有自己的习惯。规范化就是经过标准化、去重、合并、拆分、整合等过程,把各个业务系统的数据统一命名、统一取值,建立起企业标准版本的数据。比如“性别”字段,有的系统用 0 和 1,有的用 man 和 woman,通过映射表统一命名为 m 和 f。如果多个源系统都维护了相同对象的数据,还需要根据保留规则删除重复数据,只保留唯一的一条。

DW 层最后是提交维度表和事实表。提交维度表的步骤包括:确认粒度(维度表的粒度就是表的业务主键,根据业务主键判断记录唯一性)、选择代理键生成器、选择维度表类型(一般采用缓慢变化维类型 1 和类型 2)、增量加载维度数据(每个字段都要设置默认值,首次加载要有一条代理键为 -1 的默认记录,防止事实表查找不到代理键)、生成代理键管道(建一个包含业务主键和代理键映射关系的查找维度表)。提交事实表的步骤包括:选择事实表类型、用代理键替换主键、增量加载事实数据、提交错误事实表、事实表合并、事实表归档。这部分细节很多,面试时能把这个顺序完整讲出来,基本就过关了。

3.4 DM 层:给报表和分析准备好的“半成品”

DM(Data Market)层是四层模型里的最上层,按业务需求把 DW 层的数据进行聚合,或者生成宽表。你可以把它理解成“已经切好、配好料的净菜”——源数据在 DW 层已经清洗规范好了,DM 层再做最后一道加工,变成业务方能直接用的成品。

DM 层主要做两件事。第一,创建聚合事实表。方法有三种:增量加载,创建聚合表后增量加载数据;聚合导航,用户通过报表分析工具发起请求时,根据用户请求把基础事实表自动生成聚合数据;物化视图,创建物化视图并定时刷新聚合表。第二,创建缩小维度表。因为聚合事实表的粒度和基础事实表粒度不同,需要创建和聚合表相同粒度的维度表,这些维度表只是基础维度表的缩小版,字段更少、粒度更粗。

3.5 为什么非要分四层:让每一层只干一件事

很多人刚开始学数据仓库都会有疑问:数据抽过来就抽过来了,为什么非要搞四层?直接一步到位不行吗?从 ETL 的角度说,分层的核心价值是“每层只干一件事,出了问题知道去哪找”。

STG 层管抽取,负责把数据从源系统安全地搬出来;ODS 层管存档,负责把全量历史留住;DW 层管质量,负责清洗、规范化和维度建模;DM 层管输出,负责按业务需求聚合。每一层都有明确的输入输出和职责边界。这样做的好处是:源头系统改了,最多影响 STG 和 ODS 的映射,不会直接冲击报表;业务需求变了,只需要改 DM 层,不用动底层;数据出错了,能顺着层一层层定位问题出在哪一步。开发成本虽然高了,但维护成本大幅降低——数据仓库是个长期工程,后期维护的成本远比前期开发重要。

4. 维度建模的核心:事实表、维度表、星型和雪花

4.1 事实表和维度表:一本流水账和一本字典

数据仓库的维度建模,核心就两张表:事实表(Fact Table)和维度表(Dimension Table)。

事实表是什么?你可以把它理解成一本流水账。每一个业务事件,比如一笔订单、一次退款、一次登录,都在事实表里占一行。事实表通常包含大量的行,而且里面存放的主要是数字,比如收益、数量、支出,以及用来做统计的标记字段。一般事实表里不放描述性信息,只放数值和外键。

维度表是什么?它是用来描述“这笔业务是谁、在什么时候、在哪里、什么东西”的字典。比如订单事实表旁边会有一个客户维表,里面存放客户编号、客户姓名、会员等级、所在城市;还有一个时间维表,里面存放年、季、月、日、是否是节假日等时间属性。你在分析“北京地区的白金会员今年第一季度贡献了多少销售额”时,事实表提供销售额这个数字,维表提供“北京”“白金会员”“第一季度”这些筛选条件——两者配合,才能回答业务问题。

打个比方:事实表像一本只记数字的账本,每一行是“某天某客户在某门店买了某商品”;维度表像一本配套的编码字典,告诉你“客户 10086 叫什么名字、住在哪个城市、是什么等级”。分析的时候,拿着事实表里的外键去查字典,就能给每个数字配上具体的描述,然后按你想看的维度去汇总。

4.2 事实表的四种类型:加性、半加性、非加性、无事实

事实表看起来简单,但细究起来有四种类型,每种适合不同场景。

第一种是粒度事实表,也叫加性事实表。它记录的是在特定时间、空间点上一次瞬间的测量,比如一笔销售订单。这种表可以跨所有维度直接做求和、计数等聚合操作——把金额加起来、把数量加起来,都有业务含义。但有一个铁律:一个事实表只能有一个粒度,不能把不同粒度的事实建在同一张表里,否则求和结果就会变得不可解释。

第二种是周期快照事实表,也叫半加性事实表。它表现的是一个时间段、或者规律性重复的状态,比如银行账户余额、月度财务报表。账户余额这种数字,按月维度可以求“月末余额”,但一般不能把 12 个月的余额直接相加——相加没有业务含义。所以叫“半加性”:部分维度(比如时间之外的其他维度)可以聚合,时间维度上不能随便加。

第三种是聚合快照事实表,也叫非加性事实表。它描述有明确开始和结束的过程,比如合同履行、保单受理、工作流处理。它的粒度是一个实体从创建到当前状态的完整历史,随着业务处理步骤逐步完善记录。这种表不适合长期连续的过程,比如跟踪银行账户。

第四种是无事实事实表。每个事实表的粒度是一个事件测量,但有些事件发生了,就是没有具体的测量值。比如“学生参加了哪门课程”这个事件,没有金额、数量,只有事实本身。无事实事实表就是用来记录这些事件发生与否的。

4.3 星型模型和雪花模型:一张图能看懂的区别

维度表和事实表的连接方式,决定了模型长什么样。最常见的是星型模型和雪花模型。

星型模型(Star Schema)是所有维度表都直接连接到事实表上,整个结构从上面看像一个星星,中间是事实表,周围一圈维度表。它的特点是维度表不再往下连接其他表,存在一定的数据冗余。比如“门店维度”里的“区域”字段,在星型模型里直接冗余在门店维表里。好处是查询时不需要做太多关联,很多统计直接查事实表加维度表就行,所以效率一般比较高。

雪花模型(Snowflake Schema)是部分维度表没有直接连接到事实表上,而是通过其他维度表连接过去的,结构像雪花一样往外分叉。比如门店维表不直接连事实表,而是先连一个区域维表,再通过区域表连事实表。它减少了数据冗余,但查询时往往需要多关联一层表,开发复杂度和查询成本会高一些。

两者的选择原则,用这张表可以概括:

对比维度星型模型雪花模型
维度表连接方式维度表直接连事实表部分维度表通过其他维度表连接
数据冗余较高较低
查询效率一般较高(关联少)一般较低(关联多)
维护复杂度较低较高
适用场景大多数常规分析维度较大且相对静态的层次

通俗地说:冗余可接受的前提下,优先用星型模型;如果维度表很大、层次关系复杂,而且数据相对静态,才考虑雪花模型。面试里经常有“星型模型是不是一定比雪花模型好”的题目,答案是:不一定,得看维度表的大小和变化频率,但大多数场景下星型模型是更务实的折中选择。

4.4 缓慢变化维(SCD)的三种处理:覆盖、加行、加列

维度表里的数据不是一成不变的。客户的地址会变、员工的部门会调、产品的描述会改。怎么处理这些变化,就是缓慢变化维(Slowly Changing Dimension,SCD)要解决的问题。面试里这个问题几乎必考,标准答案就是三种类型。

Type 1:直接覆盖。用新值直接替换旧值,历史信息不保留。比如客户改了手机号,就把原字段改成新号。这种方式最简单,适合“不需要看历史”的场景——但代价是历史没了,如果之后要分析“客户改手机号之前的订单归属”,就查不到了。

Type 2:增加新行。不改旧数据,而是把当前行的状态标记为关闭(off),设置一个 end_time 时间戳;同时新增一行,把状态标记为开启(on),设置 begin_time 为上一个记录的 end_time 加 1。这样就保留了完整的历史轨迹,适合需要看“某个时间点上这条数据长什么样”的场景,代价是表的数据量会随着变化次数增长。

Type 3:增加新列。给表新增一个列来存储新值,原来的列保留旧值。比如“当前地址”和“原地址”并存。这种方式只保留最近一次变化,适合“只需要对比当前和上一个版本”的场景。

三种方式不是互斥的,一个维度表可以不同类型字段用不同策略:重要属性用 Type 2,次要属性用 Type 1,需要对比的属性用 Type 3。关键是想清楚每个字段的“历史价值”。

4.5 拉链表:想看历史快照又怕费空间的折中方案

拉链表是缓慢变化维 Type 2 在实践中最常用的一种实现方式。它的核心思路是给每张表维护start_date和end_date两个字段:一条记录在某个时间段内是“有效”的,到了end_date就封链,不再参与查询。

表结构大致是这样的:

-- 拉链表:dw_order_his,记录订单的历史状态 CREATE TABLE dw_order_his ( order_id VARCHAR(32), -- 订单编号 order_status VARCHAR(10), -- 订单状态 start_date DATE, -- 该状态生效日期 end_date DATE -- 该状态失效日期,当前生效记录为9999-12-31 );

更新时的操作逻辑是:在 ODS 层创建一张表,存放当天发生变化的数据(包括新增和更新);然后把 ODS 变化表和拉链表做关联,先对旧记录执行“封链”操作,也就是把end_date改成当前日期;再把变化数据插入拉链表,新记录的end_date设为9999-12-31,start_date设为当天。这样,想查“某个订单在某个历史时间点是什么状态”,只需要按时间条件过滤start_date和end_date就能查出来。

拉链表的使用场景非常明确:一是表的数据量很大,比如一张用户表有上亿条记录、几十个字段,全量快照存储成本太高;二是表中部分字段会被更新;三是需要查看某一个时间点的历史快照;四是每天记录变化的比例不大,比如 10 亿用户里每天新增和变化的大约 200 万条。满足这四条,拉链表就是比“每天全量快照”省钱得多、又比“只保留当前值”有历史可查的方案。

拉链表查询性能的优化有两个思路:一是给start_date和end_date做索引,能明显提升按时间过滤的查询速度;二是做数据分级,全量拉链表放一份,另外暴露一张只提供近 3 个月数据的拉链表给高频查询用——既保住了完整历史,又不让日常查询被巨大的表拖垮。

5. 这些概念最容易搞混的四个误区:为什么总在面试里翻车

5.1 STG 层和 ODS 层到底差在哪

这是新手最容易混淆的一对概念,因为两者的表结构都“和源系统模型一致”,都包含审计列,名字听起来也都像“存储层”。

为什么混:STG 和 ODS 在物理模型上确实很像,而且很多小公司的数据量小,干脆把两层合并,导致不少人对它们的定位是模糊的。

怎么区分:STG 是临时卸货区,只保留 7 天或一个月,主要目的是减轻源系统压力、支持任务重跑,基本不做数据转换;ODS 是永久档案馆,全量保存源系统的所有历史数据,而且要加逻辑删除标记和增量时间戳,目的是保留完整历史、支撑下游查询。记住一句话:STG 的数据是“过客”,ODS 的数据是“永久居民”。另外,如果是流式数据同步,可以跳过 STG 层直接进 ODS 层——STG 层面向的是批处理场景。

5.2 数据仓库的“稳定”和“时变”是不是矛盾

面到“数据仓库特点”时,经常有人把“稳定性”和“时变性”理解成互相打架——一个说不允许修改,一个说会定期反映最新变化,这不矛盾吗?

为什么混:两个特点都和时间有关,字面上一个指向“不变”,一个指向“在变”。

怎么区分:稳定性说的是数据一旦进入数据仓库,用户只能查询和分析,不能修改删除——它约束的是“已入库的数据”;时变性说的是数据仓库会定期接收新的集成数据,从而反映出最新的变化——它约束的是“新数据的进入”。一个管存量,一个管增量,各自管一段,完全不冲突。可以类比档案馆:已经归档的档案不能改(稳定),但档案馆每天都会接收新的档案进来(时变)。

5.3 ETL 日志是不是只有出错时才需要记

很多人觉得 ETL 日志就是“出错了才记一笔”,这其实是运维视角的误解。

为什么混:因为一旦 ETL 跑挂了,大家第一反应都是“看日志”,久而久之就觉得日志是排错工具。

怎么区分:ETL 日志分三类。执行过程日志是流水账,记录 ETL 执行过程中每一步的起始时间、影响了多少行数据;错误日志是出问题时专门记录的,包含出错时间、出错模块、出错信息;总体日志是概要记录,只记 ETL 的开始时间、结束时间、是否成功。三者的角色是:过程日志帮你定位“跑得慢在哪一步”,错误日志告诉你“挂了挂在哪”,总体日志用来做日常监控。而且,如果 ETL 出错了,不仅要有错误日志,还要向系统管理员发送警告,最常用的就是发邮件,附上出错信息,让管理员能快速排查。日志要记全,警告要主动,这才是合格的数据仓库运维习惯。

5.4 星型模型是不是一定比雪花模型快

网上很多资料说“星型模型查询效率高,所以一般用星型”,这话本身没错,但有人把它理解成了“星型模型在所有场景下都比雪花模型好”,这就过头了。

为什么混:星型模型确实在大多数情况下关联更少、冗余更高、查询更快,加上很多 BI 工具默认支持星型建模,容易让人形成“星型优于雪花”的印象。

怎么区分:星型模型快的前提是“维度表直接连事实表、不需要额外关联”;一旦维度表本身很大、字段多、层次深,直接冗余会造成维护困难和存储膨胀。雪花模型虽然要多关联一层,但它在处理大的、相对静态的层次时有优势,比如组织架构、产品类目这种层级固定、变化不频繁的维度。所以选择的原则是:在冗余可接受的前提下用星型,在维度大且相对静态的场景下用雪花。真正决定查询快慢的,是数据量、索引、查询语句和计算引擎,模型只是其中一个因素。

5.5 一个事实表只能有一个粒度

这是事实表设计里最容易被忽略的约束。“粒度”指的是表中一行数据代表什么级别的对象——是一笔订单,还是一天的订单汇总,还是一个月度累计。

为什么混:因为很多业务口径相近,比如“订单明细”和“订单汇总”都跟订单有关,有的人就把它们放在一张表里,用字段区分。

怎么区分:一个事实表只能有一个粒度,不能将不同粒度的事实建在同一张表中。为什么?假设一张表里既有每笔订单的数据,又有每天按门店汇总的数据,当你对金额做求和时,汇总行的金额会被重复计算,结果毫无意义。设计事实表时,第一步就是确认粒度:每一行到底代表一次交易、一个周期快照、还是一个完整过程。粒度定清楚了,才知道该用什么事实类型、该按什么方式加载、聚合结果是否可解释——这是整个维度建模里最不能含糊的一件事。

6. 什么时候用数据仓库,什么时候别用:先想清楚再动手

数据仓库不是万能的,它适合的场景和不适用的场景都很明确。

适合用数据仓库的时候,通常满足几个特征:第一,有多个业务系统,需要跨系统整合数据来做分析——比如把订单、库存、售后、物流数据拉通起来看“全链路经营状况”;第二,需要看历史快照——比如查某个订单在某个时间点是什么状态,或者复盘“上季度这个客户的消费轨迹”;第三,源系统承担不了复杂查询——在业务库上跑大范围统计会影响日常交易性能;第四,需要统一指标口径——不同部门对“销售额”的定义不一样,数据仓库可以把它规范成唯一的版本。满足其中两三条,就值得做数据仓库。

别用数据仓库的场合也很多。团队没有专职的数据开发人员,报表直接查业务库就能跑,数据量在百万级以内,这时候搭一套四层模型是给自己找麻烦;业务需要毫秒级的实时响应,比如风控接口、实时推荐,这种场景该用流式计算或者实时数仓,而不是离线数仓;数据源头都还没稳定、口径天天变的时候,建仓也只是建了个“数据的坟场”。另外,如果公司决策层并不真用数据做决策,只是“觉得得有数仓”,那这个项目大概率会烂尾。

我自己就踩过这个坑。刚转行那年,接到一个数据分析任务,我嫌麻烦没有梳理业务口径,直接把源库的数据抽出来拼了一张大宽表给业务方用。结果业务方拿着“销售额”对不上财务的数,追查了三天,发现是两个系统对“已退款的订单”处理方式不同。从那以后,我每次动手前都强制自己先回答三个问题:数据给谁看?看多细?历史要不要回溯?把这三个问题想清楚,再决定要不要上数据仓库、该上哪几层。这条路没有捷径,但每一步都走得踏实就不会翻车。希望帮到你。

本文还有配套的精品资源,点击获取