上周跟南京河西某互联网公司的数仓组长在大排档吃龙虾,他扒着虾壳吐槽,上个月运营部临时要拉一份新用户复购报表,本来以为半天就能出结果,翻到数仓里的用户表才发现,3个月前产品加的“用户来源渠道”字段没人同步进ETL链路,连当时的调度日志都被运维当垃圾清了一半,熬了两个大夜才把拼凑的数导出来,差点没赶上老板的月度经营会。
数仓不是把数据堆起来就行
很多刚入行的小孩对数据仓库的认知,还停留在“把业务库的表抽过来存着,查的时候直接捞”,那真的是把这事儿想简单了。业务库是面向实时交易设计的,订单表为了写入快,可能会冗余存用户当时的会员等级、收货地址甚至实时的优惠券金额,今天运营要把去年双11的订单按用户当时的会员等级拆出贡献占比,你总不能去翻业务库存了快一年的binlog吧?
数仓的核心从来不是存数据,是把散在各个业务链路里的、带时间维度的、不会随便随业务库变动的业务属性给沉淀下来。我刚入行的时候跟着老大哥做数仓,他当时说,数仓工程师最核心的能力,不是会写多么复杂的嵌套SQL,是能站在业务的角度想清楚:这个数据存进来,以后要给谁用,要用来算什么指标,会不会有一天业务规则变了,现在存的东西还要不要用。那时候我还觉得他说的太玄乎,直到后来碰到一个项目,团队图省事把用户的注册渠道字段直接存在了订单事实表里,后来公司把渠道归因规则从“首次注册渠道”改成了“末次点击渠道”,所有历史订单的渠道归属全乱了,重新洗了整整一周的数才把问题解决,那时候才懂他说的话是什么意思。

之前见过一个小团队,图省事根本不分层,所有表都扔在同一个库里,今天加个字段,明天改个计算逻辑,到第三个月的时候,连写SQL的人自己都分不清哪张表是算GMV的,哪张是算用户留存的,每次出数都要挨个找字段对,错了就互相甩锅。哎,真的,省下来的分层设计的时间,最后全要在半夜赶报表的时候加倍还回去。
那些没人跟你说的数仓隐形坑
第一个坑,就是把维度表当成静态表存。比如用户的会员等级,从普通用户升到白银,3个月前的用户行为关联的等级是普通,结果你把维度表直接更新成白银,回头算历史复购率的时候,把所有老用户都算成白银等级的贡献,老板拿着报表去跟行业对标,差了快30%,你说你慌不慌?
所有跟业务属性相关的维度表,必须做拉链表,哪怕你团队小到只有3个数仓开发,这个规矩不能破。别觉得麻烦,等你要回溯半年前的用户标签、渠道属性的时候,就知道这个设计能帮你省多少事。

还有个常见的坑,就是为了查询快,把所有预计算的宽表都提前算到极致。比如算用户月活,把用户过去12个月的所有浏览、下单、支付行为全拼在一张宽表里,刚开始查确实快,等过了半年,用户量翻了三倍,宽表的体积涨了8倍,每天的ETL任务从原来的2小时跑不完,直接拖到业务部早上上班了还没出数,那才叫尴尬。之前有个做零售的客户就是这么干的,后来实在扛不住,把大宽表拆成一层一层的聚合,平时查常用的核心指标就走汇总层,要拆细维度就往下钻,反而比原来的大宽表跑的快,存储资源还省了一半。
小团队做数仓根本不用搞的太复杂
很多人一听说数仓,就觉得得买几百万的商业软件,得搭几十节点的集群,小团队根本玩不起。说实话,真不是。你要是团队规模在20人以下,业务也就电商加本地生活两个板块,根本没必要上来就追什么实时数仓、湖仓一体的新概念。先把最基础的三层搭起来就行:最上层贴业务库的ODS层,什么都别改,原封不动把业务表抽过来,留够3个月的历史数据兜底;中间DWD层,把脏数据洗干净,把业务过程拆成一个个独立的事实表,比如下单、支付、页面浏览,别全混在一张表里;最下层DWS层,就把业务部经常要的几个固定指标算好,比如日活、GMV、复购率,存成汇总表,查的时候直接捞。对吧?
别总追着新名词跑,什么Data Mesh,什么流批一体,等你团队规模到了上百人,每天要处理几十亿条数据的时候,再考虑这些东西完全来得及。之前有个做本地生活的小团队,上来就跟风搞湖仓一体,折腾了三个月,连最基础的日活报表都算不准,最后把技术栈全换回去,老老实实搭传统数仓,两周就把所有核心报表都跑顺了,省下来的时间都去对接业务需求了,不比天天折腾新技术强?
对了,别上来就把数仓的权限全放开,什么人都能进库改表,今天这个加个字段,明天那个删个分区,不出三个月,你的数仓就变成没人敢碰的黑盒。哪怕是小团队,也要定个简单的规矩:所有表的变更必须提个申请,写清楚改了什么,为什么改,影响哪个下游的报表,改完了要同步给所有用这张表的人。听着麻烦?真等出了数不准的问题,你挨个查哪张表被谁动过,那才叫真的麻烦。
其实数仓这东西,从来不是什么高大上的技术架构。你做的好不好,根本不用看你用了多少顶尖的开源组件,就看业务部的人要数的时候,能不能10分钟之内拿到准确的数,不用半夜追着数仓开发问为什么今天的GMV对不上。