
StarRocks bitmap_intersect 聚合函数详解基于位图交集实现留存计算【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks本文聚焦 StarRocks 位图函数家族中的bitmap_intersect聚合函数它接收一组 bitmap 输入计算这些位图的交集并返回结果 bitmap是留存分析、标签人群重叠计算等场景的高性能基石。阅读本文后你将掌握bitmap_intersect的语法、与bitmap_union配合的两段式聚合写法、与bitmap_to_string联用的结果解析方法并能结合 bitmap_intersect.h 的源码理解其底层按位与AND实现原理与适用边界。函数定位分组后的位图交集bitmap_intersect是 StarRocks 提供的聚合函数Aggregation Function官方文档docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_intersect.md对其定位是在分组group by之后计算 bitmap 交集典型应用场景是用户留存率user retention rate计算——即找出“今天和昨天都活跃过的用户”。位图Bitmap在 StarRocks 中被广泛用于对海量用户 ID 等整型集合做压缩存储与集合运算。与普通的COUNT(DISTINCT)相比位图方案在亿级基数场景下具有显著的内存与性能优势。bitmap_intersect正是位图集合运算中“求交集”的聚合入口与之同族的位图函数还包括bitmap_union并集、bitmap_union_count并集去重计数、bitmap_and两个 bitmap 的交集、bitmap_xor对称差集等完整清单可参见 bitmap-functions.mdx。函数语法与返回值BITMAP BITMAP_INTERSECT(BITMAP value)参数一组BITMAP类型的值通常来自某个分组内的多行数据返回值BITMAP类型即这组 bitmap 的公共元素集合交集语义输入一个 bitmap 集合求该集合中所有位图的交集并返回结果位图。若分组内只有一行输入则交集结果即该行自身的 bitmap若某分组不存在公共元素则返回空位图。从聚合器注册处aggregate_resolver_minmaxany.cpp可以看到bitmap_intersect被注册为TYPE_OBJECT输入/输出类型的聚合函数底层由AggregateFactory::MakeBitmapIntersectAggregateFunction()创建见 aggregate_factory.hpp其聚合状态为BitmapValuePacked——一个由BitmapValue与initial初始化标记组成的结构体。使用示例标签维度下的留存计算表结构前提bitmap_intersect的输入位图通常由位图聚合列提供。以下表结构以user_id为位图聚合列bitmap_union作为聚合类型tag为用户标签date为活跃日期KeysType: AGG_KEY Columns: tag varchar, date datetime, user_id bitmap bitmap_union在 StarRocks 中这类表一般通过DUPLICATE KEY明细表配合bitmap_union(user_id)预聚合或直接使用聚合模型表中类型为BITMAP、聚合方式为BITMAP_UNION的列来承载用户 ID 集合。场景一计算各标签下“今日且昨日”均活跃的用户数-- Calculate users retention under different tags today and yesterday. select tag, bitmap_intersect(user_id) from ( select tag, date, bitmap_union(user_id) user_id from table where date in (2020-05-18, 2020-05-19) group by tag, date) a group by tag;这段 SQL 采用两段式聚合内层聚合按tag, date分组用bitmap_union(user_id)把同一天、同一标签下的所有用户 ID 合并成该日的用户位图。bitmap_union是位图并集聚合语义上等价于“当日活跃用户集合”外层聚合按tag分组对内层产出的每一天的位图执行bitmap_intersect得到“两天都出现过”的公共用户集合即留存用户。由于bitmap_intersect是聚合函数无法直接对两列 bitmap 做点对点运算因此必须先在内层将每日用户合并为单行位图外层才能以位图为单位求交集——这正是上述两段式写法的核心原因。场景二输出留存用户的具体 IDbitmap_intersect返回的是BITMAP类型无法直接以整数列表形式展示。将其与bitmap_to_string函数联用即可把位图展开为逗号分隔的 ID 字符串--Find out users retained under different tags today and yesterday. select tag, bitmap_to_string(bitmap_intersect(user_id)) from ( select tag, date, bitmap_union(user_id) user_id from table where date in (2020-05-18, 2020-05-19) group by tag, date) a group by tag;此时每个tag分组返回一行第二列形如1,5,23的字符串直观展示留存用户 ID 明细。若需进一步统计留存人数可将bitmap_to_string换成bitmap_count(bitmap_intersect(user_id))得到留存用户数用于计算留存率留存数 / 昨日或今日活跃总数。源码原理状态机驱动的按位与聚合bitmap_intersect的 BE 端实现位于 bitmap_intersect.h其核心是一个继承自AggregateFunctionBatchHelperBitmapValuePacked, BitmapIntersectAggregateFunction的聚合器类。从源码看它的求交逻辑非常直白由initial标记构成一个两态状态机update()单行更新第一个 bitmap 输入时用|按位或直接写入状态并置initial true之后每来一个 bitmap都用按位与与当前状态求交集见 bitmap_intersect.hmerge()分片合并多 BE / 多分片并行聚合时将其他分片的中间状态以同样的“首次赋值、后续按位与”方式合并进当前状态见 bitmap_intersect.hfinalize_to_column()把最终 bitmap 追加到结果列见 bitmap_intersect.h。这里的“首次用或运算赋值”是实现细节上的一个等价技巧对于首个输入|即赋值保证空分组语义下交集起点是第一个 bitmap 本身之后逐位求交即可收敛到公共集合。聚合函数名由get_name()返回bitmap_intersect见 bitmap_intersect.h与 SQL 中的函数名一一对应。测试佐证交集语义与空值处理BE 端单测 aggregate_test.cpp 直接验证了交集语义构造三个 bitmap{1}、{2,1}、{1,3}连续update后finalize断言结果to_string()为1——即三个集合的公共元素只有1。该测试同时覆盖了多行输入的累积求交路径。另一组测试 aggregate_test.cpp 验证了nullable 输入场景对NullableColumn包装的 bitmap 列执行bitmap_intersect结果同样正确。这意味着在实际表中存在NULL位图值时聚合器仍可正常工作底层BitmapColumn以对象列形式承载位图数据。注意事项与适用边界输入必须为 BITMAP 类型若原始列是整型 ID需先用to_bitmap或bitmap_hash转换为 bitmap再参与bitmap_union/bitmap_intersect运算留存的基数前提bitmap_intersect只负责求交留存率分母如昨日活跃总数需另行用bitmap_union_count或bitmap_count(bitmap_union(...))计算与bitmap_and的区别bitmap_and是标量函数对两列 bitmap 逐行求交bitmap_intersect是聚合函数对分组内多行 bitmap 求交二者适用 SQL 形态不同结果位图可能为空当分组内各 bitmap 无公共元素时返回空位图配合bitmap_count得到 0位图基数上限StarRocks 位图单元素上限为 2^64 - 1bitmap_intersect的结果继承位图自身的容量与序列化约束。小结bitmap_intersect是 StarRocks 位图分析体系中负责“求交集”的聚合算子SQL 侧以BITMAP_INTERSECT(BITMAP value)呈现配合内层bitmap_union预聚合即可高效完成多日留存、多标签人群重叠等集合运算BE 侧则以BitmapValuePacked为状态、按位与为核心算子兼顾并行分片下的正确合并。对于留存率类指标bitmap_intersectbitmap_to_string/bitmap_count的组合已成为标准写法值得在离线与实时分析场景中优先选用。关键词BITMAP_INTERSECT, BITMAP, 位图交集, 留存计算, StarRocks 聚合函数【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考