

作者:陈乔怀古,资深数据仓库工程师
关注公众号:【陈乔数据观止】,回复关键字:【资料】,进社群下载全部 word/ppt/pdf 文件。
添加v:cqhg_bigdata,备注数仓,领取美团外卖实时数仓建设实践文档👇。

一、背景与目标
案例公司是一家快速发展的电商SaaS平台,初期所有数据都存储在业务MySQL数据库中。随着业务增长,报表查询变慢、数据口径混乱、分析需求无法满足等问题频发。老板一句“我们需要一个数据仓库”,让我从零开始搭建整套数据体系。
目标:
统一数据出口,解决数据孤岛问题 支持多维度、灵活的报表分析 支撑用户行为分析、营销效果评估 为未来数据中台打基础
二、第一阶段:选型与架构设计(踩坑1:技术选型拍脑袋)
1. 初始选型
结果: 两周后崩溃。订单表日增50万条,MySQL查询超时,ETL脚本维护困难,crontab无法监控依赖。
填坑方案1:重新选型,拥抱大数据生态
✅ 最终技术栈:
存储层:Hive(离线数仓) + ClickHouse(实时分析) 计算引擎:Spark(批处理)、Flink(实时,后期引入) 调度系统:Airflow(可视化DAG,依赖管理) 数据采集:DataX(离线)、Kafka(实时日志) 元数据管理:Atlas(后期引入) 查询分析:Superset + Doris(后期替换ClickHouse)
三、第二阶段:数据分层设计(踩坑2:没有分层,直接ODS到ADS)
1. 错误做法
初期为了快速出报表,直接从MySQL通过DataX同步到Hive ODS层,然后写SQL聚合到ADS(应用层),中间没有中间层。
问题:
同一个维度逻辑在多个ADS表中重复(如用户等级计算) 修改逻辑需改多个表 数据一致性差
填坑方案2:引入标准分层模型
✅ 采用Kimball维度建模 + 分层设计
关键实践:
DWD层保持原子性,DWS层按“用户、商品、订单”等主题域聚合 所有ADS只依赖DWS/DWD,不跨层跳读 使用一致的维度表(如dim_user, dim_product)
四、第三阶段:ETL开发与调度(踩坑3:脚本化ETL,无版本管理)
1. 问题描述
初期用Python写ETL脚本,存放在本地,通过crontab调用。很快出现:
脚本版本混乱(同事改了没通知) 日志不统一,出错难排查 无法重跑历史数据
填坑方案3:Airflow + Git + 模板化SQL
✅ 标准化ETL流程
Airflow调度
DAG按主题域划分: dwd_order_dag.py
,dws_user_dag.py依赖关系可视化:ODS → DWD → DWS → ADS 邮件告警 + 钉钉机器人通知 SQL模板化
-- 模板:dwd_order_detail.sql
INSERT OVERWRITE TABLE dwd_order_detail PARTITION(dt='${ds}')
SELECT
order_id,
user_id,
product_id,
price,
get_user_level(user_id) as user_level, -- 维度退化
FROM_UNIXTIME(create_time) as create_time
FROM ods_order_info
WHERE dt = '${ds}'Git管理
所有SQL、DAG脚本纳入GitLab 分支策略:dev → test → prod Code Review强制执行
五、第四阶段:数据质量保障(踩坑4:数据不准,背锅无数次)
1. 典型事故
某次营销活动报表显示“订单量下降50%”,业务部门紧张,结果发现是ETL漏跑了一天,但没人发现。
填坑方案4:建立数据质量监控体系
✅ 四层保障机制
基础监控
表数据量波动告警(±30%触发) 分区缺失检测(如ods表没生成dt=2023-08-01) 字段空值率监控(如user_id为空>5%告警) 一致性校验
ODS与源库数据量比对(每日自动校验) ADS与DWS聚合结果交叉验证 业务规则校验
示例: ads_sale_report.gmv ≤ sum(dwd_order.price)使用Great Expectations框架定义规则 血缘追踪
通过Atlas记录表级血缘 故障时快速定位影响范围
工具推荐:DataLeap(字节)、OneData(阿里)、或自研+Atlas
六、第五阶段:性能优化(踩坑5:Hive查询太慢,BI等半小时)
1. 问题场景
Superset看板加载dws_user_daily
表(10亿行)聚合,耗时15分钟。
填坑方案5:多维度优化
✅ 存储优化
分区字段: dt
(日期) +province
(省份)分桶: user_id
分桶,提升join效率文件格式:ORC + ZSTD压缩(比Text节省70%空间)
✅ 计算优化
Spark配置调优:executor-memory、parallelism 小文件合并:每日凌晨合并ODS层小文件 CBO(Cost Based Optimizer)开启
✅ 查询层优化
引入Doris作为ADS层存储,替代ClickHouse(更易用,支持高并发) 预计算宽表 + 物化视图 Superset开启结果缓存(30分钟)
七、第六阶段:元数据与数据治理(踩坑6:新人看不懂表,文档缺失)
1. 痛点
表名 tmp_jack_20230801
不知道谁建的字段 status
取值含义不明没人知道 ads_user_retention
被哪些报表使用
填坑方案6:元数据管理 + 数据资产化
✅ 落地措施
表/字段注释强制要求
CREATE TABLE dwd_order_detail (
order_id STRING COMMENT '订单ID',
status INT COMMENT '订单状态:1待支付,2已支付,3已发货,4已完成'
) COMMENT '订单明细事实表';数据目录(Data Catalog)
使用Apache Atlas + 自研前端 支持搜索、分类、评分 血缘与影响分析
修改dim_user前,自动提示影响12个ADS表 数据Owner制度
每个主题域指定负责人(如订单域→张三)
八、第七阶段:实时数仓探索(踩坑7:以为实时=Kafka+Spark Streaming)
1. 初期尝试
用Spark Streaming消费Kafka日志,写Hive,延迟5分钟,但:
状态管理复杂 容错困难 无法支持分钟级实时报表
填坑方案7:Flink + Kafka + Doris 实时链路
✅ 新架构
Nginx日志 → Filebeat → Kafka → Flink SQL → Doris → Superset
Flink CDC同步MySQL变更到Kafka Flink SQL做实时聚合(UV、订单统计) Doris支持高并发低延迟查询
实现:实时大屏延迟 < 10秒
九、经验总结:从0到1的7个关键原则
不要重复造轮子:优先用成熟开源组件(Airflow、Flink、Doris) 分层是生命线:没有分层的数仓注定混乱 质量 > 速度:宁可晚两天上线,也要保证数据准确 文档即代码:表结构、血缘、Owner必须可查 监控先行:没有监控的数仓是定时炸弹 小步快跑:先做核心主题(订单、用户),再扩展 业务驱动:始终围绕业务需求迭代,避免过度设计
十、后续规划
引入数据血缘自动解析(解析SQL生成血缘) 建设数据质量评分体系 探索湖仓一体(Iceberg + Spark) 自助取数平台(降低业务方使用门槛)
最后的话:
数据仓库不是项目,而是持续演进的工程。每一个“坑”都是成长的印记。希望这篇真实踩坑日记,能帮你少走两年弯路。
欢迎留言交流你的数仓建设经验。
附:常用工具清单
调度:Airflow / DolphinScheduler ETL:DataX / SeaTunnel 查询引擎:Spark SQL / Presto / Doris 实时:Flink + Kafka 元数据:Atlas / DataHub 监控:Prometheus + Grafana + 自研告警平台
从ODS到ADS:一条SQL的数据奇幻漂流与层层加工之旅 你的数据仓库真的合格吗?京东数据负责人:衡量好坏的6个维度,千万别搞错! 别只回答“做什么”!新业务入仓,说清DWD/DWS的“建仓依据”才是加分项 主题域 vs 数据域:数仓设计不是重复造轮子,90%的人都理解错了! 数据中台建设的首要难题:如何用主题域划分破解“数据孤岛”? 数据仓库分层设计:ODS/DWD/DWS/ADS到底该怎么划边界? 为什么你的DWD层总是混乱?维度建模三件套拯救你! DWS层实战:宽表建模的10个经典场景! 宽表设计避坑指南:哪些字段该加?哪些不该加? ADS层设计指南:面向业务的指标聚合艺术
送你一张优惠券👇






