暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

从0到1的数据仓库建设日记:记录踩过的每一个坑和填坑方案

陈乔数据观止 2025-09-10
59
作者:陈乔怀古资深数据仓库工程师

关注公众号:【陈乔数据观止】,回复关键字:【资料】,进社群下载全部 word/ppt/pdf 文件。

添加v:cqhg_bigdata,备注数仓,领取美团外卖实时数仓建设实践文档👇

一、背景与目标

案例公司是一家快速发展的电商SaaS平台,初期所有数据都存储在业务MySQL数据库中。随着业务增长,报表查询变慢、数据口径混乱、分析需求无法满足等问题频发。老板一句“我们需要一个数据仓库”,让我从零开始搭建整套数据体系。

目标:

  • 统一数据出口,解决数据孤岛问题
  • 支持多维度、灵活的报表分析
  • 支撑用户行为分析、营销效果评估
  • 为未来数据中台打基础

二、第一阶段:选型与架构设计(踩坑1:技术选型拍脑袋)

1. 初始选型

组件
初始选择
理由(当时的理解)
存储
MySQL
熟悉,开发快
ETL
Python脚本
灵活,可控
调度
Crontab
简单
查询
Superset
可视化好

结果: 两周后崩溃。订单表日增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维度建模 + 分层设计

层级
命名
职责
示例
ODS
ods_*
原始数据镜像,不做清洗
ods_order_info
DWD
dwd_*
明细事实表,维度退化
dwd_order_detail(含user_level)
DWS
dws_*
轻度汇总,按主题域
dws_user_daily(用户日行为)
ADS
ads_*
应用层,直接对接BI
ads_sale_report

关键实践:

  • DWD层保持原子性,DWS层按“用户、商品、订单”等主题域聚合
  • 所有ADS只依赖DWS/DWD,不跨层跳读
  • 使用一致的维度表(如dim_user, dim_product)

四、第三阶段:ETL开发与调度(踩坑3:脚本化ETL,无版本管理)

1. 问题描述

初期用Python写ETL脚本,存放在本地,通过crontab调用。很快出现:

  • 脚本版本混乱(同事改了没通知)
  • 日志不统一,出错难排查
  • 无法重跑历史数据

填坑方案3:Airflow + Git + 模板化SQL

✅ 标准化ETL流程

  1. Airflow调度

    • DAG按主题域划分:dwd_order_dag.py
      dws_user_dag.py
    • 依赖关系可视化:ODS → DWD → DWS → ADS
    • 邮件告警 + 钉钉机器人通知
  2. 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}'

  3. Git管理

    • 所有SQL、DAG脚本纳入GitLab
    • 分支策略:dev → test → prod
    • Code Review强制执行

五、第四阶段:数据质量保障(踩坑4:数据不准,背锅无数次)

1. 典型事故

某次营销活动报表显示“订单量下降50%”,业务部门紧张,结果发现是ETL漏跑了一天,但没人发现。

填坑方案4:建立数据质量监控体系

✅ 四层保障机制

  1. 基础监控

    • 表数据量波动告警(±30%触发)
    • 分区缺失检测(如ods表没生成dt=2023-08-01)
    • 字段空值率监控(如user_id为空>5%告警)
  2. 一致性校验

    • ODS与源库数据量比对(每日自动校验)
    • ADS与DWS聚合结果交叉验证
  3. 业务规则校验

    • 示例:ads_sale_report.gmv ≤ sum(dwd_order.price)
    • 使用Great Expectations框架定义规则
  4. 血缘追踪

    • 通过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:元数据管理 + 数据资产化

✅ 落地措施

  1. 表/字段注释强制要求

    CREATE TABLE dwd_order_detail (
        order_id STRING COMMENT '订单ID',
        status INT COMMENT '订单状态:1待支付,2已支付,3已发货,4已完成'
    COMMENT '订单明细事实表';

  2. 数据目录(Data Catalog)

    • 使用Apache Atlas + 自研前端
    • 支持搜索、分类、评分
  3. 血缘与影响分析

    • 修改dim_user前,自动提示影响12个ADS表
  4. 数据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个关键原则

  1. 不要重复造轮子:优先用成熟开源组件(Airflow、Flink、Doris)
  2. 分层是生命线:没有分层的数仓注定混乱
  3. 质量 > 速度:宁可晚两天上线,也要保证数据准确
  4. 文档即代码:表结构、血缘、Owner必须可查
  5. 监控先行:没有监控的数仓是定时炸弹
  6. 小步快跑:先做核心主题(订单、用户),再扩展
  7. 业务驱动:始终围绕业务需求迭代,避免过度设计

十、后续规划

  • 引入数据血缘自动解析(解析SQL生成血缘)
  • 建设数据质量评分体系
  • 探索湖仓一体(Iceberg + Spark)
  • 自助取数平台(降低业务方使用门槛)

最后的话:
数据仓库不是项目,而是持续演进的工程。每一个“坑”都是成长的印记。希望这篇真实踩坑日记,能帮你少走两年弯路。

欢迎留言交流你的数仓建设经验。


附:常用工具清单

  • 调度:Airflow / DolphinScheduler
  • ETL:DataX / SeaTunnel
  • 查询引擎:Spark SQL / Presto / Doris
  • 实时:Flink + Kafka
  • 元数据:Atlas / DataHub
  • 监控:Prometheus + Grafana + 自研告警平台

据统计,99%的大咖都关注了这个公众号👇
大家都在看👇
  1. 从ODS到ADS:一条SQL的数据奇幻漂流与层层加工之旅
  2. 你的数据仓库真的合格吗?京东数据负责人:衡量好坏的6个维度,千万别搞错!
  3. 别只回答“做什么”!新业务入仓,说清DWD/DWS的“建仓依据”才是加分项
  4. 主题域 vs 数据域:数仓设计不是重复造轮子,90%的人都理解错了!
  5. 数据中台建设的首要难题:如何用主题域划分破解“数据孤岛”?
  6. 数据仓库分层设计:ODS/DWD/DWS/ADS到底该怎么划边界?
  7. 为什么你的DWD层总是混乱?维度建模三件套拯救你!
  8. DWS层实战:宽表建模的10个经典场景!
  9. 宽表设计避坑指南:哪些字段该加?哪些不该加?
  10. ADS层设计指南:面向业务的指标聚合艺术

送你一张优惠券👇

扫码加入星球🪐 所有资料都可以直接下载

文章转载自陈乔数据观止,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论