数据湖、数据仓库、湖仓一体设计详解
数据湖、数据仓库、湖仓一体设计详解
文档主题:数据湖 / 数据仓库 / 湖仓一体的概念、架构、建模、选型与设计实践
适用场景:系统架构设计、数据平台建设、软考「系统架构设计师」备考参考
关注维度:选型权衡 / 易混淆避坑 / 计算与建模 / 双轨口诀
目录
- 一、概念定位与本质区别
- 二、数据湖设计
- 三、数据仓库设计
- 四、湖仓一体设计
- 五、三者协同的典型架构(现代数据栈)
- 六、选型决策矩阵
- 七、易混淆点辨析
- 八、设计Checklist
- 九、双轨口诀
- 附录 A:术语速查表
- 附录 B:典型计算与建模题
一、概念定位与本质区别
| 维度 | 数据湖 (Data Lake) | 数据仓库 (Data Warehouse) | 湖仓一体 (Lakehouse) |
|---|---|---|---|
| 本质 | 原始数据的"蓄水池" | 加工数据的"精品店" | 湖+仓的"综合体" |
| 数据形态 | 原始、任意格式 | 结构化、高度加工 | 开放格式+事务管理 |
| Schema | Schema-on-Read(读时模式) | Schema-on-Write(写时模式) | 两者兼备 |
| 存储格式 | 任意(CSV/JSON/Parquet/图片/视频) | 私有/封闭格式为主 | 开放格式(Parquet+Delta/Iceberg/Hudi) |
| 事务 | 无(或弱) | 有(ACID) | 有(ACID + 时间旅行) |
| 典型用户 | 数据科学家(探索分析) | 业务分析师(报表BI) | 两类用户通吃 |
| 成本 | 低(对象存储) | 高(专有MPP) | 中低(存算分离) |
| 时效 | 批量为主 | 批量+近实时 | 批量+流式统一 |
| 数据质量 | 无保证(垃圾进垃圾出风险) | 强保证(入库前清洗) | 分层保证(Bronze→Gold) |
| 变更追踪 | 无 | 有限(SCD) | 强(Time Travel + CDC) |
一句话本质:
- 数据湖 = 存得下、读得出,但不保证好用
- 数据仓库 = 好用、快,但存得贵、接入慢
- 湖仓一体 = 用开放格式在廉价存储上重建数仓的能力
二、数据湖设计
2.1 设计目标
以最低成本存储全量原始数据(结构化/半结构化/非结构化),支持后续任意消费。
2.2 分层架构(Medallion 架构 / 铜银金)
┌─────────────────────────────────────────────┐
│ Bronze(铜层/原始层) │
│ 原样落库,按源系统分区,保留历史快照 │
├─────────────────────────────────────────────┤
│ Silver(银层/清洗层) │
│ 去重、去脏、类型规范、字段对齐 │
├─────────────────────────────────────────────┤
│ Gold(金层/curated层) │
│ 面向业务的主题聚合表,可直接供BI/ML消费 │
└─────────────────────────────────────────────┘
2.3 关键设计决策
| 决策点 | 选项 | 选型建议 |
|---|---|---|
| 存储底座 | HDFS / 对象存储(S3/OSS/OBS) | 优先对象存储:弹性、免运维、11个9持久 |
| 文件格式 | CSV / JSON / Parquet / ORC | Parquet:列存+压缩+谓词下推,分析查询首选 |
| 分区策略 | 按时间 / 按业务域 / 按源系统 | 时间分区为主(date/hour),避免小文件 |
| 元数据管理 | Hive Metastore / Glue / 自建 | 必须有统一元数据层,否则数据湖变"数据沼泽" |
| 入湖方式 | 批量ETL / CDC / 流式 | CDC(Debezium/Canal)实现增量入湖 |
| 访问引擎 | Spark / Presto/Trino / Flink | 探索用Trino(交互快),批处理用Spark |
2.4 核心陷阱("数据沼泽"问题)
- 只存不管:无元数据、无目录规范 → 找不到数据
- 无数据质量门禁:垃圾进垃圾出
- 小文件爆炸:流式写入产生大量小文件,查询性能崩溃
- 无版本管理:覆盖写入丢历史,无法回溯
- 无访问控制:敏感数据裸奔
2.5 治理要点
- 命名规范:
{域}/{实体}/{层}/{分区}/ - 数据目录:Apache Atlas / DataHub / OpenMetadata
- 血缘追踪:字段级血缘
- 生命周期:冷热分层,热数据SSD,冷数据归档
三、数据仓库设计
3.1 设计目标
面向主题、集成、非易失、时变地组织结构化数据,支撑高性能BI查询与报表。
经典四特征(Inmon定义):Subject-oriented、Integrated、Non-volatile、Time-variant
3.2 分层架构(数仓经典分层)
ODS(操作数据层) ← 贴源,原样同步
│
DWD(明细数据层) ← 清洗+标准化+维度退化,事实明细
│
DWS(汇总数据层) ← 按主题轻度/重度汇总
│
ADS(应用数据层) ← 面向报表/接口的最终指标
│
DIM(维度层) ← 公共维度,缓慢变化维
3.3 建模方法对比
| 建模法 | 核心思想 | 适用 | 代表 |
|---|---|---|---|
| 范式建模(3NF) | Inmon自顶向下,减少冗余 | 大型企业数仓底座 | Inmon |
| 维度建模(星型/雪花) | Kimball自底向上,事实表+维度表 | 业务分析、BI | Kimball |
| Data Vault | Hub+Link+Satellite,审计友好 | 大规模集成、历史追溯 | Linstedt |
| Anchor建模 | 进一步去冗余,6NF | 超大规模、频繁变更 | — |
星型 vs 雪花:
- 星型:维度表反范式(宽表),join少,查询快,存储冗余 → BI首选
- 雪花:维度表范式化,省存储,join多 → 维度巨大时用
3.4 缓慢变化维(SCD)四种类型
| 类型 | 含义 | 处理 |
|---|---|---|
| SCD1 | 覆盖更新 | 直接改,丢历史 |
| SCD2 | 保留历史版本 | 加有效起止时间字段,新增行 |
| SCD3 | 有限历史 | 加"旧值"列 |
| SCD4 | 用历史子表 | 主表存当前,子表存历史 |
3.5 技术选型
| 类型 | 代表 | 特点 |
|---|---|---|
| 传统MPP | Greenplum/Teradata/Vertica | 存算耦合,性能强,扩展受限 |
| 云数仓 | Snowflake/Redshift/BigQuery/Synapse | 存算分离,弹性扩缩 |
| Hadoop生态数仓 | Hive on Tez/Spark | 廉价但延迟高 |
| 新兴实时数仓 | Doris/StarRocks/ClickHouse | 亚秒级OLAP,MPP向量化 |
3.6 设计要点
- 主题域划分:交易域、用户域、流量域、营销域……
- 粒度声明:每层事实表明确粒度(如"订单一行一记录")
- 总线矩阵:确认一致性维度,跨主题共享
- 预计算策略:Cube/物化视图,空间换时间
- 分区与分桶:按天分区,按user_id分桶避免倾斜
- 指标口径统一:原子指标→派生指标→计算指标,定义在元数据
四、湖仓一体设计
4.1 设计目标
在廉价对象存储 + 开放格式上,同时获得:
- 数据湖的低成本、开放、全格式
- 数据仓库的ACID事务、Schema管理、高性能查询、BI直连
4.2 三大开源引擎(核心选型)
| 引擎 | 出身 | 强项 | 弱项 | 选型建议 |
|---|---|---|---|---|
| Delta Lake | Databricks | 生态成熟、Z-Order优化、流批统一 | Spark绑定深 | Spark生态首选 |
| Apache Iceberg | Netflix→Apache | 引擎中立(Spark/Trino/Flink/Hive)、隐藏分区、schema演进强 | 生态较新 | 多引擎/云中立首选 |
| Apache Hudi | Uber | 增量upsert强、CDC友好、表类型灵活(CoW/MoR) | API较复杂 | 增量更新/CDC场景首选 |
4.3 核心能力对比
| 能力 | Delta | Iceberg | Hudi |
|---|---|---|---|
| ACID事务 | ✅ | ✅ | ✅ |
| 时间旅行(Time Travel) | ✅ | ✅ | ✅ |
| Schema演进 | ✅ | ✅✅最强 | ✅ |
| 隐藏分区 | ❌ | ✅ | ❌ |
| Upsert/Delete | ✅ | ✅ | ✅✅最强 |
| 多引擎支持 | Spark/Trino | Spark/Trino/Flink/Hive/Impala | Spark/Trino/Flink/Hive |
| 流批一体 | ✅✅ | ✅ | ✅ |
| 小文件合并 | ✅Optimize | ✅Compaction | ✅Compaction |
4.4 架构参考
┌──────────────────────────────────────────────────┐
│ 消费层:BI(Tableau/Superset) / ML / Ad-hoc查询 │
├──────────────────────────────────────────────────┤
│ 计算层(多引擎,存算分离) │
│ Spark(批) / Trino(交互) / Flink(流) │
├──────────────────────────────────────────────────┤
│ 表格式层:Iceberg / Delta / Hudi(ACID+Schema) │
├──────────────────────────────────────────────────┤
│ 存储层:对象存储(S3/OSS) + Parquet列存 │
├──────────────────────────────────────────────────┤
│ 元数据:Catalog(Nessie/Rest/Unity/Glue) │
└──────────────────────────────────────────────────┘
4.5 关键设计决策
- 表格式选型:见4.2,多引擎选Iceberg,Spark深度用Delta,强upsert用Hudi
- Catalog选型:Nessie(支持Git式分支)/ Unity Catalog(Databricks)/ Glue(AWS)
- 分区策略:Iceberg用隐藏分区(
days(ts)),避免用户手动分区列 - 小文件治理:定期Compaction/Optimize,流式写入后必做
- Z-Order/聚簇:对高频过滤列做Z-Order,提升Data Skipping
- 分支与隔离:dev/prod分支,ML实验用独立分支不污染主线
- 流批统一:Flink写Iceberg,Spark批读,同一张表
五、三者协同的典型架构(现代数据栈)
数据源(DB/日志/SDK/第三方)
│
┌───────┴───────┐
│ 入湖(原始) │ ← CDC + 批量 + 流
└───────┬───────┘
│
数据湖(Bronze) ← 全量原始,低成本
│
清洗(Silver) ← Delta/Iceberg表
│
┌───────────┼───────────┐
│ │ │
数仓(Gold) ML特征 Ad-hoc
(维度建模) (特征表) (探索沙箱)
│
BI报表
演进路径:数据湖 → 湖仓一体 →(可选)专用数仓加速层
六、选型决策矩阵
| 场景 | 推荐 |
|---|---|
| 全量原始存储、成本敏感、数据科学家探索 | 数据湖 |
| 成熟BI、固定报表、强Schema、查询性能要求高 | 数据仓库 |
| 既要存原始又要BI直连、流批一体、避免数据搬运 | 湖仓一体 |
| 多引擎混用、云中立 | 湖仓+Iceberg |
| Spark深度、Databricks生态 | 湖仓+Delta |
| 强CDC/频繁upsert | 湖仓+Hudi |
| 亚秒级高并发OLAP | 湖仓 + StarRocks/Doris加速层 |
七、易混淆点辨析
| 易混点 | 辨析 |
|---|---|
| 数据湖 vs 数据仓库 | 湖存原始任意格式(读时模式);仓存加工结构化(写时模式) |
| 湖仓一体 vs 数据湖 | 湖仓在湖之上加了表格式层(ACID/Schema/时间旅行),不是裸Parquet |
| 湖仓一体 vs 数据仓库 | 湖仓用开放格式+对象存储;传统数仓用封闭格式+专有存储 |
| Iceberg vs Delta vs Hudi | 三者能力趋同,差异在生态绑定与upsert/分区强项 |
| ODS vs DWD | ODS贴源原样;DWD已清洗标准化 |
| 星型 vs 雪花 | 星型维度反范式(宽表快);雪花维度范式化(省存储慢) |
| SCD2 vs 时间旅行 | SCD2是业务维度的历史版本;Time Travel是表级数据版本(技术机制) |
| 存算分离 vs MPP | 存算分离弹性好但网络开销;MPP存算耦合性能高但扩展难 |
| Data Vault vs 维度建模 | Data Vault审计/集成友好但查询需转换;维度建模直接可查 |
| CoW vs MoR(Hudi) | CoW(Copy on Write)写时复制读快;MoR(Merge on Read)读时合并写快 |
| 范式建模 vs 维度建模 | Inmon范式3NF自顶向下做底座;Kimball维度自底向上直接可查 |
八、设计Checklist
数据湖:
- [ ] 对象存储底座
- [ ] 统一元数据层
- [ ] 分区与命名规范
- [ ] 小文件治理
- [ ] 数据目录与血缘
- [ ] 访问控制
- [ ] 生命周期管理
数据仓库:
- [ ] 主题域划分
- [ ] 分层(ODS/DWD/DWS/ADS/DIM)
- [ ] 粒度声明
- [ ] 总线矩阵
- [ ] SCD策略
- [ ] 指标口径统一
- [ ] 预聚合/物化视图
湖仓一体:
- [ ] 表格式选型(Iceberg/Delta/Hudi)
- [ ] Catalog选型
- [ ] 隐藏分区
- [ ] Compaction调度
- [ ] Z-Order/聚簇
- [ ] 流批统一
- [ ] 分支隔离
- [ ] 多引擎访问
九、双轨口诀
9.1 顺口溜
湖蓄原水任意装,仓炼精品主题强;
湖仓一体两兼得,开放格式事务帮。
铜银金层层层净,ODS明细汇总上;
Iceberg中立多引擎,Delta Spark流批畅,
Hudi增量upsert王,三者趋同看生态绑。
9.2 谐音口诀
“湖仓冰”——湖(数据湖)仓(数据仓)冰(Iceberg) → 记住湖仓一体首选Iceberg
“IDH”——Iceberg/Delta/Hudi,按"中立/绑定/增量"记
“我老师过通顺功”——内聚偶逻时过通顺功(附:数据建模相关)
“星宽雪窄”——星型宽表快,雪花窄表省
9.3 分层口诀
数据湖:铜银金,原洗用(Bronze原始/Silver清洗/Gold可用)
数据仓:O D W S A,贴明汇应(ODS贴源/DWD明细/DWS汇总/ADS应用)
湖仓:存表计消,自下而上(存储→表格式→计算→消费)
附录 A:术语速查表
| 术语 | 全称 | 含义 |
|---|---|---|
| Schema-on-Read | 读时模式 | 写入不校验,读取时再解释结构 |
| Schema-on-Write | 写时模式 | 写入前校验结构,强约束 |
| ACID | 原子/一致/隔离/持久 | 事务四特性 |
| CDC | Change Data Capture | 变更数据捕获,增量同步 |
| SCD | Slowly Changing Dimension | 缓慢变化维 |
| MPP | Massively Parallel Processing | 大规模并行处理 |
| OLAP | Online Analytical Processing | 联机分析处理 |
| CoW | Copy on Write | 写时复制(Hudi表类型) |
| MoR | Merge on Read | 读时合并(Hudi表类型) |
| Z-Order | Z序曲线 | 多列联合排序,提升Data Skipping |
| Time Travel | 时间旅行 | 查询历史版本快照 |
| Data Skipping | 数据跳过 | 基于统计信息跳过无关文件 |
| Medallion | 奖牌架构 | 铜银金三层架构 |
| Data Vault | 数据保险库 | Hub+Link+Satellite建模 |
| 总线矩阵 | Bus Matrix | 一致性维度×事实表矩阵 |
附录 B:典型计算与建模题
B.1 星型 vs 雪花存储/查询代价
题目:事实表 1 亿行,维度表"地区"1000 行。星型中地区宽表(20列)冗余存储;雪花拆为"国家表(200行)+省市表(800行)"各10列。比较两种方案的存储与查询join数。
解析:
- 星型:维度冗余 = 1000×20列;查询事实+1维度 = 1次join
- 雪花:维度拆分存储更省 = 200×10 + 800×10;查询事实+地区 = 2次join(事实→省市→国家)
- 结论:星型查询快、存储冗余;雪花存储省、join多
B.2 小文件对查询性能影响
题目:流式写入每分钟1个文件,1天产生1440个小文件(每个1MB)。查询需扫描全量。Parquet footer读取开销约每文件5ms。求单次查询文件开销,并说明治理方案。
解析:
- 文件开销 = 1440 × 5ms = 7.2秒(仅文件元数据开销)
- 治理:Compaction合并为目标128MB/文件 → 文件数 ≈ 1440MB/128MB ≈ 12个 → 开销 ≈ 60ms
- 结论:小文件治理是湖仓必做项,目标文件大小 128MB~1GB
B.3 Iceberg 隐藏分区
题目:表按 event_time 查询频繁。Iceberg隐藏分区定义为 days(event_time)。说明相比手动分区列的优势。
解析:
- 手动分区:需额外列
event_date,用户查询必须带event_date=...,否则分区裁剪失效 - 隐藏分区:用户查询
event_time BETWEEN '2026-01-01' AND '2026-01-07',Iceberg自动转换为days(event_time) IN (0..6)实现分区裁剪 - 优势:用户无感、避免分区列污染Schema、分区策略可变更
B.4 SCD2 行数计算
题目:客户维度,某客户地址变更3次。SCD2下该客户在维度表中有几行?每行需要哪些字段?
解析:
- 行数 = 4行(初始1 + 变更3)
- 必需字段:
customer_id(业务键)、address、valid_from、valid_to、is_current - 当前行:
valid_to='9999-12-31'、is_current=1;历史行:is_current=0
B.5 湖仓 vs 数仓成本对比
题目:100TB数据,月查询100次。对象存储$0.023/GB/月,云数仓存储$0.04/GB/月+计算按量。估算月存储成本差异。
解析:
- 对象存储:100×1024×0.023 ≈ $2355/月
- 云数仓存储:100×1024×0.04 ≈ $4096/月(未含计算)
- 差异:湖仓存储成本约为数仓的 57%,且计算按需弹性,闲置不计费
- 结论:存算分离 + 对象存储 = 湖仓成本优势核心
本文档覆盖:概念本质 / 分层架构 / 建模方法 / 技术选型 / 协同架构 / 易混辨析 / 设计Checklist / 双轨口诀 / 术语速查 / 计算例题。
后续可扩展:具体引擎DDL示例、性能调优实战、数据治理组织架构。
- 点赞
- 收藏
- 关注作者
评论(0)