开源方案(下):OLAP、管道与一套能跑起来的自建栈
自建 UBA 的成败不在引擎跑分,而在事件模型、去重口径与谁值夜班;栈选错一层,三年后都要用人力补票,且很难回头。
先给判断:开源自建 UBA,七成工作量不在选引擎,而在事件模型、身份、权限、指标语义和运维;剩下三成,才是引擎与管道。 这句话不是劝退,而是帮你尽早排除一类错误立项:团队还回答不了“同一个用户在 App、小程序和 Web 上怎么算一个人”,却已经开始比较 ClickHouse 与 Doris 的扫描速度。引擎当然重要,但它只在事件模型确定之后才重要;顺序反了,任何引擎都会被用成慢查询生成器。
本章不给“最强引擎”排名。它提供的是一条排除路径:先用负载特征去掉不合适的选项,再用成本公式算出量级,最后用三套参考栈和一张清单决定买、建还是租。
7.1 事件分析的负载特征#
UBA 的查询难点不是“扫得快”,而是同一份事件被反复以不同窗口、不同身份、不同去重口径重算。 把这句话想清楚,后面的引擎差异才有意义。
写入是追加,更新是例外。 典型 UBA 集群日增几千万到几百亿条事件,这是经验区间,不是厂商承诺;单条 0.3–2 KB。写入以批量追加为主,更新只发生在用户属性、身份绑定、隐私删除等少数场景。这个特征让列存加批量 part 的引擎天然占优,也让“频繁 UPDATE”变成昂贵的例外。
宽表与半结构化并存。 一张事件表常有几百个属性列,其中大量是低基数枚举、URL、JSON。列存喜欢“宽而稀疏”,但 schema 漂移会让物化视图和索引反复重建。常见的折中是:事件主表打平 30–50 个高频属性,长尾进 JSON,用户与设备维度单独建表。
低延迟聚合与高并发同时发生。 一个看板可能同时发 20–50 个查询,每个扫 7–90 天分区;产品、运营、老板在早上九点打开同一批看板,尖峰并不均匀。引擎要能扛住“少量大查询 + 大量小查询”的混合,而不是只在单查询基准里快。
去重与迟到是常态。 SDK 重试、客户端离线补传、服务端重复消费都会产生重复事件;移动端迟到几分钟到几天很常见。去重放在摄入端还是查询端,直接决定存储成本与查询复杂度:摄入端要唯一 event_id 与幂等写入,查询端要 FINAL、argMax 或 COUNT(DISTINCT),后者在十亿级上会把 CPU 翻倍。
漏斗、留存、路径是序列问题。 它们不是简单的 GROUP BY,而是“同一用户按时间排序后,判断步骤是否按序发生”。SQL 能写,但窗口函数与自连接会放大扫描和 shuffle;这也是很多团队在 BI 里写漏斗,最后都回到预聚合的原因。
明细回查与多租户是最后一公里。 分析发现问题后,用户要下钻到具体用户、会话、事件;同时不同业务线、不同客户的数据要隔离。租户隔离不能靠“多加一个 WHERE tenant_id”解决资源争抢,这一点在 7.8 还会展开。
这六种特征会反过来决定建模。宽表把用户、设备、事件属性全部打平,查询快、写入简单,但属性变更要回溯,列数会膨胀;星型模型把事件、用户、设备、维度拆开,join 多,适合 Doris/StarRocks,不适合 ClickHouse 的大规模 join;JSON/嵌套把长尾属性放一个列,节省列数,但查询要用 JSON 函数,索引与压缩效率下降。没有一种模型适合所有 UBA。
还有一个常被忽略的变量:规模不能只用事件量描述。查询并发、保留期、属性与 schema 数量、租户数量,任何一个翻倍,都会把同一事件量的成本放大。两家公司都写“日增 5 亿”,一家是 3 个租户、保留 90 天、20 个看板;另一家是 300 个租户、保留 2 年、200 个看板——后者需要的不是同一个引擎配置。
判断:先定事件 taxonomy、身份图、会话规则和指标口径,再按负载选引擎;顺序反了,换引擎只是换一个地方变慢。
这也解释了为什么“接入一个数据库就有了 UBA”是误判。ClickHouse 给你查询速度,不给你事件定义、身份合并、漏斗界面、权限模型和指标口径。把这些当成数据库自带的能力,是自建项目最常见的起点错误。
7.2 ClickHouse#
ClickHouse 是四种 OLAP 引擎里最像“为不可变事件而生”的一个,也是最容易被误用的一个。 它的优势集中在单表扫描、压缩率和写入吞吐;它的短板也正好落在 UBA 经常需要的去重、更新、join 和租户隔离上。
ClickHouse 由 ClickHouse Inc 主导,Apache License 2.0;项目 2016 年由 Yandex 开源,2021 年独立为公司 ClickHouse 仓库 Dealroom 报道。核心是 MergeTree 家族:数据按 ORDER BY 排序写入 part,后台合并,主键索引是稀疏索引,因此“按什么排序”几乎等于“哪些查询会快” MergeTree 文档。典型事件表按 tenant_id、event_date、event_name、user_id 排序,按月分区,按 event_date 设 TTL(生存时间),属性尽量打平,JSON 只放长尾。
去重是 ClickHouse 最需要提前设计的地方。ReplacingMergeTree(version) 能做最终去重,但合并时机不确定,查询时要用 FINAL 或 argMax 才能保证口径。这不是缺陷,而是“写入便宜、查询时付账”的取舍;如果业务不能接受查询端补丁,应该在摄入端生成唯一 event_id,并控制重复写入。
分析函数是它的强项:windowFunnel、retention、sequenceMatch、uniqExact/uniqCombined 都能直接用。但它没有内置的漏斗、留存、路径界面,这些要在应用层或 BI 层实现。换句话说,ClickHouse 给你的是计算原语,不是产品。
部署与计价决定了它的成本结构。开源自建之外,还有 ClickHouse Cloud(AWS/GCP/Azure)与 Bring Your Own Cloud;中国大陆区域与合规可用性需要单独确认(待核实)ClickHouse 定价页。Cloud 存储 25.30 美元/TB/月;计算单价 Basic 0.2181、Scale 0.2985、Enterprise 0.3903 美元/unit/小时;公网出流量 0.1152 美元/GB 起;新用户 300 美元/30 天 ClickHouse 定价页。定价页只给 unit 单价,没有给 unit 与 vCPU/内存的换算,必须用官方估算器确认,不能把 unit 当 vCPU。
部署形态会改变成本曲线。Cloud 把容量弹性卖给查询峰值,BYOC 把网络、备份、升级拉回自己的云账号;前者适合波动大、运维薄的团队,后者适合数据不能出云账号的组织。自建看起来没有 license,实际是把账单换成了闲置容量、备份和人力,这三项不会出现在云厂商的报价单上。
商业势能是它最容易被忽略的变量。2026 年 1 月估值 150 亿美元,2026 年 8 月 ARR 超过 3.5 亿美元 Dealroom 报道。它在 2025 年 3 月 13 日收购 HyperDX,补上可观测性界面与会话回放 HyperDX 收购公告;2026 年 1 月 16 日收购 Langfuse,进入 LLM 可观测性 Langfuse 加入公告。2026 年 9 月 23 日的 26.9 版本加入只追加物化视图的增量刷新、高基数 DISTINCT 落盘等能力 26.9 发布说明。这些动作说明它在从数据库公司变成实时数据平台公司,而不是只卖查询。
口径冲突要并列写。BusinessWire 在 2026 年 5 月的新闻稿称 ClickHouse ARR 2.5 亿美元、4,000 家客户,但该页面无法访问,只能标为待核实 BusinessWire 新闻稿。它与 Dealroom 的 3.5 亿美元不是同一时点、同一来源,不能混成一个数。
限制也很具体:多表 join 需要精心设计;ALTER UPDATE/DELETE 是重操作;part 过多、合并跟不上会拖垮写入;多租户资源隔离要靠副本、计算组或独立集群;没有指标语义层。调优方向因此很固定:按天或按月分区,ORDER BY 把租户、事件名、用户放前面,高频过滤属性用跳数索引或 Projection,漏斗与留存预聚合成 AggregatingMergeTree,避免 SELECT * 和跨大表 JOIN,写入用批量或 async_insert 控制 part 数量。
7.3 Doris / StarRocks#
Doris 与 StarRocks 常被放在一起,因为它们的共同点很实际:SQL 兼容、更新自然、join 能打,适合“事件表要和订单表、用户表放在一起查”的团队。 它们不是 ClickHouse 的廉价替代,而是另一种负载形状的答案。
Doris 是 Apache 软件基金会顶级项目,Apache License 2.0,商业化公司 SelectDB(飞轮科技)由创始团队组建 Doris 仓库。它采用 FE/BE 架构,FE 管元数据、查询解析和节点管理,BE 管存储与计算;支持 Duplicate、Aggregate、Unique 三种数据模型,Unique 模型支持 merge-on-write 行级更新;同步单表物化视图与异步多表物化视图并存;采集以 Stream Load、Routine Load、Flink/Spark Connector 为主,另有湖仓 Catalog、倒排索引、向量索引 Doris 4.x 文档。建表通常按日期分区、按 key 分桶,UV 用 bitmap/roaringbitmap,半结构化用 VARIANT。官方称针对万列宽表做了优化,也给了宽表聚合 5–10 倍向量化提升的说法——后者是厂商自测口径,不是第三方复现。
Doris 的版本节奏很快。4.0.0 于 2025 年 10 月 14 日发布,加入向量索引、AI 函数、SEARCH()、Spill Disk、TopN 懒物化与 SQL Cache Doris 4.0.0 发布说明;4.1.0 于 2026 年 4 月 21 日、4.1.5 于 2026 年 10 月 16 日继续补湖仓、AI 资源、Routine Load 与物化视图 Doris 版本记录。官网称 10,000+ 用户 Doris 官网;SelectDB 文档又称“10 年超 2000 家企业使用”,两个口径不同,都是厂商口径 SelectDB 企业版介绍。版本快也意味着升级风险:4.0 之后功能扩张明显,向量/AI 能力较新,生产验证要自己做;升级前先跑回归,不要盲目追最新版。
StarRocks 同样是 Apache License 2.0 StarRocks LICENSE,项目隶属 LF Projects,商业公司 CelerData 在 2026 年 5 月 27 日更名为 PhoenixAI PhoenixAI 更名报道。架构是 FE/BE/CN,强调 CBO(基于代价的优化器)、向量化 C++ 执行引擎、Primary Key 模型、同步/异步物化视图、Shared-data 存算分离,以及 Iceberg/Hudi/Delta/Paimon Catalog StarRocks 官网。它的强项是复杂多表 join、窗口函数、CTE 与湖仓联邦查询;在四个引擎里,它的“多表 + 高并发”最均衡。
StarRocks 的两条风险要写进采购材料。第一是版本质量:4.1.0 的容器镜像存在 BE 启动顺序问题,官方明确建议容器用户不要升级到 4.1.0,等 4.1.1 StarRocks 4.1 发布说明;4.1.6 于 2026 年 9 月 30 日发布。第二是商业主体变化:CelerData 更名 PhoenixAI,并在 2026 年 6 月 11 日宣布 8000 万美元 B 轮,由 Sky9 Capital 领投 8000 万美元 B 轮报道。这不等于产品会消失,但路线、定价与支持主体都可能变,合同要写清控制权变更条款。技术上的两个坑也要提前知道:多表 join 很吃统计信息,统计不准时执行计划会退化;Shared-data 模式依赖对象存储与本地 cache,cache 命中率直接决定延迟。
两者之间怎么选?如果更新多、业务在中国、需要本地交付与信创适配,Doris 的默认路径更短;如果查询以多表 join、湖仓联邦为主,且团队能接受更复杂的 FE/BE/CN 运维,StarRocks 更合适。别用“谁更像 MySQL”来选,MySQL 协议兼容只降低接入成本,不改变执行模型。两家的商业版——SelectDB 与 PhoenixAI——公开页都没有单价,按云资源、BYOC 或订阅报价,采购时必须拿到书面区间;这也是它们与 ClickHouse Cloud 公开计价的一个差异。
把四种引擎放在一张表里,差异会更清楚。
| 维度 | ClickHouse | Doris | StarRocks | Druid |
|---|---|---|---|---|
| License | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
| 定位 | 不可变事件、日志、可观测性 | 更新型实时数仓 | 多表复杂分析、湖仓 | 时间序列预聚合 |
| 写入 | 批量追加,强 | Stream/Routine Load,强 | Stream Load,强 | Kafka/Kinesis 原生 |
| 更新/去重 | ReplacingMergeTree 最终去重,查询要 FINAL/argMax | Unique Key merge-on-write | Primary Key,部分列更新 | 弱,更新困难 |
| 多表 join | 中,需避免大 join | 强 | 四者中最均衡 | 弱 |
| 高并发/隔离 | 单表强,租户隔离要设计 | 强,计算组可隔离 | 强,shared-data 可弹性 | 强,但多进程运维重 |
| 湖仓 | 中,外部表为主 | 强,4.x 补 Lakehouse | 强,多 Catalog | 中 |
| 运维难度 | 高 | 中高 | 高 | 很高 |
| 最适合 | 单表聚合、明细回查 | 更新多、中国生态 | join 多、湖仓 | 指标型看板、安全分析 |
| 主要坑 | part 过多、join、语义层缺失 | 写入放大、compaction | 统计信息、cache 命中率 | rollup 固定维度、join 弱 |
这张表最重要的不是“谁更强”,而是“谁的强项和你的负载同形”。如果事件表只追加、查询以单表聚合为主、团队能接受 MergeTree 的运维模型,ClickHouse 的性价比最高;如果事件要频繁修正、用户属性要更新、漏斗要和订单表 join,Doris/StarRocks 的复杂度更低;Druid 只在“时间序列 + 预聚合 + 高并发”三者同时成立时值得保留。
关于 benchmark,本章只认两类标签:厂商自测,或第三方。Doris 的 5–10 倍、StarRocks 的“亚秒级”定位、ClickHouse 的单表扫描优势,基本都是厂商自测或厂商口径;第三方在同一数据集、同一查询集、同一并发下的复现,本次没有拿到(待核实)。更可靠的做法是拿自己的 7 天事件数据、自己的 20 条查询、自己的并发做 POC(概念验证),记录 p50/p95、CPU、磁盘、成本五组数字。POC 里必须包含三个坏查询:大漏斗、跨表 join、明细回查;只测 COUNT(*) 的 POC 参考价值有限。
判断:ClickHouse 与 Doris/StarRocks 的差距,不在 10 亿行扫描快 20% 还是 30%,而在去重、更新、join、隔离这四件事上谁让你少写代码、少招人。
7.4 Druid 与湖仓#
Druid 是四种引擎里最专用、也最容易被“实时 OLAP”这个词带进错误场景的一个。 它为时间序列、预聚合和高并发设计,因此适合指标型看板,不适合做 UBA 的唯一明细引擎。
Druid 的组件比前三个都多:Coordinator 管 segment 分配,Overlord 管摄入任务,Broker 管查询路由,Router 做网关,Historical 提供本地缓存,MiddleManager/Peon 与 Indexer 负责摄入;数据以 segment 为单位放在 deep storage(S3/HDFS),元数据在 MySQL/PostgreSQL,协调依赖 ZooKeeper Druid 架构文档。它的成本杠杆是 rollup:预聚合之后存储和查询都降,但维度组合被固定,临时下钻要回到原始数据;高基数维度会让 rollup 失效。
Druid 的分析能力偏“时间序列”:time-series、topN、groupBy 很强,SQL 与原生查询都能用,多表 join 弱,复杂明细查询不是它的设计目标。它仍在发版:36.0.0、37.0.0、38.0.0 分别在 2026 年 2 月 9 日、5 月 8 日、10 月 1 日发布 Druid 官网,38.0.0 含 250+ 项改动 Druid 38.0.0 发布说明。但商业重心已经转移:Imply 首页把自己描述为“agentic SIEM 的数据平台”,主推 Lumi 与 Polaris,而不是通用实时分析 Imply 官网;Polaris 的定价同样按用量或合同报价,公开单价未披露。这不代表 Druid 会停,但代表“买商业支持做通用 UBA”的确定性在下降。所以 Druid 的合理位置是“指标加速层”:把高频、固定维度的看板放进 rollup,把明细留在 OLAP 或湖仓。让它独自承担 UBA 的明细探索,等于用预聚合去回答一个随时会变的临时问题。
湖仓是另一条线,而 Iceberg 是最容易被误解的一个。它不是数据库,也不是查询引擎,而是开放表格式;解决的是“数据归谁、能不能被多引擎读、能不能回溯”,不解决亚秒级查询 Iceberg 规范。它用 snapshot、manifest、data file 三层元数据组织表,支持隐藏分区、schema 演进、时间旅行、branch/tag、REST Catalog,v3 规范加入删除向量与行级血缘;1.12.0 于 2026 年 9 月 30 日发布,V4 规范已在推进 Iceberg 1.12.0 发布说明。
生态在往标准化走。Apache Polaris 作为 Iceberg REST Catalog 已进入 ASF,支持 Doris、Flink、Spark、StarRocks、Trino 等多引擎 Polaris 官网;Databricks 在 2024 年宣布收购 Iceberg 创始团队公司 Tabular,加深对生态的影响 Databricks 收购公告。对 UBA 的含义是:事件真相层可以放在 Iceberg,serving 仍然要 OLAP。
但 Iceberg 的日常运维不轻。流式写入会不断产生小文件,manifest 也会膨胀;不合并的话,查询 planning 时间会超过扫描时间。另一个坑是 catalog:不同引擎对 REST/Glue/Hive/Nessie 的支持不一致,跨引擎写要做权限与提交冲突测试。事件表通常按 event_date、tenant_id 分区,按 event_time 排序;写入端要做小文件合并、快照过期、孤儿文件清理。选 Iceberg 之前先回答三个问题:谁负责 compaction,Catalog 用哪一个,哪些引擎需要写。三个问题没有答案,湖仓就会变成“能存不能查”的归档桶。
warehouse-native 指平台不搬走事件,只把指标计算下推到客户数仓。它的代价也不只是查询费。事件要先进对象存储,延迟从秒变分钟;每次查询都扫外部表,cold start 与 metadata planning 会吃掉体验;指标定义要跟 dbt/数仓版本走,产品侧改一个口径要发一次数据 PR。它把成本从存储转到计算和治理,但没有消灭成本。
判断:Iceberg 是归档与复用的契约,不是 serving 层。把它当查询引擎用,最后会在延迟和 metadata planning 上付出代价。
7.5 Kafka / Flink#
Kafka 和 Flink 是自建栈里最容易被“顺便装上”的两个组件,也是最容易把固定成本抬高的两个。 它们解决的是“事件怎么流、怎么带状态算”,不是“事件怎么被查询”。
Kafka 是分布式事件流平台,做事件总线和可回放日志,不是分析数据库。4.0.0 于 2025 年 3 月 18 日发布,是第一个完全运行在 KRaft 模式的主版本,同时 GA 了 KIP-848 消费组协议、预览了 KIP-932 队列语义 Kafka 4.0 公告。此后 4.1.0(2025-09-02)、4.2.0(2026-02-17)、4.3.0(2026-05-22)、4.3.1(2026-06-25)基本按每年三个版本的节奏推进 Kafka 下载页。
容量估算的顺序是先算日字节与峰值倍数,再按目标单分区吞吐反推分区数,最后定副本与保留。分区不是越多越好:Controller 元数据、rebalance、文件句柄都会随分区数上升。Tiered Storage 可以把冷数据移到对象存储,降低本地盘成本,但跨区流量仍然按 GB 计费。对多数 UBA,Kafka 的价值是“多下游、可重放、削峰”,不是“更快”;如果只有一个下游、没有重放需求,直接写 OLAP 或对象存储会更简单。
Kafka 的 exactly-once 经常被误读。KIP-98 提供的是幂等生产者加事务:生产者可以跨多个 TopicPartition 原子写,消费者用 read_committed 只读已提交消息 KIP-98。这只保证 Kafka 内部的读写;如果 sink 是 ClickHouse、MySQL 或 S3,仍要靠两阶段提交、幂等 upsert 或去重键。
Flink 是有状态流处理引擎,做实时 ETL、会话化、去重、CEP(复杂事件处理)和实时告警。它的事件时间与 Watermark、窗口、Keyed State、Checkpoint、Savepoint、RocksDB/ForSt 状态后端,都是为“状态一致性”服务的 Checkpoint 文档。当前主线是 2.x,稳定版 2.3.0,1.20.5 仍是 LTS;Flink CDC 3.7.0 于 2026 年 10 月 10 日发布,加入可插拔模型 API 与 OpenAI 兼容接口 Flink 官网。
端到端 exactly-once 同样不能想当然。Flink 能保证“状态更新 exactly-once”,但端到端需要 source 参与快照、sink 参与 checkpoint。官方表格写得很清楚:Kafka producer 在事务模式下可以 exactly-once,Elasticsearch/OpenSearch sink 只有 at-least-once 连接器一致性说明。所以“上 Flink 就有 exactly-once”是错的,必须端到端设计。
Flink 的隐性成本在状态。RocksDB 状态越大,checkpoint 越久,恢复越慢;要把状态按 key 设计、设 TTL、避免全量窗口。另一个判断标准是状态规模:会话化与去重需要按用户 key 保存状态,状态越大,checkpoint 与恢复越贵;如果只是窗口聚合,很多工作可以在 OLAP 的物化视图里完成。Checkpoint 存 HDFS/S3,Savepoint 用于升级与回滚,两者不要混用。人才也稀缺:能调大状态、checkpoint 和反压的人,比会写 SQL 的人少得多。
判断:如果业务能接受 1–5 分钟延迟,CDC(变更数据捕获)加 OLAP 微批通常比 Kafka + Flink 便宜一个数量级;只有“会话超时 30 分钟要实时切分”“欺诈要在秒级拦截”“多流 join 不能等批”这类需求,才值得上 Flink。
7.6 BI 与语义层#
Superset、Metabase、Grafana 都不解决指标口径。 它们是指标消费端;口径在事件 taxonomy、dbt/数仓模型或自建语义层里。把这个顺序搞反,最后会得到四个看板里的四个“活跃用户”。
| 工具 | 定位 | 语义层强度 | 计价锚点 | 适合 |
|---|---|---|---|---|
| Superset | SQL-first BI | 弱–中 | 免费/托管报价 | 内部报表、数据团队 |
| Metabase | 易用 BI/嵌入 | 中 | 100/575 美元/月起 | 业务自助、SaaS 嵌入 |
| Grafana | 可观测性 | 弱 | 免费/Cloud | 监控、日志、SLO |
| GrowthBook | 实验平台 | 中(数仓指标) | 40 美元/席位/月起 | 增长实验 |
GrowthBook 不是 BI,把它放进这张表,是因为它和 BI 消费同一套数仓指标,也最容易被误当成“分析平台”。Grafana 则是另一种边界:AGPL-3.0,13.2.4 于 2026 年 10 月 13 日发布,适合看 pipeline、日志与 SLO,不适合业务漏斗 Grafana 仓库。
Superset 是 Apache 项目,SQL Lab、Dataset、Chart、Dashboard、Alert/Report、行级安全、缓存和 40+ 可视化类型都有 Superset 官网;6.1.0 于 2026 年 5 月 13 日发布 Superset 6.1.0 发布说明。它的语义层是“数据集 + 指标”的轻量实现,不是集中治理的指标层;漏斗、留存、路径没有专用界面,需要写 SQL 或接外部工具。它适合做内部看板层,不适合当 UBA 产品。
Metabase 核心是 AGPL,enterprise 目录为商业许可;自建改造要遵守 AGPL 的网络使用条款,闭源嵌入需商业授权 Metabase 仓库。它的查询构建器、原生 SQL、Dashboard、Model、Metric、Metabot、Embedding SDK 对业务用户更友好;64.1 于 2026 年 10 月 7 日发布。定价是 Starter 100 美元/月(年付 90 美元/月),Pro 575 美元/月(年付 517.50 美元/月),Enterprise 起价 20,000 美元/年;超出包含用户数后 12 美元/用户/月,AI 服务 3.75 美元/百万 token Metabase 定价。它的 Model 与 Metric 也只是轻量语义层,跨团队强制治理仍然缺位。
GrowthBook 核心 MIT,enterprise 目录为商业许可,属于 open core GrowthBook 仓库。它是 warehouse-native 的实验平台与功能开关,不做事件采集与存储,只读数仓里的曝光与指标;Pro 40 美元/席位/月(最多 30 用户),Managed Warehouse 有 100 万事件/月的免费额度,2M 之后按 30 美元/百万计 GrowthBook 定价。5.1.0 于 2026 年 9 月 22 日发布,加入上下文老虎机(beta)、漏斗指标、托管 MCP 与 OAuth GrowthBook 5.1.0 发布说明。它是实验工具,不是通用 UBA。
语义层通常有三种落法:数仓里的宽表/汇总表,最简单但复用差;dbt/指标层,定义集中但需要工程化;自研指标服务,最灵活但成本最高。UBA 的指标比 BI 指标更复杂:同一个“活跃用户”要区分设备、账号、合并身份,还要区分自然日、滚动 7 天、滚动 30 天。把这些口径写进代码而不是文档,才有机会统一。语义层也不是买一个工具就能解决:需要有人对指标命名、口径、维度、权限负责;否则 Superset 的 Dataset、Metabase 的 Model、GrowthBook 的 Metric 只会把同一套混乱复制三遍。
判断:如果 UBA 要可复用,指标定义必须先进数仓或语义层,再被 BI 和实验工具消费,而不是反过来。
7.7 三套参考栈#
下面三套栈是“能跑起来”的配置,不是报价单。 它们的作用是让你在立项时把组件、人力、月成本放在同一张纸上,而不是先买一个引擎再补周边。
| 栈 | 事件量假设 | 组件 | 人力 | 月成本假设 | 适用 |
|---|---|---|---|---|---|
| 轻量 | <5,000 万/日,保留 30–90 天 | ClickHouse Cloud Basic 或单集群 Doris;无 Kafka/Flink;Metabase 或 Superset;GrowthBook Cloud | 0.5–1 人 | 1,000–5,000 美元 | MVP、单产品、少量租户 |
| 标准 | 1–10 亿/日,保留 6–12 个月 | Kafka 3 broker + Tiered Storage;Flink 会话化/去重;ClickHouse/Doris/StarRocks 集群;Iceberg 归档;Superset;GrowthBook | 3–6 人 | 1.5 万–5 万美元 | 中型 UBA、多业务线 |
| 超大规模 | >50 亿/日,保留 1–3 年 | Kafka 多集群 + MirrorMaker;Flink 多集群;OLAP 多集群/多计算组;Iceberg + Polaris/Unity;Trino/Spark;自研前端 | 10–20 人 | 10 万美元以上 | 大型平台、多租户 SaaS |
三套成本都是假设,不是厂商报价。轻量栈按 ClickHouse Cloud Basic 的存储 25.30 美元/TB/月、计算 0.2181 美元/unit/小时估算;标准栈按 3 副本 Kafka、3 节点 OLAP、对象存储与 Flink 常驻集群估算;超大规模栈不含自研前端的人力。实际价格受区域、折扣、保留时长、查询并发影响,必须用云厂商估算器复核。
轻量栈刻意不上 Kafka/Flink。这个量级下,直接写入或每小时微批足够;Kafka 的 3 副本和 Flink 的常驻 slot 会把固定成本抬高。标准栈上 Flink 的前提是会话化、去重、实时告警至少有一个是硬需求;如果只是看板刷新,用 OLAP 的 Routine Load 或物化视图更简单。
标准栈加 Iceberg 不是为了“更先进”,而是为了两件事:原始事件留一份可回溯的真相,以及让 Trino/Spark/StarRocks 这些引擎不必各自存一份。代价是 compaction 与 Catalog 运维。超大规模栈的分水岭不是事件量,而是租户数量与合规要求。
超大规模栈之所以要多集群,也不是因为单集群跑不动,而是因为故障域和租户隔离:一个租户的脏查询、一次回填、一个版本的回归,都不应该影响全部客户。
一个反证是:连“一体化产品”也没有逃开这套组合。PostHog 的公开架构是 Django 负责 Web/API、Rust 服务负责 capture/flags/replay、Kafka(云上用 WarpStream)做总线、ClickHouse 存事件与分析、Aurora PostgreSQL 存元数据、Redis/Valkey 做缓存、S3 存放回放与导出 PostHog 架构文档。Plausible 的社区版要同时维护 PostgreSQL 与 ClickHouse Plausible 仓库;Umami 用 PostgreSQL 单库,适合轻量场景 Umami 仓库。所谓“开箱即用”,只是把选型与运维藏在了产品后面。
三套栈的分界线不是事件量本身,而是你是否需要为实时性、租户隔离和合规单独付费。 轻量栈上 Kafka+Flink,通常是把钱花在不需要的地方。
7.8 成本模型与运维#
自建栈的账,先算存储,再算查询,最后算人力;多数立项材料只算第一项。 这不是财务细节,而是选型结论的分水岭:同样的事件量,存储可能只占账单的一小半,人力才是长期项。
存储公式:
存储 TB = 日事件数 × 单条字节 × 压缩后比例 × 副本数 × 保留天数 ÷ 10^12
其中“压缩后比例”指压缩后大小 ÷ 原始大小。举例:10 亿条/日 × 1 KB/条 = 1 TB/日原始数据;按 8 倍压缩 = 125 GB/日;3 副本 = 375 GB/日;保留 365 天 = 136.9 TB。按 ClickHouse Cloud 存储 25.30 美元/TB/月,约 3,464 美元/月 ClickHouse 定价页。这还没算查询计算、出流量、备份和 compaction。
查询成本有两种算法:
查询成本 ≈ 日查询数 × 平均扫描 GB × 每 GB 扫描单价
或 ≈ 平均并发 × 单查询 CPU 秒 × 核时单价
按扫描计价的引擎用前者,按资源计价的引擎用后者。ClickHouse Cloud 的计价单位是 compute unit,Scale 档 0.2985 美元/unit/小时 ClickHouse 定价页;如果按 8 个 unit 常驻估算,约 1,744 美元/月,但 unit 与 vCPU/内存的换算要以官方估算器为准,不能直接当 vCPU 用。
Kafka 的存储是“日字节 × 副本数 × 保留天数”,Tiered Storage 可以把冷数据移到对象存储;Flink 的成本主要是常驻 slot、状态大小与 checkpoint 存储;Iceberg 的成本主要是对象存储请求、元数据与 compaction。真正的隐性成本是人力:一个能调 ClickHouse part/merge、Flink checkpoint、Kafka ISR(副本同步状态)的工程师,在中国市场年薪约 40–80 万元,在美国约 15–25 万美元(估算,非官方数据)。
把三项放在一起,3 年 TCO 可以写成:3 年 TCO ≈ 月基础设施 × 36 + 人力年成本 × 3 + 一次性迁移与双跑成本。以标准栈为例:月基础设施 5 万美元 × 36 = 180 万美元;4 名工程师 × 15 万美元/年(美国口径下限,估算)× 3 = 180 万美元;合计约 360 万美元,云资源与人力各占一半。换成中国团队,绝对值下降,但人力仍是不能省的那一半。
判断:自建栈的 3 年 TCO 里,软件许可通常是 0,云资源占 30–50%,人力占 30–50%(估算)。只算服务器价格的自建方案,通常会低估 2–3 倍。
多租户是运维里最容易欠债的部分。常见做法有三种:共享表加 tenant_id,成本最低、隔离最弱;共享集群加独立数据库或计算组,折中;独立集群,隔离最好、成本最高。UBA 的租户差异大,建议按租户分层:大客户独立计算组,小客户共享池;查询队列按租户配额;行级权限在查询引擎或语义层做,不要只在前端过滤。资源组、查询超时、并发上限三件套必须同时有,否则一个租户的脏查询就能拖垮全站。
保留与删除要按事件类型分层:原始事件 90–180 天,聚合结果 2–3 年,用户级明细按合规要求删除。GDPR 的删除请求要能定位到 user_id 并传播到 Kafka、OLAP、Iceberg、备份;只删 OLAP 不够。审计日志本身也要保留,否则无法证明删除发生过。
数据质量的三个源头通常不在引擎:SDK 版本不一致导致字段缺失、身份合并把两个人并成一个、时区/时间戳把事件放到错误的分区。前两个要在采集与身份层解决,第三个要在建表时统一 UTC 并保留原始时区。任何 OLAP 都不能替你修这些问题。
降本手段按性价比排序:先做 TTL 与冷热分层,再做预聚合与列裁剪,最后才考虑换引擎。换引擎的迁移成本,通常高于一年的存储差价。
七个失败模式值得贴在墙上:
- part 太多:小批量高频写入让合并跟不上,查询变慢。
- 查询时去重:每次 FINAL 或 COUNT(DISTINCT),CPU 翻倍。
- 多租户共用一套资源:大租户全表扫描,小租户全部超时。
- 回填打爆线上:历史重跑和实时写入抢 CPU。
- schema 漂移:属性类型变化导致物化视图失效。
- 没有语义层:同一个指标在四个看板里有四个数。
- 过度流式:为了“实时”上 Flink,结果 90% 的查询是 T+1。
7.9 选型清单#
把前面的内容压成一张可执行的清单:先排除,再按约束排序,最后用 POC 验证三个坏查询。 不要从“哪个引擎最强”开始,从“哪类负载不该用哪个引擎”开始。
| 场景 | 首选 | 备选 | 主要理由 |
|---|---|---|---|
| 事件只追加、单表聚合为主、有 OLAP 运维 | ClickHouse + 自研前端 | ClickHouse Cloud/BYOC | 单表性价比高,join/更新/语义层要自己补 |
| 事件要修正、用户属性常更新、要和订单表 join | Doris/StarRocks | SelectDB/PhoenixAI 商业版 | 更新与 join 自然,SQL 兼容,代价是运维与商业绑定 |
| 数据不能出仓、要长期保留、多引擎复用 | Iceberg + Trino/StarRocks | Hudi/Delta | 开放与归档成本低,但不是 serving 层 |
| 已有数仓、实验为主、不想养管道 | warehouse-native(Snowflake/BigQuery + GrowthBook) | 托管 ClickHouse | 上线快,成本随查询增长 |
| 日增 <5,000 万、团队 <3 人 | 托管/SaaS | 轻量 ClickHouse Cloud | 自建现金成本通常更高 |
前四条路线的共同点是:都把 OLAP 当执行引擎,把事件模型当产品。区别只在数据放在哪、谁负责运维、指标定义归谁;最后一行不是技术路线,而是规模阈值。
落地前用十个问题做排除:
- 峰值/日均事件量、单条字节、迟到比例、重复比例各是多少?
- 查询以单表聚合、明细回查、多表 join 哪类为主?p95 延迟目标是多少?
- 是否需要行级更新/删除?RBAC(基于角色的访问控制)、列级脱敏与审计能否满足合规?
- 租户数量与最大租户占比?是否需要独立计算组?
- 端到端 exactly-once 是否硬要求?sink 有哪些?
- 回填窗口多长?能否在不影响线上查询的情况下重跑 90 天?
- 部署形态:公有云、私有化、BYOC、信创?数据能否出境?
- 团队是否具备 Java/C++/K8s/on-call 能力?谁值夜班?
- 3 年 TCO:存储、计算、出流量、支持、人力各多少?
- 版本升级节奏与回滚方案?最近一次破坏性变更是什么?
90 天路线可以压成四段。第 1–2 周定事件 taxonomy、身份规则、会话规则、10 个核心指标,先写“指标字典”,不管引擎。第 3–4 周搭最小管道,建事件表与 7 天回填,用 1% 流量验证去重与迟到。第 5–8 周实现事件分析、漏斗、留存、路径四条查询,把常用查询做成物化视图或预聚合,压测 50 并发。第 9–12 周接 Superset/Metabase 做内部看板,接 GrowthBook 做实验,补权限、审计、监控、备份、成本看板,写 runbook。
三个不要:不要用厂商 benchmark 当 SLA;不要在没有指标字典时上 AI NLQ(自然语言查询),错误答案会更快;不要把所有租户、所有查询放在一个集群里。
POC 的设计比 POC 的结论重要。拿自己的 7 天事件数据、自己的 20 条查询、自己的并发,记录 p50/p95、CPU、磁盘、成本;必须包含大漏斗、跨表 join、明细回查三个坏查询。只测 COUNT(*) 的 POC,换来的只是一个会骗人的数字。
采购与自建的决策线可以写得很硬:团队少于 3 个数据工程师、事件量小于 5,000 万/日、没有强合规要求,优先托管或 SaaS;有 5 人以上平台团队、事件量过亿、数据不能出网,再考虑自建。自建不是省钱,是用人力换控制权;把这句话写进立项材料,能避免一半的失败项目。