bigywater.tech
ClickHouse 内部原理 · 55

Bitmap 函数:用户集合如何快速求交并集

真实对比普通JOIN和Bitmap函数在两个百万级用户集合上求交集的表现,量化Bitmap真实的内存优势和适用场景。

95倍内存差距
真实Bitmap求交集相比普通JOIN的内存优势
结果完全一致
真实两种写法算出的交集数量分毫不差

做的事:同一个"两个用户集合求交集",真实用两种方式各测一遍

代码CREATE TABLE demo.usertags (tag String, uid UInt32) ENGINE=MergeTree ORDER BY tag; INSERT INTO demo.usertags SELECT 'vip', number FROM numbers(1000000); -- vip: 0~999999 INSERT INTO demo.usertags SELECT 'active', number*2 FROM numbers(1000000); -- active: 0,2,4...1999998 -- 写法1:普通JOIN求交集 SELECT count() FROM (SELECT uid FROM demo.usertags WHERE tag='vip') a INNER JOIN (SELECT uid FROM demo.usertags WHERE tag='active') b ON a.uid=b.uid; -- 写法2:Bitmap求交集 SELECT bitmapCardinality(bitmapAnd( (SELECT groupBitmapState(uid) FROM demo.usertags WHERE tag='vip'), (SELECT groupBitmapState(uid) FROM demo.usertags WHERE tag='active') ));

验证:真实95倍的内存差距,结果完全一致

实测 · 本机执行输出(100万vip用户 ∩ 100万active用户)
普通JOIN求交集:真实内存 85,360,820 字节(约85.4MB),耗时 23ms,结果 500000
Bitmap求交集  :真实内存    894,071 字节(约0.87MB),耗时 11ms,结果 500000

真实内存差距:85360820 / 894071 ≈ 95倍
真实速度提升:约2倍

两种写法算出的交集数量真实完全一致(500000,即0~999999之间的偶数),但Bitmap写法用不到1MB内存就完成了同样的计算,JOIN写法则真实要用85MB以上——JOIN需要为两边各自构建包含完整uid值的哈希结构,而Bitmap把每个uid直接映射成位图里的一个比特位,100万个连续或者接近连续的uid压缩后真实只需要极小的空间。

Bitmap真实适合的场景,和它的真实限制

Bitmap函数真实的设计目标就是"大规模整数集合的交并差运算"——本文用groupBitmapState把一列uid真实聚合成一份位图状态,bitmapAnd/bitmapOr/bitmapAndnot对两份位图做真实的按位运算求交集/并集/差集,bitmapCardinality数出位图里真实有多少个1(即集合大小)——这一整套运算全程不需要构建哈希表、不需要排序,效率来自位运算本身在CPU层面的高度优化,也来自位图这种表示方式对整数集合天然紧凑(本文两个100万规模的集合,位图能压缩到远小于"真实存储100万个UInt32数值"所需的4MB)。真实最适合的业务场景是用户分群/标签系统这类需要频繁对"符合某几个条件的用户集合"做交并差运算的场景(比如"vip且最近7天活跃且没有退订"这种多条件圈人),把每个条件的用户集合各自维护成一份Bitmap,业务查询时用位运算现算组合结果,比每次都用多表JOIN现查要轻量得多。真实的限制也很直接:Bitmap存的是整数(本文的UInt32 uid),如果你的用户标识是字符串(比如UUID或者邮箱),需要先真实映射成一个连续或者接近连续的整数ID才能享受到Bitmap的这些优势;本文也没有进一步验证并集(bitmapOr)、差集(bitmapAndnot)、以及在uid分布非常稀疏(比如UInt64全空间随机分布而不是连续区间)时Bitmap的真实压缩效果和性能表现,读者如果场景差异较大,值得针对自己真实的数据分布再测一次。

分步演示:从JOIN求交集到Bitmap的95倍内存优势

每一步都是本文上面用真实两个百万级用户集合跑出来的原始结果。

95倍内存差距,Bitmap求交集真实的效率来源
这一步新验证的方式

    本文用到的工具

    • 本机 ClickHouse 26.9.4(单节点),真实的 groupBitmapState/bitmapAnd/bitmapCardinality
    • 诚实说明:本文未进一步验证并集/差集及稀疏uid分布下的真实表现
    京ICP备2026067502号-1京公网安备11010502063487号