广告投流第一战:如何用 StarRocks 搞定“起量监控”与“素材优选”?

5 阅读15分钟

在广告投放的全链路漏斗中,流量请求 → 流量识别 → 广告召回 → 出价竞价 → 胜出反馈 → 展示→ 点击→ 数据回收是完整闭环。

本篇作为广告投流系列第一篇,完整梳理整个漏斗,并聚焦展示→点击阶段的 StarRocks 实时分析能力,解决“出价/素材实时监控”与“素材创意优选”两大难题。同时结合 Pinterest 真实生产案例,展示方案在亿级规模广告场景下的落地效果。

一、广告投放完整漏斗分析

广告投流本质上是多阶段漏斗,每一环都存在损耗, 本文 StarRocks 方案主要服务于阶段三的实时监控与决策,同时通过分钟级数据反馈反哺阶段一、二的召回与出价优化。

1.1 阶段一:请求阶段(流量进入→识别→召回→出价)

流量进来后,系统首先要做的是识别流量,匹配人群与定向,再进行广告召回和出价决策。

1.2 阶段二:竞价反馈阶段(胜出通知 → 展示准备)

竞价成功后,DSP 会收到反馈,进入投放阶段的展示环节,但竞价成功与实际展示之间存在漏斗损失(fill rate、超时、可见性等)。

1.3 阶段三:  展示交互与数据回收阶段(展示→点击→转化)

在投放交付阶段,展示后产生点击,数据实时回收,形成闭环监控与优化。

1.4 漏斗整体损耗关键点分析

  • 请求多 → 召回少(召回率低)
  • 竞价胜出 → 实际展示少(Win-to-Impression 损失)
  • 展示多 → 点击少(CTR 低)

通过以上三个阶段的完整漏斗分析,可见展示→点击阶段的 CTR 直接影响 eCPM 排名,是起量成败的最关键变量。本文 StarRocks 方案主要针对阶段三的实时监控与素材优选,同时通过数据闭环反哺前序召回与出价,实现全链路提效。

二、业务方案分析

2.1 经典永不过时:eCPM 公式拆解  (广告主视角)

广告系统的核心竞价公式:

eCPM (effictive cost per miile)=出价*CTR*CVR*1000
  • 出价: 广告主愿意为高潜力流量支付的金额
  • 点击率(CTR):点击次数 ÷ 曝光次数,反映创意素材的吸引力, 起量阶段最关键变量(直接影响 eCPM 排名)
  • 转化率(CVR) :转化数 ÷ 点击数,用于优化素材、出价与用户路径,提升 ROI

在程序化广告(RTB/竞价)中:

  • 广告主看到的是“我的 eCPM 出价 / 预估成本”(系统根据出价 + 预估 CTR/CVR 计算的千次展示预估花费)
  • 广告商看到的是“广告位的 eCPM 收入”

eCPM(千次展示有效收益)本质上是广告系统对单次展示价值的综合预估,它直接决定了广告在竞价排序中的竞争力(eCPM 越高 → 排名越靠前 → 曝光机会越多  → 起量越轻松)。

如上文完整漏斗所示,在展示-点击阶段,CTR 是最为关键的变量。提升 CTR 不仅能直接降低点击成本(CPC),还能显著提高 eCPM,从而在竞价队列中获得更多胜出机会。一份高 CTR 的广告足以证明其创意、文案、视觉设计或目标定向足够吸引用户。

CTR 诊断三类情况:

  • 高 CTR + 低 CVR:广告吸引力强,但落地页或产品难以满足预期,需优化转化链路;
  • 低 CTR + 高 CVR:广告定向精准但曝光不足,应扩大人群覆盖或改进创意;
  • 双低指标:需从定向、创意、落地页全链路排查问题。

2.2 适用对象

本方案主要面向广告主的投放团队、增长团队以及运营团队,特别适用于以下场景:

  • 新账户冷启动阶段: 需要快速找到精准人群;
  • 老账户遭遇起量瓶颈: 展示量或者点击率持续低迷;
  • 多素材并行测试: 需要实时监控各素材表现, 并快速决策。

2.3 业务痛点

在流量获取阶段,运营人员通常面临三大核心痛点:

(1)冷启动困难

新账户/新素材/新计划上线后,平台算法(如 oCPM/oCPC/oROI)需要积累足够样本(点击、转化数据)来学习和匹配人群。没有历史数据 → 系统不敢给优质流量 → 曝光少 → 起量慢 → 预算烧得慢或烧不出去。

这对广告主来说是典型的高成本低效率阶段:钱花了但没效果,测试期拉长,试错成本高。

(2)素材衰退

素材衰退:老素材 CTR 下滑(用户审美疲劳)→ eCPM 下降 → 排名掉 → 曝光减少 → 量级萎缩。广告主需要不断迭代创意,否则 ROI 崩。

(3)空跑浪费

空跑:高曝光但低点击/无转化 → 预算白烧(无效流量)。这直接导致广告主 CPA 暴涨、ROI 负值,甚至赔付(如果平台有成本保障)。优化师常见事故就是“账户总空跑”“计划前端转化好后端差”“预算瞬间跑超但没转化”。这些也都是广告主/代理商/优化师的普遍痛点。

image.png

2.4 业务目标

通过数据驱动的方式,实现以下三个核心目标:

  • 缩短冷启动周期:提供分钟级甚至秒级反馈,把测试周期从天压缩到分钟级/小时级,大幅减少试错预算。
  • 提升 CTR 与 ECPM:通过精准召回 + 素材优化,快速淘汰低质素材,放大高潜素材。
  • 避免空跑流量:通过实时监控秒级发现异常计划,分钟级暂停低效素材,降低无效消耗。

2.5 相关指标设计

image.png

三、场景实践 1:基于 StarRocks 构建实时指标监控

实现创意×渠道×地域×人群标签 CTR 趋势监控 + 分钟级智能告警

3.1 场景描述

广告投放团队需要对不同 创意 × 渠道 × 地域 × 人群标签 的 CTR 趋势进行实时监控, 当某个创意的 CTR 突然下降超过 20%,或某个渠道的 CTR 异常上升但人群转化没有提升,系统应该在分钟级发出告警。

  • 素材优选:对于 CTR 表现优异的新素材,需要立即增加预算。
  • 空跑预警:对于“曝光过万,点击寥寥”的低质素材,必须在分钟级内发现并关停,防止预算浪费。

广告主投放团队在起量阶段常见的常见需求:

  • 多维 CTR 趋势监控: 创意 × 渠道 × 地域 × 人群标签;
  • 分钟级告警: 创意 CTR 突降 >20% / 渠道 CTR 异常上升但人群转化未提升
  • 素材优选: 高 CTR 新素材自动加预算;
  • 空跑预警: 曝光 >1 万且点击寥寥的低质素材分钟级发现并关停;

StarRocks:把等数据、人工盯盘变成实时智能决策引擎

  • 分钟级数据新鲜度: 异步物化视图自动刷新,远超传统 T+1 或 15 分钟延迟;
  • 亚秒级多维下钻: 支持上百人不同维度的分析, 同时查询不卡(CBO + Pipeline 执行引擎);
  • 极速查询性能: 针对亿级别的大表的关联操作,可以实现秒级别的查询响应;

3.2  架构设计

采用 Flink + StarRocks (明细模型 + 物化视图) 架构选型。

在广告实时监控这类高吞吐、Append-only 的场景中,我们选择 Duplicate Key(明细模型) + 异步物化视图 的组合方案。

  • 数据写入:通过 Flink 作业实时消费 Kafka 中的广告日志,通过 Flink StarRocks Connector 实时写入 StarRocks 的明细表。
  • 预聚合:利用 StarRocks 的异步物化视图实时物化视图,自动按 ad_idcreative_id + 人群标签聚合 CTR 维度聚合曝光量和点击量,计算 CTR。
  • 查询:BI 看板直接查询物化视图,实现亚秒级响应。

3.3 方案设计

曝光和点击数据通过流式 append 写入 StarRocks 明细表,每条广告展示事件实时更新聚合表。

(1)明细表设计

CREATE TABLE fact_ad_events (
    event_time     DATETIME NOT NULL,
    ad_id          BIGINT,
    creative_id    BIGINT,
    campaign_id    BIGINT,
    creative_version STRING,
    channel        VARCHAR(64),
    region         VARCHAR(32),
    user_tag       VARCHAR(128),     -- 人群标签(兴趣/年龄/性别/LTV分层等)
    event_type     VARCHAR(20),      -- 'show' / 'click' / 'convert'
    cost           DECIMAL(18,6),
    user_id        BIGINT
)
DUPLICATE KEY(event_time, ad_id, creative_id)
PARTITION BY RANGE (event_time) ()
DISTRIBUTED BY HASH(ad_id) BUCKETS 64
PROPERTIES ("replication_num" = "3");

(2)创建异步物化视图,每分钟刷新

CREATE MATERIALIZED VIEW agg_ad_realtime
PARTITION BY date_trunc('minute', event_time)
DISTRIBUTED BY HASH(creative_id)
REFRESH ASYNC EVERY (INTERVAL 1 MINUTE)
AS
SELECT
    date_trunc('minute', event_time)          AS event_minute,
    event_time,                               -- 必须保留原始列,让分区能找到
    ad_id,
    creative_id,
    creative_version,
    channel,
    region,
    user_tag,
    COUNT_IF(event_type = 'show')             AS impression_count,
    COUNT_IF(event_type = 'click')            AS click_count,
    COUNT_IF(event_type = 'convert')          AS convert_count,
    SUM(cost)                                 AS cost
FROM fact_ad_events
GROUP BY
    date_trunc('minute', event_time),
    event_time,                               -- 对应上面保留的列
    ad_id,
    creative_id,
    creative_version,
    channel,
    region,
    user_tag;

(3)指标监控 1:素材优选, 高 CTR 新素材, 及时增加预算

WITH ranked_new_material AS (
    SELECT
        creative_id,
        creative_version,
        channel,
        user_tag,
        SUM(click_count) AS click_counts,
        SUM(impression_count) AS impression_count,
        ROUND(SUM(click_count) * 100.0 / NULLIF(SUM(impression_count), 0), 2) AS ctr_percent,
        RANK() OVER (PARTITION BY channel ORDER BY
            ROUND(SUM(click_count) * 100.0 / NULLIF(SUM(impression_count), 0), 2) DESC
        ) AS ctr_rank
    FROM agg_ad_realtime
    WHERE  event_minute >= NOW() - INTERVAL 1 HOUR
    AND creative_version LIKE '%new%'   -- 新素材标识
    GROUP BY creative_id, creative_version, channel, user_tag
    HAVING SUM(impression_count) >= 10   -- 先过滤低曝光素材,提升性能
)
SELECT
    creative_id,
    creative_version,
    channel,
    user_tag,
    impression_count,
    ctr_percent,
    ctr_rank
FROM ranked_new_material
WHERE ctr_rank <= 5
  AND ctr_percent >= 4.0 AND impression_count >= 20;
ORDER BY channel, ctr_rank; -- Top5 且 CTR≥4%(行业可调), 且曝光至少300才参与排名

DEMO 执行示意

image.png

(4)指标监控 2:查询近 60 分钟多维 CTR 趋势, 毫秒级查询响应

SELECT 
    event_minute,
    creative_id,
    creative_version,
    channel,
    region,
    user_tag,
    impression_count,
    click_count,
    ROUND(click_count * 100.0 / NULLIF(impression_count, 0), 2) AS ctr_percent,
    ROUND(convert_count * 100.0 / NULLIF(click_count, 0), 2)     AS cvr_percent
FROM agg_ad_realtime
WHERE event_minute >= NOW() - INTERVAL 60 MINUTE
ORDER BY event_minute DESC, ctr_percent DESC;

DEMO 执行示意

image.png

(5)异常监控 1: 使用 StarRocks 的窗口函数计算移动平均,识别 CTR 突降 20%异常

WITH ctr_trend AS (
    SELECT creative_id, creative_version,
           ROUND(click_count * 100.0 / NULLIF(impression_count, 0), 2) AS ctr_percent,
           AVG(ROUND(click_count * 100.0 / NULLIF(impression_count, 0), 2))
               OVER (PARTITION BY creative_id ORDER BY event_minute ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) AS moving_avg
    FROM agg_ad_realtime
    WHERE event_minute >= NOW() - INTERVAL 30 MINUTE
)
SELECT * FROM ctr_trend
WHERE (moving_avg - ctr_percent) / moving_avg > 0.20
ORDER BY (moving_avg - ctr_percent) DESC;

DEMO 执行示意

image.png

(6)异常监控 2:滑动窗口进行空跑预警, 一分钟刷新一次(曝光过万 + 点击极低)


SELECT creative_id,
       creative_version,
       impression_count,
       click_count,
       ROUND(click_count * 100.0 / NULLIF(impression_count, 0), 2) AS ctr_percent
FROM agg_ad_realtime
WHERE impression_count > 10000
  AND click_count < 50
  AND event_minute >= NOW() - INTERVAL 10 MINUTE;

四、场景实践 2:基于 StarRocks 创意 A/B 测试与多版本对比

4.1 场景描述

广告主同时投放 3-5 个不同版本的创意素材,需要快速识别哪个版本的 CTR 最高。A/B 测试要求:流量均匀分配到各版本,实时对比各版本的曝光量、点击量、CTR,达到统计显著性(通常需要 1000+转化或 10000+曝光)后决定胜出版本,并关闭低劣版本,避免预算继续浪费在低效创意上。

用户核心诉求如下:

  • 分钟级看到真实差异;
  • 多维度拆解:版本 × 渠道 × 地域 × 人群标签 × 时段;
  • 高效判断统计显著性;
  • 行动: 胜出即扩投、劣版即关停;

StarRocks 核心优势:助力把握最佳决策期

传统方案要导出数据 → 用 Python/R 跑卡方 → 等半天 → 经常错过最佳决策窗口。StarRocks 支持将 SQL 一键计算,亚秒级出结果,物化视图每分钟自动刷新。

StarRocks 把 A/B 测试从“等数据、跑脚本”变成分钟级科学决策, 投放团队分钟级就能看到“版本 B 卡方值 18.7,已显著胜出”,立刻关停劣版。

image.png

4.2 架构设计

采用 Flink + StarRocks(异步物化视图)架构:

  • Flink 实时消费 Kafka 中的广告日志,Sink 到 StarRocks 明细表。
  • 异步物化视图自动按 creative_version + 多维度聚合曝光/点击/转化,分钟级刷新。
  • 查询:BI 看板 直接访问物化视图,实现亚秒级响应。
  • 决策自动化:自动化服务提交 SQL 判断结果,自动调整预算/关停版本。

4.3 方案设计

(1)异步物化视图定义

CREATE MATERIALIZED VIEW agg_ad_abtest
PARTITION BY event_minute                      -- 直接用别名分区(3.1+ 支持)
DISTRIBUTED BY HASH(creative_id, creative_version)
REFRESH ASYNC EVERY (INTERVAL 1 MINUTE)
AS
SELECT
    date_trunc('minute', event_time)          AS event_minute,
    campaign_id,
    creative_id,
    creative_version,
    channel,
    region,
    user_tag,
    COUNT_IF(event_type = 'show')             AS impression_count,
    COUNT_IF(event_type = 'click')            AS click_count,
    COUNT_IF(event_type = 'convert')          AS convert_count
FROM fact_ad_events
GROUP BY
    date_trunc('minute', event_time),         -- 对应 event_minute
    creative_id,
    creative_version,
    campaign_id,
    channel,
    region,
    user_tag;

(2)实时多维对比看板

SELECT 
    creative_version,
    channel,
    region,
    user_tag,
    SUM(impression_count) AS impressions,
    SUM(click_count) AS clicks,
    ROUND(SUM(click_count) * 100.0 / NULLIF(SUM(impression_count), 0), 2) AS ctr_percent,
    ROUND(SUM(convert_count) * 100.0 / NULLIF(SUM(click_count), 0), 2) AS cvr_percent
FROM agg_ad_abtest
WHERE event_minute >= NOW() - INTERVAL 24 HOUR
GROUP BY creative_version, channel, region, user_tag
ORDER BY ctr_percent DESC;

Demo执行示意

image.png

(3)统计显著性自动判断(卡方检验,胜出决策核心)

WITH stats AS (
    SELECT creative_version,
           SUM(impression_count) AS imp,
           SUM(click_count) AS clk
    FROM agg_ad_abtest
    WHERE campaign_id = 1234
      AND creative_version IN  ('V1_old','V1_new','V2_old','V2_new')
      AND event_minute >= NOW() - INTERVAL 12 HOUR
    GROUP BY creative_version
)
SELECT a.creative_version AS winner, b.creative_version AS loser,
       ROUND(a.clk*100.0/a.imp,2) AS ctr_a,
       ROUND(b.clk*100.0/b.imp,2) AS ctr_b,
       POWER(a.clk - a.imp*p,2)/(a.imp*p) + POWER(b.clk - b.imp*p,2)/(b.imp*p) AS chi_square
FROM stats a CROSS JOIN stats b
CROSS JOIN (SELECT SUM(clk)*1.0/SUM(imp) AS p FROM stats) total
WHERE a.creative_version != b.creative_version
HAVING chi_square > 0.003 AND ctr_a > ctr_b;

Demo执行示意

(4)分时段细分分析

某美妆品牌发现创意 A 在晚上 8-10 点 CTR 最高,而创意 B 在中午时段表现更好。StarRocks 的分时段分析帮助实现 Dayparting 策略,实现不同时段投放不同创意:

SELECT 
  HOUR(event_time) as hour_of_day,
  creative_version,
  COUNT(CASE WHEN event_type='impression' THEN 1 END) as impressions,
  COUNT(CASE WHEN event_type='click' THEN 1 END) as clicks,
  ROUND(clicks * 100.0 / NULLIF(impressions, 0), 2) as ctr_percent
FROM fact_ad_events
WHERE campaign_id = 1234
  AND event_time >= date_sub(NOW(), INTERVAL 7 DAY)
GROUP BY hour_of_day, creative_version
ORDER BY hour_of_day, creative_version;

Demo执行示意

五、案例:Pinterest 广告主报表重构

全球知名图片社交平台 Pinterest 在广告主报表场景中,也经历了类似的架构升级。

5.1 背景与痛点

Pinterest 拥有海量广告主,其提供的 Partner Insights工具旨在帮助广告主通过自定义仪表板查看广告的实时表现(如曝光、点击、CTR)。在原有架构中,Pinterest 使用 Druid 来存储和提供实时洞察数据。随着广告业务规模扩大,广告商对实时性、自定义分析能力及成本效率的要求日益提升, 原架构因此面临严峻挑战:

  • 成本高昂:为了维持高性能,Druid 集群需要大量的实例资源,导致资源消耗大。
  • SQL 支持有限 :Druid 对标准 SQL 的支持不足,无法满足广告商复杂分析需求;
  • 数据新鲜度不足:部分数据处理链路延迟较高,难以做到真正的“实时”,通常是 T+1 或分钟级延迟,无法满足广告主即时调优的需求。
  • 灵活性差: 原有架构在处理复杂自定义指标分析时,依赖 JSON 配置繁琐,且对标准 SQL 支持不够完善,增加了开发和客户 Onboarding 的复杂度。

5.2 解决方案

Pinterest 将 Partner Insights 的底层分析引擎迁移至 StarRocks, 利用 StarRocks  SQL 能力替代 Druid 的 JSON 查询 DSL,并构建了统一的低延迟分析层,直接接入广告曝光和点击流数据。核心优化点:

  • 架构升级与数据摄取简化 :利用 StarRocks 标准 SQL 接口替代复杂 JSON 配置,广告商可直接通过 SQL 提取数据,大幅简化客户入职流程;
  • 性能优化 :通过向量化引擎加速查询,结合物化视图预计算高频指标,降低实时分析延迟;
  • 存算分离与资源效率 :采用存算分离架构(已落地 100 + 客户),支持灵活扩缩容,降低资源消耗

新的架构图如下:

图片

5.3 方案收益

迁移至 StarRocks 后,Pinterest 在广告报表场景取得了显著收益:

1. 性能提升:P90 查询延迟降低了 50% ,广告主查看报表的体验更加丝滑。

2. 成本大幅降低:所需实例数量减少了 68% (仅为原来的 32%),性价比大幅提升。

3. 数据极速鲜活:数据新鲜度从分钟级/小时级提升至 10 秒级,广告主可以看到 10 秒前发生的广告曝光数据。

4. 流程简化: 通过标准 SQL 进行数据提取,省去了 JSON 配置的麻烦,简化了客户 Onboarding 流程,广告主实时决策效率显著提高。

总结

广告投放的本质是在不确定性中快速迭代决策。每一次的数据分析都应该转化为可执行策略,通过引入 StarRocks,在流量获取阶段把起量监控变成实时智能决策引擎,让 CTR 与 eCPM 真正跑赢竞品。

具体收益如下:

1. 冷启动成本大幅降低: 向量召回 + 实时监控,把测试周期从“天”压缩到“分钟级”,大幅减少试错预算,提升 CTR。

2. 运营效率倍增:秒级监控 + 异常预警 + 精准人群分析,让团队从“拉数”中解放,专注策略与创意迭代。

下期预告:广告投流第二战——如何利用 StarRocks 解决“转化归因”与“ROI 实时计算”难题?敬请期待。