资讯动态

StarRocks bitmap_andnot 函数详解:位图差集运算原理与实战

发布时间:2026/9/17 19:43:24 来源:尧图企业网站定制
StarRocks bitmap_andnot 函数详解位图差集运算原理与实战【免费下载链接】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导读bitmap_andnot是 StarRocks 位图Bitmap函数家族中用于计算差集的核心成员它返回存在于左操作数lhs中但不存在于右操作数rhs中的所有位图值并生成一个新的位图结果。本文以 bitmap_andnot 官方文档为主体骨架结合 StarRocks BE 源码实现 与 单元测试用例深入剖析该函数的语法、语义、NULL 处理规则与底层实现原理帮助你在精确去重、标签画像、集合运算等场景中正确、高效地使用位图差集能力。函数概述bitmap_andnot(BITMAP lhs, BITMAP rhs)是 StarRocks 内置的位图集合运算函数其语义可以概括为返回A − B即所有属于lhs但不属于rhs的位图成员值计算结果以新的 BITMAP 对象返回。它相当于集合论中的差集运算Set Difference与bitmap_and交集、bitmap_or并集、bitmap_xor对称差集共同构成位图集合运算的完整四件套。在 bitmap_functions.h 中的函数注册声明 中可以确认这四个函数均作为向量化表达式DEFINE_VECTORIZED_FN统一注册bitmap_andnot位于与bitmap_and、bitmap_or、bitmap_xor相邻的位置。语法与参数bitmap_andnot(BITMAP lhs, BITMAP rhs)参数说明参数类型含义lhsBITMAP左操作数作为差集的被减集合基准集合rhsBITMAP右操作数作为差集的减除集合返回值BITMAP 类型包含所有在lhs中存在但在rhs中不存在的成员值。需要特别说明的是该函数的语义对参数顺序敏感bitmap_andnot(A, B)与bitmap_andnot(B, A)的结果一般不同与交集、并集的交换律特性截然不同使用时务必确认参数传入顺序。返回值类型说明bitmap_andnot的返回类型为BITMAP。在 StarRocks 的存储与计算引擎中BITMAP 属于对象类型TYPE_OBJECT底层由 BitmapValue 类承载。从 BitmapValue 的实现 可以看出位图内部的存储形态存在三种动态过渡状态EMPTY空、SINGLE单值与BITMAP完整位图。差集运算在源码中通过BitmapValue operator-(const BitmapValue rhs)实现运算过程中可能会触发类型状态迁移例如从 BITMAP 缩减为 EMPTY。这意味着当lhs的所有成员都被rhs覆盖时结果是一个空位图EMPTY而非 NULL当结果仅剩一个成员时内部会以 SINGLE 形态高效存储无需保留完整位图结构。使用示例官方文档提供了两个典型示例直观展示了差集运算的行为mysql select bitmap_to_string(bitmap_andnot(bitmap_from_string(1, 3), bitmap_from_string(2))) cnt; ------ |cnt | ------ |1,3 | ------ mysql select bitmap_to_string(bitmap_andnot(bitmap_from_string(1,3,5), bitmap_from_string(1))) cnt; ------ |cnt | ------ |3,5 | ------示例解析示例一lhs {1, 3}rhs {2}。由于2并不存在于lhs中差集结果仍是{1, 3}说明删除一个不存在的成员不会对结果产生任何影响示例二lhs {1, 3, 5}rhs {1}。1被从基准集合中剔除结果输出{3, 5}。两个示例均通过bitmap_from_string将逗号分隔的字符串构造为位图再用bitmap_to_string将结果位图序列化为可读字符串进行验证。这一「构造 → 运算 → 序列化」的三段式写法是调试位图函数最常用的手段。与相关位图函数的对比函数集合运算结果语义对参数顺序是否敏感bitmap_and交集 A ∩ B两个位图共有的成员否bitmap_or并集 A ∪ B两个位图全部成员否bitmap_xor对称差集 A ⊖ B恰好只存在于其中一个位图的成员否bitmap_andnot差集 A − B存在于 A 但不存在于 B 的成员是底层实现原理核心调用链bitmap_andnot的前端解析与执行入口位于 bitmap_functions.cpp其核心实现逻辑如下StatusOrColumnPtr BitmapFunctions::bitmap_andnot(FunctionContext* context, const starrocks::Columns columns) { RETURN_IF_COLUMNS_ONLY_NULL(columns); ColumnViewerTYPE_OBJECT lhs(columns[0]); ColumnViewerTYPE_OBJECT rhs(columns[1]); size_t size columns[0]-size(); ColumnBuilderTYPE_OBJECT builder(size); for (int row 0; row size; row) { if (lhs.is_null(row) || rhs.is_null(row)) { builder.append_null(); continue; } BitmapValue bitmap; bitmap | (*lhs.value(row)); bitmap - (*rhs.value(row)); builder.append(bitmap); } return builder.build(ColumnHelper::is_all_const(columns)); }这段代码揭示了几个关键实现细节向量化逐行计算函数采用ColumnViewerColumnBuilder的向量化范式对输入列的每一行独立执行差集运算输出新的TYPE_OBJECT列两步运算实现先通过operator|将lhs的值复制进局部变量bitmap再通过operator-执行差集剔除。这两步底层分别对应 BitmapValue 的operator|并集与operator-差集方法语义保证从源码可见运算结果基于lhs的完整拷贝进行因此原始输入位图不会被修改函数具备纯函数特性列类型确认测试代码中通过ColumnHelper::cast_toTYPE_OBJECT断言结果列的类型为对象列column-is_object()印证了返回 BITMAP 类型的设计见 bitmap_functions_test.cpp。NULL 处理规则从源码中if (lhs.is_null(row) || rhs.is_null(row))分支可以确认一个重要的行为规则当lhs或rhs任一输入为 NULL 时bitmap_andnot的该行结果直接返回 NULL。这与 SQL 标准的三值逻辑保持一致——NULL 参与集合运算时结果未定义因此透传 NULL。同时函数入口处的RETURN_IF_COLUMNS_ONLY_NULL(columns)是一个快速路径优化当整列均为 NULL 时直接返回全 NULL 列避免无意义的逐行计算。单元测试验证StarRocks 在 bitmap_functions_test.cpp 中为bitmap_andnot设计了覆盖多种场景的单元测试其中两个典型用例验证了核心语义// 用例 A交集部分被剔除 // lhs {1,2,3,4}rhs {15,22,3,4} // 期望结果1,2 auto column BitmapFunctions::bitmap_andnot(ctx, columns).value(); ASSERT_EQ(1,2, p-get_object(0)-to_string()); // 用例 B两集合无交集结果保持不变 // lhs {1,2,3,4}rhs {12,40,634} // 期望结果1,2,3,4 ASSERT_EQ(1,2,3,4, p-get_object(0)-to_string());这两组用例分别验证了部分剔除当两个位图存在交集成员3、4时交集部分被正确从lhs中移除剩余{1, 2}无交集情形当rhs与lhs完全没有公共成员时差集结果与lhs完全相同即运算对结果无影响。测试采用BitmapValue::add()直接构造位图成员、以to_string()断言结果的模式可在不启动 FE/BE 集群的情况下对函数实现进行快速验证。典型应用场景场景一精确去重后的增量排除在用户行为分析中常需要计算「新增用户」——即存在于本周期活跃用户集合、但不存在于上周期活跃用户集合的用户SELECT bitmap_to_string( bitmap_andnot( bitmap_agg(user_id), -- 本周期活跃用户 (SELECT bitmap_agg(user_id) FROM t_activity WHERE dt 2026-09-16) ) ) AS new_users FROM t_activity WHERE dt 2026-09-17;场景二标签画像差集筛选在标签体系中可利用差集筛选「具有 A 标签但无 B 标签」的客群例如「高价值用户但不含 VIP」SELECT bitmap_count( bitmap_andnot( (SELECT bitmap_union(tag_bitmap) FROM user_tags WHERE tag_id high_value), (SELECT bitmap_union(tag_bitmap) FROM user_tags WHERE tag_id vip) ) ) AS high_value_non_vip_cnt;场景三与 bitmap_to_string / bitmap_count 组合验证在排查位图运算结果时可以沿用官方示例的「构造 → 运算 → 序列化」组合-- 查看差集结果的具体成员 SELECT bitmap_to_string(bitmap_andnot(bitmap_from_string(1,3,5,7), bitmap_from_string(3,7))); -- 查看差集结果的基数 SELECT bitmap_count(bitmap_andnot(bitmap_from_string(1,3,5,7), bitmap_from_string(3,7)));注意事项与使用限制参数顺序敏感bitmap_andnot(A, B)与bitmap_andnot(B, A)通常结果不同务必明确「从谁中减去谁」NULL 透传任一参数为 NULL 时结果为 NULL实际应用中应对可能为空的位图列做 COALESCE 处理空结果非空值当lhs被完全覆盖时返回空位图EMPTY 状态此时bitmap_count返回 0而不是 NULL返回类型固定为 BITMAP结果需配合bitmap_to_string、bitmap_count、bitmap_union等函数使用不能直接作为标量数字参与运算。延伸阅读位图函数家族的完整文档索引位于 docs/en/sql-reference/sql-functions/bitmap-functionsBE 端位图函数实现与注册be/src/exprs/bitmap_functions.cpp、be/src/exprs/bitmap_functions.h位图底层数据结构 BitmapValue涵盖 EMPTY / SINGLE / BITMAP 三种存储形态及operator-、operator、operator|、operator^等全部集合运算算子函数单元测试 bitmap_functions_test.cpp其中包含bitmap_andnot的 16 组覆盖 NULL、常量列、无交集、完全覆盖等场景的测试用例。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价