1. 五种架构不是替代关系,而是五种不同的数据组织方式
我最早接触这几套概念的时候,也以为它们是按时间顺序排队出现的:先有数据仓库,然后数据集市,再进化到数据湖,接着是数据网格,最后大家发现都不完美,于是搞出湖仓一体。这个线性理解害我走了不少弯路,直到有一次在做一份跨部门报表时,同一个"活跃用户数"在三个系统里跑出三个数字,我才明白问题的本质——这五个词描述的压根不是同一件事,它们在回答的是五个不同层次的问题。
数据仓库回答的是"口径怎么统一、指标怎么复用";数据集市回答的是"部门要的东西怎么快速给到";数据湖回答的是"什么数据都先存下来行不行";数据网格回答的是"数据团队扛不动全公司的需求怎么办";湖仓一体回答的是"存下来的原始数据和加工过的指标能不能放在一个体系里管"。你看,这五个问题可以同时存在,很多公司今天的实际状态就是五套东西并存,而不是谁把谁干掉了。
这篇文章我打算按"每种架构解决什么问题、代价是什么、什么时候该上、踩过哪些坑"这条线来讲,不讲教科书定义,讲实际落地时你会遇到的选择。判断自己该用哪一种的标准其实很朴素:先看你当前最大的痛点是"数据找不到"、"口径对不上"、"部门需求响应慢"、还是"存储成本压不住",痛点决定架构,而不是反过来。
一个我踩过的坑:先别急着选技术栈,先把"谁负责哪些数据、谁有权用哪些数据"这两张表画出来。技术选型错了好换,责任边界错了要重构组织。
还有个前提得说清楚,这五种形态背后其实只有三个变量在变:数据的结构化程度、加工的时机(先加工后存还是先存后加工)、以及治理权的归属(集中还是分布)。你把这三个变量想明白,任何新冒出来的名词你都能自己归类,不需要追着一波又一波的概念跑。
2. 数据仓库:先把口径钉死,再谈性能
数据仓库最核心的价值从来不是"快",而是"准"。它是那种你愿意为了一致性牺牲一点灵活性的地方。我见过太多团队上来就纠结用 ClickHouse 还是 Doris,结果三种口径的 GMV 在系统里飘着,性能再快也是白搭。
数据仓库的本质是面向主题、集成、相对稳定、反映历史变化的数据集合。这四个词里"集成"是最费劲的,因为集成意味着你要把来自十几个业务库的编码表、状态值、时间口径全部对齐。举个例子,A 系统的订单状态用 0/1/2 表示,B 系统用 pending/paid/cancelled 表示,进了仓库必须统一成一套状态枚举,还要映射历史数据。这一步没做完,后面所有建模都是空中楼阁。
2.1 分层设计:ODS、DWD、DWS、ADS 各自该放什么
分层不是为了好看,是为了让每一层只有一种职责,出问题的时候能快速定位是哪一层错了。我习惯的分法是这样:
| 层次 | 存放内容 | 加工方式 | 典型保留周期 |
|---|---|---|---|
| ODS | 贴源数据,与业务库结构基本一致 | 抽取、轻量清洗 | 3~12 个月 |
| DWD | 明细事实,做过编码统一、去重、维度补全 | 清洗、规范化 | 12~36 个月 |
| DWS | 按主题聚合的轻度汇总,如用户日粒度行为 | 聚合、宽表化 | 12~36 个月 |
| ADS | 直接服务报表和接口的结果表 | 按需定制 | 6~24 个月 |
ODS 层我建议不要做业务逻辑,只做技术处理:字段类型转换、脱敏、时区统一。很多团队在 ODS 就开始写 case when,结果业务规则一改,追溯都追溯不到。DWD 层是真正干重活的地方,编码映射、拉链、去重全在这层。DWS 层要克制,别做成"什么维度都往宽表里塞",宽表一旦超过 200 个字段,维护成本会指数级上升。
实践里有个小技巧:表命名带上层次前缀和更新频率,比如dwd_order_detail_di(日增量)、dws_user_action_1d(日粒度全量)。命名规范这件事,团队小的时候觉得无所谓,等到表数量过千,你会发现没有规范根本找不到表。
2.2 维度建模与范式建模的分歧点在哪
这个争论持续了三十年,其实答案取决于你的使用场景。范式建模(第三范式为主)适合数据变化频繁、写入密集的场景,冗余少、一致性强,但查询往往要 join 七八张表,分析师写 SQL 写到崩溃。维度建模(星型、雪花)把业务过程抽象成事实表加维度表,查询简单、性能可控,代价是维度更新时要处理缓慢变化维。
我的选择标准很直接:面向分析用维度建模,面向集成用范式建模,两者可以在同一仓库里共存。DWD 层用偏范式的方式保持干净,DWS 和 ADS 层用星型模型服务查询。缓慢变化维我一般用拉链表(记录 start_date、end_date、is_current),因为很多业务要复盘"当时的用户等级是什么",直接覆盖维度的做法会把历史判断全部抹掉。
拉链表的坑:更新逻辑一定要幂等,跑重了不能产生重复区间。我一般会加唯一索引或者用 merge 语法,跑批前先删当天分区再重跑。
2.3 小型数据仓库的选型清单
不是每个团队都需要一套庞大的集群。数据量在千万级到亿级、并发查询几十个的场景,下面这几种组合完全够用:
- PostgreSQL + 分区表 + 物化视图:单机就能扛住几亿行,配合列存扩展(如 cstore_fdw 之类思路)还能更省。运维成本几乎为零,适合 5 人以下数据团队。
- ClickHouse 单机或小集群:写入吞吐和聚合查询极强,适合日志、埋点类宽表分析。缺点是 join 弱、更新麻烦,别拿它当交易库用。
- Apache Doris / StarRocks 小集群:MPP 架构,支持较好的 join 和实时更新,三五个节点就能跑起来,适合既要实时又要多维分析的场景。
- DuckDB:单文件、嵌入式,适合本地做数据探索和中小规模 ETL,直接把 parquet 文件当表查,做原型验证特别快。
选型的核心不是比谁参数好看,而是比你的团队能不能维护它。一个需要专职 DBA 才能跑稳的系统,放在只有两个数据开发的小团队里,迟早会变成事故源。
3. 数据集市:把"全公司的仓库"切成"部门能用的表"
数据集市经常被误解成"小号数据仓库",其实它更像是一种交付方式。它的核心特征是面向特定部门或特定分析主题,字段精简、口径固定、响应快。销售部门要的集市里不会有生产设备的传感器数据,风控部门要的集市里也不会放市场活动的曝光日志。
为什么需要它?因为一个全公司共用的仓库,随着表数量膨胀,分析师找表的成本会超过写 SQL 的成本。数据集市的作用是把"这个部门关心的 30 张表"从几千张表里挑出来,配上说明文档和统一的指标定义,让人一进去就能干活。
3.1 独立数据集市与从属数据集市的成本差异
这里有个经典分歧。独立数据集市由各部门自己建,直接抽业务库,见效快,但三五年后必然出现"同一个客户在三个集市里三个 ID"的局面,跨部门分析基本做不了。从属数据集市从企业级仓库里派生,一致性有保障,但建设周期长,部门会觉得"我要个报表怎么要走三个月流程"。
我的折中做法是:关键实体(客户、商品、组织、时间)必须由仓库统一供维,业务指标允许部门在集市里自行组合。这样既保证了跨部门口径能对上,又给了部门足够的灵活性。实施上就是仓库出一套 conformed dimension(一致性维度表),集市里的事实表通过代理键去关联这些维度,而不是各自维护一份客户表。
3.2 一致性维度没做好,数据集市就会变成数据孤岛
一致性维度这件事,说起来简单做起来要命。难点在于不同部门对同一个实体的关注字段完全不同,客户维度在销售眼里是"等级、来源渠道",在客服眼里是"会员状态、历史工单数"。硬把所有人的字段塞进一张维度表,它就会变成一个没人敢改的怪物。
我通常的做法是维度表分核心属性和扩展属性:核心属性(ID、名称、创建时间、状态)由仓库统一维护,扩展属性按主题拆成多个卫星表,部门按需关联。这样一致性有保证,扩展也不打架。判断标准是:凡是会被两个以上部门用于筛选或分组的字段,就必须进核心属性。
还有一个容易被忽略的点是维度版本管理。产品分类体系一年改两次很正常,如果集市直接引用最新分类,去年的报表口径就和今年对不上了。所以维度表要带生效时间,报表默认按业务发生时间去找对应的版本。
4. 数据湖:存得下不等于用得好
数据湖最初的承诺很诱人:先把所有数据原样存下来,管它结构化的还是非结构化的,等需要用的时候再定义 schema。这个"schema on read"的思路解决了传统仓库"改表结构要走流程"的痛点,但代价是——如果没有强治理,它会迅速变成一个谁都说不清里面有什么的沼泽。
我在一个项目里见过真实的数据沼泽:对象存储里两万多个目录,命名从data_2020到new_new_final_v3,没有人知道哪个是权威版本,也没有人知道哪些字段是加密的。这种湖的存储成本很低,但使用成本极高,本质上等于没有数据。
4.1 数据沼泽是怎么一步步形成的
它不是一天变成沼泽的,通常是这几个动作叠加的结果:
- 写入无规范:任何团队都能往湖里扔文件,路径和格式随缘,csv、json、parquet 混着放。
- 元数据不登记:文件扔进去就没人管,没有分区信息、没有字段说明、没有数据负责人。
- 只写不删不归档:冷数据一直占着存储,成本慢慢堆上去。
- 权限一刀切:要么全开放,要么全锁死,中间没有细粒度控制。
对应的解法其实很朴素:统一存储路径规范、强制元数据登记、按生命周期分层存储、按列和行做权限。路径规范建议用域/主题/表名/分区四级结构,分区统一用dt=YYYYMMDD这种带键名的形式,这样所有引擎都能自动识别分区。
4.2 开放表格式解决了哪些老问题
Hive 表玩了十几年,几个顽疾一直存在:小文件多、不能行级更新、并发写入容易冲突、schema 改了历史数据读不出来。开放表格式(Iceberg、Hudi、Delta Lake 这类)主要就是在解决这些问题:
| 能力 | Hive 表 | 开放表格式 |
|---|---|---|
| 行级更新删除 | 不支持,要重写分区 | 支持 merge on read |
| 并发写入 | 靠分区隔离,易冲突 | 乐观锁 + 快照隔离 |
| 时间旅行 | 不支持 | 按快照或版本号查询历史 |
| Schema 演进 | 危险,易读错 | 支持加列、改名、类型提升 |
| 小文件治理 | 手动 compact | 内置 compaction |
选哪种其实取决于生态。如果你的计算引擎以 Spark 和 Flink 为主,Iceberg 的社区活跃度和引擎兼容性更稳;如果实时写入场景多、需要分钟级可见,Hudi 的 upsert 能力更顺手;如果全栈都在某个云厂商体系内,Delta Lake 的集成度会更高。
别忽略 compaction。流式写入小文件的速度远超你的想象,一天下来可能几万个几十 KB 的文件,查询时元数据开销比读数据还大。一定要配定时 compaction 任务,并且监控文件数量这个指标。
4.3 湖上的元数据与权限治理
湖里最值钱的不是数据,是元数据。我的经验是至少要维护三类信息:技术元数据(表结构、分区、文件数、大小、更新时间)、业务元数据(表的中文名、字段含义、指标口径、负责人)、操作元数据(谁在什么时候读了什么、跑了多久)。前两类决定别人能不能用,第三类决定你能不能查问题。
权限控制上,行级和列级权限是刚需。比如用户手机号只有特定角色能看明文,其他角色只能看脱敏值;再比如区域经理只能看自己区域的明细。这些在数据湖上通常有两种实现路径:一是通过统一的 catalog 层做策略(查询时动态改写),二是通过视图封装。前者维护成本低,后者更直观,我一般两者结合,敏感的用视图兜底。
5. 数据网格:把数据当产品交付的组织级改造
数据网格这个词听起来很玄,剥开看其实是一个很现实的判断:当公司有几十个业务域、几百个数据消费者时,一个集中式数据团队无论如何都排不完需求。它不是技术方案,而是组织方案,技术只是支撑。
它的四个核心原则我按重要性重排一下:领域所有权、数据即产品、自助式平台、联邦式治理。注意顺序,很多人上来就搭自助平台,结果没人认领数据,平台搭好了也是空的。
5.1 四个核心原则拆开看
领域所有权指的是每个业务域自己负责自己产生的数据,从采集到质量到对外发布。这跟过去的"数据团队统一收口"完全相反,好处是业务域最懂自己的数据,坏处是每个域的能力参差不齐,需要平台和标准兜底。
数据即产品意味着每一份数据都要有明确的负责人、SLA、文档、质量指标和版本。我一般要求每个数据集至少回答五个问题:谁负责、多久更新一次、字段含义是什么、质量怎么衡量、出问题找谁。回答不上来的就不算产品,只能算临时文件。
自助式平台是把采集、存储、计算、权限、监控这些能力做成开箱即用的服务,让业务域不需要自己从零搭。联邦式治理是先定一套全局标准(比如指标定义、命名规范、隐私分级),各域在标准内自治,而不是中央强行管到每个字段。
5.2 数据网格最容易落空的地方
我见过几个失败的案例,问题几乎都出在同一处:只做了平台,没有做组织。业务域被要求"你们自己管数据",但没有给编制、没有给激励、也没有评审机制,最后数据产品的"负责人"变成了一个挂名的名字,SLA 写了也没人看。
要落地,至少得配套三件事:一是把数据质量指标纳入业务域的考核,不然优先级永远排不上;二是建立跨域的口径评审会,不然各域自说自话,跨域分析又回到手工对齐;三是平台必须真的做到自助,如果一个数据产品的上线还要找平台团队排队两周,那网格的意义就没了。
我的判断标准:如果你所在的组织连"数据负责人"这个角色都还没有,先别谈数据网格。从建元数据和明确责任人开始,比引入任何新架构都实在。
6. 湖仓一体:统一元数据才是关键动作
湖仓一体经常被简化成"湖加仓",这个理解太表面了。它真正要解决的是同一份数据在湖和仓里各存一份、各算一遍、口径不一致的问题。核心动作是让多种计算引擎(批处理、流处理、交互式查询、机器学习)能直接读同一份存储上的同一份数据,并且共享同一套元数据和权限。
6.1 湖仓一体要解决的三类割裂
第一类是存储割裂。过去原始数据在对象存储,加工结果在仓库内部存储,要跨过去就得导数据,链路长、延迟高、还容易出错。湖仓一体的做法是全部落到开放格式的对象存储上,由表格式提供事务和索引能力。
第二类是元数据割裂。湖里有自己的 catalog,仓里有自己的 catalog,同一个业务实体两套定义。解决方式就是统一到一个 catalog 上,让引擎都往这里注册和查询,这样 lineage(血缘)才能连起来。
第三类是计算割裂。批任务用 Spark、实时用 Flink、BI 用 MPP 引擎、算法用 Python,各自要把数据搬到自己的存储里才能跑。统一之后,这些引擎可以针对同一份数据直接计算,减少了大量重复的搬运和冗余存储。
这三类割裂里,元数据统一最难但收益最大。因为一旦元数据统一,血缘分析、权限继承、数据发现全都能串起来;反过来如果元数据还是两套,你会陷入"改了 A 系统 B 系统不知道"的持续混乱。
6.2 落地时的技术组合与常见坑
组合上通常是这样:对象存储(或分布式文件系统)作为统一底座,开放表格式管理事务和快照,统一 catalog 管元数据,上面接多引擎。数据量大的话,再叠一层缓存或本地 SSD 加速热数据读取。
实际落地我最常遇到的三个坑:
- 小文件问题在统一后变得更严重,因为写入来源变多了。必须在上线前就把 compaction 策略、文件大小目标定下来(一般 128MB~512MB 一个文件比较合适),并且做成自动任务。
- 权限模型不统一,湖的权限和仓的权限是两套体系,统一之后要么全部迁到 catalog 层,要么做双向同步,千万别指望用户手动维护两份。
- 性能预期错配,大家以为统一之后查询会更快,实际上从对象存储读数据比从本地磁盘慢,必须靠缓存层和统计信息来补。上之前先做压测,别在报表上线当天才发现慢了三倍。
另外一个经验是别一次性迁移所有表。先挑几条核心链路的数据试,跑通血缘、权限、性能三件事,再逐步铺开。全量迁移最大的风险是问题集中爆发,排查的时候连是哪一层的问题都判断不出来。
7. 选型对照与落地顺序:别一上来就上最贵的
把五种形态放在一张表里对照,选型会清晰很多:
| 架构 | 核心解决的问题 | 主要代价 | 适合的团队状态 |
|---|---|---|---|
| 数据仓库 | 口径统一、指标复用 | 建模周期长、灵活性偏低 | 有多部门共用指标需求 |
| 数据集市 | 部门响应速度 | 易产生孤岛、重复建设 | 部门需求密集且差异大 |
| 数据湖 | 全量保存、格式自由 | 治理成本高、易成沼泽 | 有非结构化与半结构化数据 |
| 数据网格 | 集中团队排不过来的需求 | 组织改造成本极高 | 多业务域、数据团队长期过载 |
| 湖仓一体 | 存储与元数据的重复割裂 | 初期投入和调优成本高 | 已有湖和仓且两者并行运行 |
落地顺序我的建议是一句话:先把仓库做扎实,再谈湖。仓库的核心产物是统一口径和一致性维度,这两样东西是你后面所有架构的公共基础。仓库没打好,直接上湖只会把混乱从结构化数据扩展到半结构化数据;湖仓一体也一样,如果仓库侧的指标定义本身就是乱的,统一元数据只会把混乱放大到更大的范围。
如果已经有一个不错的仓库,下一步通常是把非结构化和高频原始数据放进湖,用开放表格式管理,再逐步把湖和仓的元数据打通,走湖仓一体的路线。数据网格我放在最后,因为它依赖前面所有能力都足够成熟,才能把责任下放给业务域而不失控。
具体到指标上,我一般用四个数来判断当前该往哪走:表数量与月活查询人数的比值(太高说明发现成本大,需要集市)、跨部门指标口径不一致的数量(大于零就要先补仓库)、存储年增长率和冷数据占比(冷数据超过六成要考虑分层和归档)、需求平均交付周期(超过两周说明集中团队过载,要么加人要么考虑网格)。
最后提醒一句:架构升级的收益往往滞后半年到一年才显现,所以推进时一定要挑一个能快速见效的点先做出来,比如把某个高频报表的交付周期从三周压到三天。有了这个案例,后面的推广会顺畅得多。
这套东西我在几个规模差很多的团队里都落地过,最大的体会是:别用架构去套组织,要用痛点去选架构。很多团队卡住不是因为技术选错了,而是因为没人愿意为数据质量负责。技术方案再先进,也扛不住一个没人认领的数据表。