做数据仓库三年了,从最开始的入门到现在的深入,踩了不少坑,也积累了一些经验。本文分享我做数据仓库三年的感悟和经验,包括数据建模、数仓分层、ETL开发、数据质量、性能优化、团队协作等方面的体会。这些道理,很多都是踩坑踩出来的,希望能帮正在做数据仓库的你少走弯路。

一、数据建模:不要过度设计,也不要不设计

刚做数据仓库的时候,我在数据建模上走了两个极端。

最开始,我觉得数据建模不重要,先把数据跑起来再说。结果,表结构随意设计,字段命名不规范,数据关系混乱。后来业务需求变了,要加字段、改表结构,发现牵一发而动全身,改起来非常痛苦。而且,数据口径不一致,同一个指标在不同的表里有不同的定义,导致报表数据对不上,业务方质疑数据的准确性。

后来,我又走向了另一个极端,过度设计。我花了大量时间设计完美的模型,考虑了各种可能的业务变化,设计了非常复杂的表结构和关系。结果,模型太复杂,开发和维护都很困难,新人根本看不懂。而且,很多设计的"扩展性"根本用不上,业务并没有按照我预想的方向发展,过度设计的部分成了负担。

用了三年我才明白,数据建模要适度。既不能不设计,也不能过度设计。

好的数据建模应该是:

  • 贴合业务:模型要反映真实的业务过程,而不是凭空想象。理解业务是建模的前提,要和业务方充分沟通,理解业务流程和数据含义
  • 适度抽象:在当前需求的基础上,做适度的抽象和扩展,应对可预见的业务变化。但不要为了不可预见的未来过度设计
  • 命名规范:表名、字段名要有统一的命名规范,见名知意。这是最基本但也最重要的
  • 口径一致:同一个指标,在整个数仓中只有一个定义。建立指标管理体系,确保口径一致
  • 文档完善:每个表、每个字段都要有文档说明,包括含义、来源、计算逻辑等。没有文档的数仓是不可维护的

我现在的做法是,先理解业务,再设计模型。设计的时候,满足当前需求为主,适度考虑可预见的扩展。不追求完美,追求够用、好用、可维护。模型上线后,根据业务反馈持续迭代优化,而不是一开始就想设计一个完美的模型。

二、数仓分层:分层是为了解耦,不是为了分层而分层

数仓分层是数据仓库的基本概念。常见的分层方式是ODS(操作数据层)、DWD(明细数据层)、DWS(汇总数据层)、ADS(应用数据层)。

刚做数据仓库的时候,我对数仓分层的理解很肤浅,觉得就是把数据分成几层,每层做一些处理。结果,分层变成了形式主义。

我遇到的问题:

  • 分层不清晰,ODS层做了DWD的事情,DWD层做了DWS的事情,边界模糊
  • 为了分层而分层,本来一层就能搞定的事情,硬要分成三层,导致数据链路长,开发和维护成本高
  • 跨层依赖严重,ADS层直接读ODS层的数据,绕过了中间层,分层失去了意义
  • 数据冗余严重,同样的数据在多层都有存储,浪费存储空间,也导致数据不一致

用了三年我才明白,数仓分层的目的是解耦,是为了让每一层各司其职,降低复杂度,提高可维护性。分层不是目的,而是手段。

好的数仓分层应该是:

  • 职责清晰:每一层有明确的职责。ODS层贴源,保留原始数据;DWD层清洗、脱敏、维度退化,做明细数据;DWS层按主题汇总,做轻度汇总;ADS层面向应用,做指标和报表
  • 单向依赖:上层只能依赖下层,不能下层依赖上层,也不能跨层依赖。ADS依赖DWS,DWS依赖DWD,DWD依赖ODS,形成清晰的依赖链
  • 适度分层:不是层数越多越好。根据业务复杂度和数据量,选择合适的分层方式。简单的业务,三层就够了;复杂的业务,可以分更多层
  • 避免冗余:每一层的数据有明确的用途,避免同样的数据在多层重复存储。需要汇总的数据在DWS层,需要明细的数据在DWD层,不要重复
  • 公共层下沉:公共的维度和指标,尽量下沉到公共层(DWD/DWS),避免在ADS层重复计算。公共逻辑只写一次,多处复用

我现在的做法是,严格遵守分层规范,每一层只做自己该做的事情。开发的时候,先想清楚这个表应该放在哪一层,为什么放在这一层。定期审查数据链路,发现跨层依赖和冗余,及时整改。

三、ETL开发:写代码容易,写好代码难

ETL(Extract-Transform-Load)是数据仓库最基础的工作。刚做数据仓库的时候,我觉得ETL很简单,就是写SQL把数据从一个表搬到另一个表,做一些清洗和转换。

但做了三年我才发现,写ETL代码容易,写好ETL代码很难。

我遇到的问题:

  • SQL写得很随意,没有注释,没有格式,过一段时间自己都看不懂
  • 没有考虑异常情况,数据有问题的时候,ETL直接报错或者产出错误数据,没有容错和告警
  • 没有幂等性,重跑的时候会产生重复数据或者数据不一致
  • 没有考虑性能,数据量小的时候跑得挺快,数据量大了之后跑得很慢,甚至跑不出来
  • 没有日志,ETL跑了多久,处理了多少数据,有没有异常,都不知道,出了问题很难排查

用了三年我才明白,ETL不是简单的SQL,而是工程。好的ETL代码,要考虑可读性、健壮性、性能、可维护性。

好的ETL开发应该是:

  • 代码规范:SQL格式规范,有注释,有明确的逻辑分段。表别名、字段命名统一,让人一眼就能看懂
  • 幂等性:ETL任务可以重复执行,不会产生重复数据或数据不一致。用分区覆盖、主键去重等方式保证幂等
  • 异常处理:考虑各种异常情况,数据为空、数据格式错误、主键冲突等。有异常处理逻辑,有告警机制,出了问题能及时发现
  • 性能优化:考虑数据量和执行效率,合理使用分区、索引、join策略。避免全表扫描,避免数据倾斜,避免笛卡尔积
  • 日志和监控:ETL执行过程中有日志,记录开始时间、结束时间、处理数据量、异常信息。有监控,任务失败或超时能及时告警
  • 可测试性:ETL逻辑可以测试,有测试用例,确保逻辑正确。修改代码后,能快速验证是否正确

我现在写ETL,会先想清楚逻辑,再写代码。写的时候注意格式和注释,写完之后测试,考虑异常情况,做性能优化。上线后有监控和告警,出了问题能及时发现和处理。虽然花的时间多了,但后期维护的成本大大降低了。

四、数据质量:数据质量是数仓的生命线

刚做数据仓库的时候,我最关注的是能不能把数据跑出来,报表能不能展示。对数据质量不够重视。

结果,数据质量问题频发:

  • 报表数据对不上,同一个指标在不同的报表里数值不一样
  • 数据突然变成0或者null,因为上游数据源出了问题,没有及时发现
  • 数据重复,因为ETL任务重跑了,没有去重
  • 数据延迟,T+1的数据到了下午还没出来,业务方等着用
  • 口径不一致,业务方理解的指标和数仓里的指标定义不一样,导致争议

这些问题,严重影响了业务方对数据仓库的信任。业务方开始质疑数据的准确性,甚至不愿意用数据仓库的数据,宁愿自己在Excel里算。

用了三年我才明白,数据质量是数据仓库的生命线。没有数据质量,数据仓库就没有价值。业务方信任数据,才会用数据;不信任数据,再漂亮的报表也没用。

好的数据质量管理应该是:

  • 数据质量监控:建立数据质量监控体系,监控数据的完整性、准确性、一致性、及时性、唯一性。关键表和关键指标要有质量监控规则,出了问题自动告警
  • 数据血缘:建立数据血缘,清楚每个表、每个字段的来源和去向。出了问题能快速溯源,找到影响范围
  • 口径管理:建立指标管理体系,每个指标有明确的定义、计算逻辑、来源。业务方和数仓团队对口径有一致的理解,避免争议
  • 数据校验:ETL任务中有数据校验逻辑,比如主键非空、数值范围、枚举值校验等。数据不符合预期的时候,告警或者阻断
  • 数据回溯:有数据回溯机制,发现数据质量问题后,能快速回溯历史数据,修复问题
  • 质量文化:在团队中建立数据质量文化,每个人都对数据质量负责。不是某一个人的事情,而是整个团队的事情

我现在做数据仓库,把数据质量放在第一位。每个表上线前都要做数据质量校验,关键指标有监控和告警。定期做数据质量审计,发现问题及时整改。虽然花了很多精力在数据质量上,但业务方对数据的信任度大大提升了,数据仓库的价值也得到了认可。

五、性能优化:不要过早优化,也不要不优化

数据仓库的性能优化是一个永恒的话题。刚做数据仓库的时候,我在性能优化上也走了两个极端。

最开始,我不重视性能优化。觉得先把功能做出来,性能以后再说。结果,数据量小的时候没问题,数据量一大,任务跑得越来越慢,甚至跑不出来。报表要等很久才能出数据,业务方抱怨不断。

后来,我又走向了另一个极端,过度优化。每个任务都要花大量时间优化,追求极致的性能。结果,开发效率很低,很多优化的收益并不大,投入产出比很低。而且,过度优化的代码往往很复杂,难以维护。

用了三年我才明白,性能优化要适度。不要过早优化,也不要不优化。

好的性能优化应该是:

  • 先监控再优化:不要凭感觉优化,先监控,找到真正的性能瓶颈。用执行计划、任务日志、资源监控等工具,找到慢在哪里,再有针对性地优化
  • 关注高投入产出比的优化:优先优化那些耗时最长、影响最大的任务。20%的任务可能占了80%的运行时间,先优化这20%
  • 合理使用分区和索引:分区是大数据量下最有效的优化方式。按日期、地域等常用过滤条件分区,避免全表扫描。索引在数仓中用得不多,但在某些场景下也有用
  • 避免数据倾斜:数据倾斜是分布式计算中最常见的性能问题。join和group by的时候,注意key的分布,避免某个key的数据量特别大
  • 合理设置并行度:并行度太低,资源利用不充分;并行度太高,调度开销大。根据数据量和集群资源,设置合理的并行度
  • 不要过度优化:对于运行时间可接受的任务,不要花太多时间优化。性能优化是有成本的,要考虑投入产出比。满足业务需求就行,不需要追求极致

我现在的做法是,先让任务跑起来,满足功能需求。然后监控任务的运行时间,找到最慢的任务,针对性优化。优化的时候,先做投入产出比高的优化(比如加分区、调整并行度),再做复杂的优化。对于运行时间可接受的任务,不过度优化。

六、需求沟通:理解业务比技术更重要

刚做数据仓库的时候,我觉得自己是做技术的,把技术做好就行。需求来了,按照需求做就行,不需要太多沟通。

结果,做出来的东西经常不符合业务方的预期:

  • 业务方要的是这个口径,我理解的是另一个口径,做出来的数据对不上
  • 业务方要的是实时报表,我做成了T+1,满足不了需求
  • 业务方要的是灵活的自助分析,我做成了固定报表,不好用
  • 业务方的需求变了,我没有及时跟进,做出来的东西已经过时了

这些问题,本质上都是沟通不到位,对业务理解不够。

用了三年我才明白,数据仓库是为业务服务的,理解业务比技术更重要。技术再好,做出来的东西不符合业务需求,也没有价值。

好的需求沟通应该是:

  • 深入理解业务:花时间了解业务,了解业务流程、业务指标、业务痛点。只有理解了业务,才能做出符合业务需求的数据产品
  • 主动沟通:不要等业务方来找你,主动和业务方沟通,了解他们的需求和痛点。定期和业务方开会,同步进展,收集反馈
  • 确认需求:需求来了,不要急着做,先和业务方确认需求。包括指标口径、数据频率、展示方式、使用场景等。确认清楚了再做,避免返工
  • 管理期望:对于不合理的需求,或者暂时做不到的需求,要和业务方沟通,管理期望。不要什么都答应,最后做不到,失去信任
  • 持续迭代:数据仓库不是一次性的项目,而是持续迭代的过程。根据业务反馈,持续优化和完善,让数据产品越来越好用
  • 数据赋能:不只是被动地满足需求,还要主动地用数据赋能业务。发现业务中的问题和机会,提供数据洞察,帮助业务做决策

我现在做数据仓库,会花很多时间和业务方沟通,理解业务需求。需求来了,先确认清楚再做。做的过程中,及时同步进展,收集反馈。上线后,持续跟踪使用情况,根据反馈迭代优化。虽然花了很多时间在沟通上,但做出来的东西更符合业务需求,业务方的满意度也更高了。

七、团队协作:数据仓库不是一个人的战斗

刚做数据仓库的时候,我觉得数据仓库就是写SQL,一个人就能搞定。后来发现,数据仓库涉及到很多方面,不是一个人能做好的。

我遇到的问题:

  • 上游数据源的同学不配合,数据格式变了不通知,导致ETL报错
  • 下游报表的同学不理解数仓的结构,直接读底层表,导致口径不一致
  • 团队成员的开发规范不统一,每个人写的SQL风格不一样,维护困难
  • 没有代码评审,代码质量参差不齐,bug很多
  • 知识不共享,某个人走了,他负责的部分就没人懂了

用了三年我才明白,数据仓库不是一个人的战斗,而是团队协作的结果。需要和上游、下游、业务方、团队成员紧密协作,才能做好数据仓库。

好的团队协作应该是:

  • 统一规范:团队有统一的开发规范,包括命名规范、SQL格式、分层规范、文档规范等。所有人都遵守规范,保证代码的一致性和可维护性
  • 代码评审:所有代码上线前都要经过评审,发现问题及时修改。代码评审不仅能保证质量,还能促进知识共享
  • 知识共享:定期组织技术分享,分享经验和心得。建立知识库,记录常见问题、最佳实践、技术方案等。避免知识只掌握在某个人手里
  • 跨团队协作:和上游数据源团队、下游应用团队建立良好的协作关系。数据格式变更要提前通知,接口变更要协商,出了问题一起排查
  • 责任明确:每个模块、每个表都有明确的负责人。出了问题知道找谁,避免推诿
  • 持续学习:数据仓库技术发展很快,团队要持续学习,跟进新技术、新方法,不断提升团队的能力

我现在做数据仓库,很重视团队协作。和上游、下游保持良好的沟通,团队内部有统一的规范和代码评审,定期做知识分享。虽然协作需要花时间,但整体效率和质量都提升了,也避免了很多因为沟通不畅导致的问题。

八、写在最后

做数据仓库三年,最大的感悟是:数据仓库不只是技术,更是工程、业务和协作的结合。

技术是基础,没有好的技术,做不出好的数据仓库。但只有技术是不够的,还需要理解业务,需要数据质量,需要团队协作,需要持续迭代。

这三年,我踩了很多坑,也学到了很多。从最开始的只关注技术,到现在关注业务、质量、协作,我对数据仓库的理解越来越深入。我也越来越觉得,数据仓库是一个需要长期投入、持续打磨的事情,没有终点,只有不断的优化和进步。

如果你正在做数据仓库,希望我的这些经验能帮到你。不要怕踩坑,踩坑是成长的必经之路。重要的是,踩坑之后要总结经验,避免再踩同样的坑。

最后,用一句话结束本文:"数据仓库是一场马拉松,不是百米冲刺。保持耐心,持续迭代,时间会给你答案。"愿每一个做数据仓库的同学,都能在这条路上越走越远,越走越好。