☰
OLAP实战:电商精准营销人群圈选与预聚合建模
2026/10/21 7:53:50 网站建设 项目流程

做电商数据这块快四年,如果让我挑一个“投入产出比最高”的技术方向,我肯定选 OLAP 在精准营销里的落地。为什么这么说?早几年我在某平台做电商数据,运营要圈一波人群,流程是这样的:提需求给数据组,数据组写 SQL 跑数,运气好半小时出结果,运气不好赶上大促筹备期集群负载高,一个查询等两三个小时都正常。等结果出来,活动预算批完了,再排队建人群包、对接推送通道,整个圈选流程少说半天。后来我们把整套逻辑迁到 OLAP 体系上,同样一个多维条件组合的查询,从半小时缩到秒级,运营在界面上勾勾选选就能自己拉人群。从那一刻开始我才真正意识到,大数据 OLAP 这个东西在电商精准营销里不是锦上添花,而是能把业务效率抬高一个量级的核心基建。

这篇文章我不打算写教科书式的概念堆砌,而是把我实际做过的建模思路、技术选型、踩坑过程完整复盘出来。适合刚接触 OLAP 的数据工程师、数据分析师,以及想给业务搭一套人群圈选系统的团队参考。

1. 这个需求到底在解决什么问题

1.1 电商营销最痛的三件事

做精准营销,第一步永远是“找到该触达的人”。听着简单,做起来全是坑。我总结下来最痛的是三件事。

第一,圈人慢。运营想要“近90天购买金额Top20%且最近30天没来过、同时又偏好某个类目的高价值流失召回人群”,这种多条件组合查询,在原始明细表上硬跑,如果没有合适的索引和预聚合,几十亿行数据就是灾难。早期我们用传统的关系库和跑批任务扛,经常出一个数要等半小时一小时。运营催得急,数据同学压力也大,最后经常是“先按一个简化版条件跑,缺的维度后面再补”,营销效果自然打折。

第二,口径乱。GMV 怎么算?含不含退款?复购率的分母是新客还是全量购买用户?“流失用户”是30天没来还是45天没来?不同业务团队各有一套说法,技术侧如果不做统一口径管理,今天出这个数、明天出那个数,运营拿着两版数字开会,场面非常尴尬。这种问题不解决,后面上再多算法都是白搭。

第三,技术与业务脱节。早期我们做人群包,是要运营提工单的,工单描述里经常是“帮我拉一波高质量用户”。什么叫高质量?得翻译成可计算的指标组合。一来一回沟通成本极高,而且运营真正想要的探索式分析(比如先看下女性用户中哪个价格带转化率高,再基于结果继续下钻)根本没法实现。业务想“玩数据”,技术却被困在“取数据”的泥潭里。

1.2 OLAP 凭什么能解决这些事

OLAP 的核心能力总结成一句话:面向分析场景、支持多维组合查询、用预计算换查询速度。它和传统跑批最大的区别在于,你不需要每次都全量扫描明细数据,而是提前把常用维度的聚合结果算好存起来,查询时直接命中。

举我当时落地的一个例子。我们有一套用户标签宽表,大约 30 亿行,字段有性别、年龄段、城市等级、近30天消费金额、近90天消费频次、偏好类目、会员等级、最近一次活跃时间等。老办法是直接在这个宽表上跑条件过滤,一个复杂查询平均要一分多钟。迁移到 OLAP 引擎并做好预聚合之后,运营前台勾选条件的圈人查询基本稳定在 2 到 3 秒返回。注意,这里说的不是简单 count,而是要把符合条件的用户 ID 明细落成人群包文件。秒级出明细,这在传统模式里是完全不敢想的。

另一个价值是即时下钻。运营在后台看到“华东地区女性用户复购率偏低”,可以继续点进去看是哪个一级类目拖了后腿,再点进去看是哪个价格带、哪个渠道来源有问题。OLAP 的维度模型天然支持这种钻取路径,业务人员自己就能操作,不再需要每次提需求排队等数。这个体验一旦给到业务,技术团队的话语权都会不一样。

2. 核心概念:把 OLAP 讲透

2.1 OLAP 和 OLTP:一个类比讲清楚

很多刚接触数据的同学容易把 OLTP 和 OLAP 搞混。我常用的一个类比是:OLTP 是收银台,OLAP 是仓库盘点。

收银台每秒都要处理很多笔交易,每笔交易就涉及几条记录的读写,但要快、要准确,不能出错。这就是传统业务库干的事,典型特征是行式存储、事务支持(ACID)、索引优化,适合高并发点查和增删改。电商的下单、支付、库存扣减,都依赖这类系统。

仓库盘点则是另一种场景:你不需要关心某一笔具体交易长什么样,你要关心的是“这个月华东区卖了多少”“哪个品类库存周转最慢”“不同价格带的毛利贡献如何”,全都是面向大批量数据的聚合统计。OLAP 就是这个“仓库盘点师”,它不在乎单条记录,关心的是多维度下的汇总结果。

从存储结构上讲,OLAP 引擎大多采用列式存储。因为分析查询通常只读取少数几个字段,列存可以大幅减少 I/O。比如算“近90天消费金额总和”,只需要读金额这一列,行存却会把所有字段都读一遍,高下立判。再加上列存天然对相同类型数据有更好的压缩率,几十亿行的表也能压到很小。

2.2 多维建模:星型模型和雪花模型的取舍

OLAP 的分析离不开“维度”和“度量”这两个概念。

维度就是你看问题的角度,比如时间、城市、品类、用户属性;度量就是你要衡量的数值,比如金额、件数、人数、转化率。把这两者组织起来的方式,最典型的是星型模型:中间一张事实表,周围是多张维度表,事实表通过外键跟维度表关联,整个结构像星星一样辐射出去。

电商场景里,订单事实表记录下单事实,包含一系列外键:用户 ID、商品 ID、门店/城市 ID、时间 ID、渠道 ID,以及金额、数量等度量字段。维度表则分别描述用户信息、商品信息、城市信息等。查询时通过 JOIN 维度表获得维度的具体属性值,然后对度量做聚合。星型模型的好处是查询路径短、理解和维护成本低,特别适合 OLAP 这种“读多写少”的分析场景。

雪花模型是在星型基础上再规范化,比如城市维度再关联省份维度、区域维度。这样存储省了,但查询时 JOIN 层级深了,性能会受影响。在 OLAP 里,我不建议为了省空间而搞雪花模型。事实是,OLAP 引擎更欢迎维度冗余。把省份、区域直接冗余进城市维度表,虽然字段多点,但查询少两次 JOIN,速度更快。列式存储本身压缩率高,那点空间开销完全值得。

2.3 预聚合,这才是 OLAP 快的关键

如果说列式存储是 OLAP 的底子,那预聚合就是灵魂。

所谓预聚合,就是在数据导入时,提前按选定的维度组合把指标算好,存成多粒度结果。查询时如果命中了预聚合粒度,引擎直接读取聚合结果返回,而不是现场去扫描几十亿行明细再 group by。

这个概念可以用一个生活例子理解:你每周要统计家里各项支出总额,如果每次统计时都把三个月的小票翻出来重新加总,效率很低。聪明做法是每天记账时就顺手把当天支出按类目汇总好,想查哪周的直接把对应几天的汇总加起来就行。预聚合就是这个“每天先汇总好的账本”。

实际建模时,预聚合要选哪些维度组合是个技术活。全量预聚合所有维度组合会产生维度爆炸,存储和构建时间都扛不住。当时我们重点关注的是运营高频使用的组合:天粒度的类目、城市、渠道、用户分层,以及周粒度的类似维度组合。低频查询走明细扫描,高频查询走预聚合结果,两端平衡。

要注意的是,预聚合不是建完就一劳永逸。查询条件如果带了维度表上的特殊过滤条件(比如只看某几个商品品牌),可能还是无法命中预聚合粒度,需要引擎做部分查询改写。这个现象我当时调试了很久才彻底搞明白,后面我会单独讲。

3. 方案落地:从数据到人群包

3.1 技术选型与总体架构

讲选型之前先说清楚我们当时面临的数据规模与要求:每天新增订单数据千万级,用户行为日志几亿条,营销人群圈选要求秒级返回,同时要支持近实时更新(至少分钟级能看到最新消费行为)。

传统思路是离线跑批的出数模式,已经证明不够用了。我们转向了 OLAP 体系。技术选型上,我们重点对比过两类方案:一类是基于 MPP 架构的列式 OLAP 引擎,适合高并发明细与聚合查询,部署运维相对简单;另一类是基于预聚合 Cube 的 OLAP 引擎,导入时构建多维 Cube,查询命中极快,适合固定报表和公认度高的分析场景,但对即时探索式查询支持较弱。

综合业务诉求,我们选择了第一款方案为主,并针对运营高频场景额外构建了一些层面的预聚合表。这套组合既满足灵活圈人,又保证常见查询速度。如果你所在团队业务模式偏固定报表,且经常跑超大范围的长周期对比,可以考虑以预聚合 Cube 为主。没有绝对的好坏,关键看是不是匹配你们的查询画像。

总体数据链路长这样:

  1. 业务库通过变更日志采集同步到消息队列;
  2. 消息队列的数据一部分走实时计算做实时指标,一部分落到离线数仓做清洗与维度对齐;
  3. 数仓加工后的明细与汇总层数据同步进 OLAP 引擎;
  4. 营销平台的数据接入层直接查询 OLAP,提供人群圈选与指标看板服务。

整个链路我们一开始就没做复杂的微服务编排,而是尽量用现成组件拼,保证快速跑通。架构简单不等于能力简陋,先把业务跑起来,再逐步迭代。

3.2 指标体系怎么定才不乱

数据建模之前先定指标口径,这个顺序千万别反。我见过太多项目先把表建了,回头再对口径,结果改模型改到怀疑人生。

我们当时和运营、产品开过好几轮对齐会,把核心指标体系钉死成一张表:

指标名称口径定义时间窗口
GMV用户确认收货且未退款的订单金额合计可配置,默认30/90天
复购率周期内购买次数≥2的用户数 / 周期内购买用户数默认90天
高价值用户周期内消费金额降序累计贡献Top20%的用户默认90天
流失预警用户周期内有购买行为但最近活跃时间超过周期阈值的用户默认30天
品类偏好用户周期内消费金额最高的二级类目默认90天
活跃用户周期内有浏览/加购/下单任一行为的用户默认7天

这张表看起来简单,但每个定义背后都有一堆细节。比如“购买次数≥2”算不算取消后又下单?“活跃用户”包不包括仅退款用户?这些都是需要业务确认的。口径定了之后,在数仓加工层做统一标签,确保 OLAP 里查出来的数和报表里的数一致。这一步做扎实之后,团队之间的吵架直接少了一半。

3.3 人群圈选实操:从前端勾选到人群包落库

运营同学在营销后台圈人的操作界面,本质上是把多组条件传给后台的查询服务,生成一段针对 OLAP 的查询 SQL。比如运营想圈“北京、上海、广州三地、最近90天消费金额≥1000元、偏好数码类目、最近7天未活跃”的用户,后台会拼出类似下面这个查询:

SELECT user_id FROM user_profile_fact WHERE city_name IN ('北京', '上海', '广州') AND gmv_90d >= 1000 AND fav_category_level2 = '数码' AND last_active_date < DATE_SUB(CURRENT_DATE, 7)

在实际执行时,这段 SQL 要考虑的不只是条件过滤,还包括几件关键事。

第一,城市字段的维度编码。为了性能,我们会对高频过滤的维度字段做全局字典编码,比较和过滤都用编码后的整型去匹配,而不是直接字符串比较。查询写得很自然,但背后的优化是隐性的。

第二,分区裁剪与二级索引。用户标签表按日期分区,或者按用户 ID 哈希分桶,查询时必须命中对应分区,不然扫描量直接翻倍。条件里有“最近90天”,引擎要能自动定位到相关分区数据,这个靠合理的数据组织来保证。

第三,结果落地。圈选出来的用户 ID 集合要落成人群包,供推送系统调用。我们先用 OLAP 查出符合条件的用户 ID,写入临时结果表,再接入推送目标库。这里有个细节:如果人群包是几十万甚至几百万量级,直接返回到应用层再逐条写入会很慢,效率极低的写法是for循环 insert。正确做法是让 OLAP 引擎直接写出结果文件,或者用INSERT INTO ... SELECT的方式在存储层完成拷贝。这个细节我们在上线第一天就踩了坑,后面会给具体数据。

第四,时效分层。促销大促期间,运营喜欢圈“昨晚刚加购未下单的用户”,这类人群对实时性要求极高,必须在分钟级完成更新。而像“近90天消费金额Top20%”这类长期稳定标签,每天刷一次就够了。所以我们的做法是把人群包拆成“实时人群”和“离线人群”两类,实时人群走增量更新的近实时链路,离线人群按天全量刷新。这样既保证时效,又不会让集群被高频构建任务拖垮。

4. 性能调优和踩坑实录

4.1 慢查询排查:一次圈选等了十分钟

系统上线没多久,就有运营反馈有个圈选页面特别慢,一个查询跑了 10 分钟还没出来。我第一反应是数据量太大、条件太多,但登录引擎监控一看,发现这条查询压根没走预聚合,跑到明细层去全表扫描了。

问题出在一个很低级的环节:运营勾选的过滤条件里带了一个自定义标签。这个标签是运营前一天临时在平台上传的,并没有同步进 OLAP 维表,所以查询引擎无法把它转成预聚合可识别的维度,只能回退到明细层硬算。找到原因后,我们马上建立了“临时标签准入机制”:运营要用的圈人标签,必须先注册到元数据系统里,后台才能针对它生成最优查询计划。在那之后,类似问题基本绝迹。

这个案例给全组上了一课:OLAP 的预聚合优化非常依赖查询形态的稳定,后台做查询生成时必须知道自己有哪些预聚合粒度可用,一旦输出一个“看起来能查但实际要走全量扫描”的 SQL,性能就崩了。

4.2 数据倾斜:爆款商品拖垮了内存

我们有个活动分析报表是按“类目 × 城市 × 渠道”看实时 GMV 的。上线第三天内存就告警了,任务反复失败。看任务日志发现,某个头部主播带过货的大爆款,在“类目=美妆 × 城市=上海”这个组合下数据量是其他组合的上百倍。聚合节点处理这个热点 Key 时内存直接吃不消,其他节点闲得等它算完。

这类问题在电商场景里太典型了。解决思路分两层:

一层是数据分桶粒度的调整。热点 Key 在分桶时被集中到同一个桶,我们改成更细的分桶键,或者在中间层按“商品粒度”先做局部聚合,再跑到上层的“类目粒度”去汇总。相当于把大任务拆成两个小阶段,热点先被消化掉一部分。

另一层是加盐处理。对特别热的 Key 附加一个随机后缀拆分,比如把“美妆”拆成“美妆_0”“美妆_1”等多个虚拟键,让数据分散到不同节点,计算完再合并。加盐虽然有效,但会引入额外的合并层,代码复杂度变高,我们只在确认热点之后才用,不会一上来就加。

调优后的效果是内存稳定了,任务执行时间从 40 分钟降到了 8 分钟。这里我特别想说,OLAP 不是一劳永逸,热点问题会随着业务的爆款出现而反复出现,监控必须跟上。

4.3 维度更新:用户标签每天都在变

做精准营销,维度数据不是静态的。用户今天可能还是“高价值用户”,明天因为一笔退款就掉级了;昨天偏好美妆,今天可能因为连看了几场 3C 直播,偏好就切到了数码。这些变化如果不能及时反映到 OLAP 里,圈出来的人群就带着过期认知。

我们早期犯过一个错:每天凌晨 3 点全量刷新用户标签宽表,结果白天运营圈“最近7天未活跃用户”,发现里面一半人今天早上刚下过单。数据是对的,只是刷新太晚了。后来我们优化成“全量日更 + 实时增量打标”的混合模式:基线标签每日凌晨更新,实时行为标签(如最近活跃时间、当日加购状态)通过实时流直接更新到 OLAP 的对应字段,保证关键时效字段是“新鲜”的。

做这个改造最大的坑在于历史数据的回刷。维度更新时装了新的分区,但事实表里的历史数据也需要按新维度重新对齐。比如用户对类目的偏好标签变了,那么他过去 90 天的所有订单记录,是否也要用新标签去回溯?如果回溯不一致,报表和圈人结果就可能前后矛盾。我们的处理方式是:事实明细表里的订单记录保留原始事实不变,用户偏好标注在用户维度表更新,查询时以“当前偏好”为准。这样口径稳定,运营也好理解。如果业务里确实需要“历史事实用历史标签”来复现某个时点人群,就得做时点快照,存储成本高不少,需要跟业务确认是否真的需要。

4.4 查询改写:为什么我建的预聚合不生效

前面提过预聚合“不生效”的问题,这里展开讲。技术团队当时花了好几天排查一个诡异现象:明明建了“天级 × 城市 × 品类”的预聚合表,查询“最近 7 天上海的数码类目 GMV”时,引擎还是走了明细扫描。

原因是查询里的时间条件被改写成了“大于某天且小于某天”,而预聚合表的时间粒度是“天”,引擎在识别聚合粒度时发现查询涉及 7 个不同的天,它选择把 7 天对应的预聚合结果累加。这本该是正确且高效的路径,但旧版本引擎在这个场景下的优化器有缺陷,没有自动做“日期序列展开后命中多个预聚合分区”的推断,于是回退到了明细层。

排查思路是这样的:拿到慢查询 SQL 之后,看执行计划,发现预聚合表的扫描行数为 0,明细表扫描行数几十亿。再结合测试,手动把查询改成WHERE date_col = '2024-01-01' UNION ALL ...这种单日期枚举形式,发现能命中预聚合。确认是优化器对日期范围的处理问题之后,我们去看了版本更新日志,升级引擎版本后问题解决。

这个案例给我们的教训是:建完预聚合表不是结束,必须定期抽样验证关键查询的命中情况。可以把执行计划里的扫描行数和耗时做监控,一旦发现“应该快却慢了”的查询,立刻查执行计划。很多团队建完模型就松一口气,结果线上跑的还是全量扫描,预聚合成了摆设,这才是最冤的。

5. 几条经验总结

5.1 千万别踩的坑

结合前后几次项目经验,我整理了一个速查表,也给你一份避坑清单:

问题现象建议
口径未统一就建模报表对不上、来回返工先花一周对齐指标体系,再开始建表
预聚合粒度拍脑袋查询命中率低、存储膨胀按实际查询日志统计高频维度组合,按需预聚合
临时标签绕过元数据查询回退明细层、性能暴跌建立标签准入机制,统一注册到元数据
热点 Key 不处理任务内存溢出、长尾严重监控热点,必要时分桶调整或加盐
维度更新不及时人群带过期标签、投放效果差全量日更 + 实时增量打标混合
统一走明细查询慢且浪费资源合理利用预聚合,定期验证查询计划

这里面我最想强调的还是口径和预聚合。数据团队经常把精力花在“怎么算得快”上,却忽略了“算得对”这个前提。口径对不上,查得快又有什么用呢?

5.2 一点经验体会:OLAP 是手段不是目的

做完这个项目之后,我最大的体会是:OLAP 再快,也只是把“取数”这个环节的摩擦力降到了最低,真正值钱的是业务人员能不能基于数据做出更好的决策。

以前运营问我“最近母婴类目是不是不行了”,我可能要一两天才能给出一个多维度对比分析。现在运营自己打开看板,从类目下钻到品牌、价格带、渠道归因,10 分钟就能得出结论。数据团队从“取数的”真正变成了“搭数据基础的人”,这个转变带来的成就感比任何技术指标都强。

给即将做类似项目的人一个建议:不要一上来就追求完美的建模和全场景覆盖。先把最高频的 3 到 5 个营销场景做透,跑通一版,让业务看到秒级的体验变化,后面再逐步扩展维度和场景。项目最怕的不是技术难,而是做了半年业务觉得没变化,那就很难收场了。

另外,一定要把监控和预警做起来。OLAP 系统上线后,慢查询、预聚合命中率、内存水位、构建任务积压,这几个指标一定要盯。我们中间有过一次因为凌晨构建任务堆积导致早上运营圈人数据滞后,非常被动。后来加了链路健康检查,任何环节延迟超过阈值立刻告警,才算让人睡上安稳觉。

最后再分享一个小技巧:业务侧的圈人页面,一定要记住把“可选的高频筛选条件”限制在注册过的维度集合内。一方面避免全量扫描,另一方面让运营的探索在可控范围内进行。页面上一个简单的下拉框限制,背后省下的可是集群的巨大计算量。这一点,对任何准备上线圈人系统的团队都适用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询