广告是支撑互联网高速发展的经济基石,也是很多互联网公司的重要收入来源。字节跳动的广告平台管理着 EB 量级的数据和服务着数以千万的商业用户,其中 ClickHouse 作为核心引擎支撑了海量数据在线分析的需求。
本次分享中,介绍了 ClickHouse 在字节跳动广告业务上的应用与实践,包含人群预估、数据分析、人群画像等多个场景。其中着重介绍了如何通过深度优化高效解决广告人群预估的问题,以及未来的迭代计划。(文末附 ClickHouse 沙龙第三场:《ClickHouse 在实时场景的应用和优化》报名方式)
沙龙视频
ClickHouse 在字节广告 DMP& CDP 的应用
讲师:董一峰 字节跳动 ClickHouse 研发工程师
文字沉淀
业务背景
众所周知,广告是很多互联网公司的主要收入,对于字节跳动来说也是如此。那么,在字节跳动广告的 DMP&CDP 业务,乃至所有广告业务中,有哪些场景在使用 ClickHouse 呢?是在线服务还是离线统计的呢?应该说都有。
可以从三个场景来讲:人群预估、人群画像和统计分析。
人群预估主要是根据一定的圈选条件,确认命中的用户数目。在广告精准投放过程中,广告主需要知道当前选定的人群组合中大概会有多少人,用于辅助判断投放情况进而确定投放预算。因为是在线业务,一般要求计算的时间不能超过 5 秒。
人群画像主要是对广告投放的用户群进行画像分析,也是在线的,同样对时间有一定的要求,因为是偏分析的场景,一般不能超过 20 秒,否则用户的体验就非常差了。
统计分析的使用场景比较多,在线、离线都有,包括一些搜索词统计分析,广告、投放收入数据的分析等等,应用的方面很多。
我今天主要分享的是人群预估,因为这是一个比较大的难点。而对于统计分析来说本身就是 ClickHouse 的强项。
就如我之前说的,人群预估就是根据一定的圈选条件,确认命中的用户数目。比如下图中我们可以看到,在投放广告的时候,可以根据地域、性别、年龄、兴趣、首次激活时间等条件进行圈选。其本质就是集合的快速交并补计算。

举一个简单的例子,假设一个望远镜厂商想通过投放广告吸引用户购买。那么假设他想投给在北京的喜欢户外或者爬山的人。本质上来说,我们就是通过集合运算,把喜欢户外和喜欢爬山的人群求并集,然后与北京的人群求交集,也就是北京的喜欢户外或者爬山的人。
这个结果就是我们想要投广告对应的的人群,而我们的目标就是能够快速地求这个人群对应的用户数。

因此,我们假设平台的全量用户是 8 人,分别是从 uid1 到 uid8。其中北京共有 5 人,分别是 uid 1 到 uid5,对应集合 A;喜欢户外的是 uid1 和 4,对应集合 B;喜欢爬山的是 uid 1、3、5、6,对应集合 C。那么,我们想要投放广告的人数是 A 交上 B 和 C 的并集,uid 1、3、4、5 共 4 人。
听起来就是集合运算,并不复杂。那么难点和挑战在哪里?主要是 3 个方面:
人群包数据量多,基数大。平台的用户数上亿,仅抖音的 DAU 就好几亿,抖音、头条对应的人群包在亿级别。整体的人群基数大,对应的标签也非常多。
计算复杂(单次计算可能包含几百上千个人群包),从之前的图我们可以看出,广告主可以设定一个非常复杂的圈选条件。
查询时长要求短(小于 5 s),其实如果页面上等待时间超过 1s,是有明显感知。如果超过 5 s,那么广告主的体验确实会非常不好。
除了这个之外,人群权限计算的人群包还需要与其他数据 join 进行分析,这就意味着说我们不仅仅只出一个数,还有比较复杂的计算。我们的计算引擎必须要有一定的分析能力,能够进行复杂的分析计算。
在使用 ClickHouse 之前我们也尝试了不少已有的系统,如 Druid、ES、Spark,甚至业务方还自研过一个系统。其中 Druid、ES、Spark 均不能很好的满足时间期望。自研的系统因为我们可以高度的定制化,性能上能够上来,但缺乏一定的灵活性。
因此,通过对比我们选择了 ClickHouse。原因主要有两个方面
第一是快,特别适用于大宽表的场景,这个是其他引擎所不能比拟的。
第二是架构简单,我们可以很好地做很多定制化的开发,甚至去修改整个执行逻辑,这个我后面会提到,我们其实对于 ClickHouse 有比较大的改动。
技术方案 V1
那么首先是我们的第一版技术方案,这个技术方案的背景是,业务提出来希望能够尽快上线,时间比较紧。

我们采用明细存储的方式,表有 2 列,分别是 tag_id 和 uid。每一个 tag_id 表示一个人群包,uid 是对应的用户 id。那么如果是一个比较大的人群包,可能需要用上亿行来表示。我们