拓冰建站拓冰建站
首页 / 资讯中心 / 正文

StarRocks bitmap_count 函数详解:统计 BITMAP 基数去重、语法与实现原理

StarRocks bitmap_count 函数详解统计 BITMAP 基数去重、语法与实现原理【免费下载链接】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_count函数——用于统计 BITMAP 中置位值为 1的位数即返回 Bitmap 的去重基数cardinality。bitmap_count是精确去重Precise Count Distinct计算链路中的核心函数常与bitmap_from_string、to_bitmap、bitmap_union等配合用于 UV独立访客等场景。读完本文你将掌握其完整语法、返回语义、NULL 处理规则、实际 SQL 用法并从源码层面理解其执行原理与优化器改写机制。函数概述bitmap_count用于统计输入 BITMAP 的 1-bit 数量即该 Bitmap 中不重复元素的个数。Bitmap 在 StarRocks 中是一种紧凑的位图数据结构通过位运算可以高效地表达某个元素是否存在因此bitmap_count天然承担了精确去重计数的职责——它不依赖近似算法返回的是准确的去重结果。该函数属于 bitmap 函数族同一目录下还包含 bitmap_from_string、bitmap_to_string、bitmap_union_count 等配套函数共同构成完整的位图精确去重方案。语法INT BITMAP_COUNT(any_bitmap)参数any_bitmap即任意一个 BITMAP 类型的表达式列、字面量或嵌套函数调用的返回值均可。返回值INT大整数类型表示输入 Bitmap 的 1-bit 数量。说明原始文档中未显式声明返回类型细节从 BE 端实现可确认返回值为 64 位整数见下文实现原理实际使用中直接按整数读取即可。返回值与 NULL 处理bitmap_count遵循如下返回语义输入返回值非空 Bitmap如bitmap_from_string(1,2,4)Bitmap 中置位个数即去重后的元素个数空 Bitmap如bitmap_empty()0NULL0其中bitmap_count(NULL)返回 0是文档明确给出的行为这也是其与众多NULL 输入返回 NULL的函数的关键区别。这一行为在 BE 端源码中有直接对应统计循环中通过viewer.is_null(row)判断若为空值则直接记 0而不是传播 NULL见下文实现代码。因此该函数可以安全地作用于可能含 NULL 的列不会因为 NULL 而污染聚合结果。示例原始文档给出了两个最典型的验证示例可直接在 MySQL 客户端连接 StarRocks 后执行示例 1统计字符串构造的 Bitmap 的置位个数MySQL select bitmap_count(bitmap_from_string(1,2,4)); ------------------------------------------- | bitmap_count(bitmap_from_string(1,2,4)) | ------------------------------------------- | 3 | -------------------------------------------字符串1,2,4经 bitmap_from_string 转换为一个 3 个 bit 置位的 Bitmapbitmap_count返回3。需要说明的是bitmap_from_string在转换过程中会自动去重因此即使输入1,1,2,4得到的 Bitmap 依然是 3 个元素bitmap_count依旧返回3——这正体现了位图天然去重的特性。示例 2NULL 输入返回 0MySQL select bitmap_count(NULL); -------------------- | bitmap_count(NULL) | -------------------- | 0 | --------------------示例 3空 Bitmap 返回 0MySQL select bitmap_count(bitmap_empty()); ----------------------------- | bitmap_count(bitmap_empty()) | ----------------------------- | 0 | -----------------------------bitmap_empty()构造一个不包含任何元素的空 Bitmap见 bitmap_empty其基数自然为 0。典型使用场景UV 精确去重bitmap_count最常见的实战场景是与聚合函数配合完成精确 UV 统计。单看一个 Bitmap 列的计数意义有限通常做法是先用bitmap_union等聚合把分散在各行/各分区的位图合并再用bitmap_count输出最终基数。例如假设表user_visit的user_bitmap列通过 to_bitmap 按用户 ID 构造-- 统计全表独立访客数UV SELECT bitmap_count(bitmap_union(user_bitmap)) AS uv FROM user_visit; -- 按日期维度统计每日 UV SELECT dt, bitmap_count(bitmap_union(user_bitmap)) AS daily_uv FROM user_visit GROUP BY dt;这里bitmap_union负责把多条记录中的 Bitmap 按位合并去重bitmap_count负责输出合并后 Bitmap 的基数两步合起来即精确去重计数。与之对应StarRocks 还提供了一步到位的聚合函数 bitmap_union_count等价于bitmap_count(bitmap_union(...))在需要输出基数时通常更简洁。实现原理从 SQL 到 BE 执行BE 端实现bitmap_count的执行逻辑位于 BE 的 bitmap_functions.cpp核心代码如下StatusOrColumnPtr BitmapFunctions::bitmap_count(FunctionContext* context, const starrocks::Columns columns) { ColumnViewerTYPE_OBJECT viewer(columns[0]); size_t size columns[0]-size(); ColumnBuilderTYPE_BIGINT builder(size); for (int row 0; row size; row) { int64_t value viewer.is_null(row) ? 0 : viewer.value(row)-cardinality(); builder.append(value); } return builder.build(ColumnHelper::is_all_const(columns)); }从源码可以确认三点实现事实返回类型为TYPE_BIGINT64 位整数结果通过ColumnBuilderTYPE_BIGINT构造对应 SQL 层面的INT返回类型NULL 语义viewer.is_null(row) ? 0直接印证了NULL 输入返回 0的行为而非返回 NULL核心计算委托给BitmapValue::cardinality()真正的基数统计由位图数据结构自身完成。cardinality 的内部实现BitmapValue::cardinality()定义于 bitmap_value.cppint64_t BitmapValue::cardinality() const { switch (_type) { case EMPTY: return 0; case SINGLE: return 1; case BITMAP: return _bitmap-cardinality(); case SET: return _set-size(); } return 0; }由 bitmap_value.h 可知StarRocks 的BitmapValue针对不同数据规模使用多态存储BitmapDataType { EMPTY, SINGLE, BITMAP, SET }EMPTY空位图基数 0SINGLE仅 1 个元素的极简场景常见于流式导入基数直接返回 1无需额外计算SET元素较少时add逻辑中集合元素达到 32 个前使用哈希集合存储基数即集合大小BITMAP元素较多时切换为基于 Roaring Bitmap#include roaring/roaring.hh的位图存储基数由 Roaring 底层高效统计。这种分层设计让bitmap_count在0 或 1 个元素的高频场景注释中明确提到 streaming load 场景下零开销返回结果在超大基数场景下则由 Roaring Bitmap 提供压缩存储与快速基数计算。相关配置BE 端存在config::max_length_for_bitmap_function配置用于限制bitmap_to_string等函数在基数过大时抛出异常见 bitmap_functions.cpp。该配置位于 be.conf 中bitmap_count本身不受此限制但在先转字符串再计数的组合用法中可能遇到该阈值实际使用时需注意。优化器层面的改写count(distinct bitmap_col)bitmap_count的另一个关键地位体现在 FE 优化器中。count(distinct bitmap_column)这种写法在 FE 端会被专门的规则改写相关实现位于 RewriteBitmapCountDistinctRule.javareturn aggregationOperator.getAggregations().values().stream().anyMatch( agg - agg.isDistinct() agg.getFunction().getFunctionName().getFunction().equals(FunctionSet.COUNT) agg.getChildren().size() 1 agg.getChildren().get(0).getType().isBitmapType());改写规则的核心逻辑是当检测到count(distinct BITMAP类型列)时将其改写为bitmap_union_count(...)即bitmap_count(bitmap_union(...))的等价形式。这意味着用户既可以直接写bitmap_count(bitmap_union(...))完成精确去重也可以直接写count(distinct bitmap_col)优化器会自动走位图路径享受同样的位图去重性能该规则由RuleSet.java注册到优化器规则集中见 RuleSet.java属于查询优化阶段的常规改写用户无需手动干预。与其他去重方式的对比方式示例特点bitmap_countbitmap_unionbitmap_count(bitmap_union(b))精确去重返回准确基数适合需精确结果的场景bitmap_union_countbitmap_union_count(b)上述组合的聚合函数封装一步到位count(distinct col)count(distinct user_id)精确去重当列为 BITMAP 类型时会被优化器改写为位图路径approx_count_distinctapprox_count_distinct(col)近似去重HyperLogLog 等性能高但结果有误差需要说明bitmap_count返回的是准确基数与近似去重函数存在本质区别选择哪种方式取决于业务对精确度与性能的权衡。总结bitmap_count(any_bitmap)返回输入 BITMAP 的 1-bit 数量即精确去重基数NULL 输入与空 Bitmap 均返回0可放心用于含 NULL 的数据列典型用法是与bitmap_union/bitmap_union_count配合实现 UV 精确去重BE 端由 bitmap_functions.cpp 实现底层借助BitmapValue的分层存储EMPTY/SINGLE/SET/BITMAP与 Roaring Bitmap 高效计算基数FE 优化器会将count(distinct bitmap_col)自动改写为位图去重路径详见 RewriteBitmapCountDistinctRule.java。如需查看更多位图相关函数可查阅 bitmap 函数目录 下的完整函数清单。keywordBITMAPBITMAP_COUNT【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门