StarRocks base64_to_bitmap 函数详解:把 Base64 序列化 Bitmap 高效导入 BITMAP 列
【免费下载链接】starrocksThe world's 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
base64_to_bitmap是 StarRocks 提供的 Bitmap 族函数之一,用于将经过序列化并编码为 Base64 字符串的 Bitmap 数据还原为 BITMAP 类型,是 Stream Load / Broker Load 等导入链路中向 BITMAP 列装载数据的关键转换函数。读完本文,你将掌握该函数的语法、底层执行原理(含常量折叠优化与异常处理路径),并能够独立完成「序列化 Bitmap → Base64 编码 → 导入 → 查询」的完整实战流程。该函数自 StarRocks v2.3 起支持。
函数定位:为什么需要 base64_to_bitmap
StarRocks 的 BITMAP 类型常用于精确去重计数(如 UV 统计)场景。BITMAP 是一个二进制对象,无法以可读文本的形式直接写入导入文件,因此在导入之前,需要先在客户端(Java 或 C++ 程序)中构造BitmapValue对象、添加元素、序列化,并将序列化结果编码为 Base64 字符串;待 Base64 字符串进入 StarRocks 后,再用base64_to_bitmap将其还原为 BITMAP 数据落库。
整个过程对应两条链路:
- 序列化方向:
BitmapValue→ 序列化字节 → Base64 字符串(对应逆函数 bitmap_to_base64 与to_base64类函数); - 还原方向:Base64 字符串 →
base64_to_bitmap→ BITMAP 列(本文主角)。
语法与参数
BITMAP base64_to_bitmap(VARCHAR bitmap)参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
bitmap | VARCHAR | 传入的 Base64 字符串。它必须是由 BitmapValue 对象序列化后再经 Base64 编码得到的合法内容,而不是任意 Base64 文本。 |
返回值
返回 BITMAP 类型值。若入参为NULL、空字符串、非法 Base64 或解码后无法反序列化为合法 Bitmap,则根据执行环境返回NULL或抛出错误(详见下文「异常与边界处理」)。
底层实现:从 Base64 到 BitmapValue 的两步还原
base64_to_bitmap的向量化实现在 be/src/exprs/bitmap_functions.cpp,核心逻辑可以拆解为两层:
- Base64 解码:调用
base64_decode2将 VARCHAR 输入解码为原始二进制字节; - Bitmap 反序列化:调用
BitmapValue::valid_and_deserialize(定义于 be/src/types/bitmap_value.h 与 be/src/types/bitmap_value.cpp)校验并还原为内存中的BitmapValue对象。
函数内部针对「常量列」与「普通列」提供了两条执行路径,并配套prepare/close生命周期钩子,见 be/src/exprs/bitmap_functions.h:
- 常量快路径(const path):
base64_to_bitmap_prepare在FRAGMENT_LOCAL阶段检查第 0 列是否为常量列;若是,则在prepare中只解码一次并缓存Base64ToBitmapState,随后base64_to_bitmap_const对所有行复用同一 Bitmap,避免逐行重复解码(对应测试 bitmap_functions_test.cpp); - 通用路径(general path):对非常量列逐行调用
ColumnViewer读取 VARCHAR 值,逐行解码、反序列化,遇到空值或解码失败行则append_null(); - 资源回收:
base64_to_bitmap_close负责释放prepare阶段分配的Base64ToBitmapState,防止状态泄漏。
从行级行为看,base64_to_bitmap_general对每一行执行如下判断(bitmap_functions.cpp):
- 行为
NULL→ 结果为NULL; - 行为空字符串 → 结果为
NULL; base64_decode2返回负值(非法 Base64)→ 结果为NULL;valid_and_deserialize失败 → 若allow_throw_exception()为真则抛出base64_to_bitmap: failed to deserialize bitmap: ...的RuntimeError(错误信息中截取输入前 200 字符辅助排查),否则该行置NULL。
因此,保证写入导入文件的是「合法序列化 + 合法 Base64」的内容,是使用该函数的前提。
前置准备:如何生成合法的 Base64 输入
参数文档要求在使用base64_to_bitmap之前,先用 Java 或 C++ 构造BitmapValue对象、添加元素、序列化并 Base64 编码。C++ 侧的BitmapValue支持三种内部存储形态,反序列化时valid_and_deserialize均能正确还原(对应测试见 bitmap_functions_test.cpp 的bitmapToBase64Test):
- 空 Bitmap:基数 0,往返转换后
cardinality()仍为 0; - Set 形态:逐个 add 不超过 32 个元素时按集合存储(如
{1,2,3,4}); - 32bit / 64bit 位图形态:使用向量或大整数构造时进入位图存储(如
{600123456781, 600123456782, ...}等 64 位值)。
由于bitmap_to_base64与base64_to_bitmap互为逆运算,一个简单可靠的生成方式是:先在 StarRocks 内用bitmap_to_base64对合法 Bitmap 求值得到标准 Base64 样例,再将其写入导入文件——测试bitmapToBase64Test正是采用「先bitmap_to_base64再base64_to_bitmap」的往返断言来验证二者一致性的。
注意:
base64_to_bitmap要求输入是BitmapValue 序列化字节的 Base64 编码,而不是任意字符串的 Base64 编码。把一段普通文本 Base64 化后传入,会因反序列化校验失败而得到NULL或报错。
实战:Stream Load 导入 JSON 中的 Base64 Bitmap
以下完整示例来自函数文档,演示「建表 → Stream Load 导入 → 查询」三步流程。相关导入语法可参阅 STREAM_LOAD。
1. 创建数据库与 Bitmap 表
以下示例创建一个以tagname、tagvalue为主键的 Primary Key 表,其中userid列为 BITMAP 类型,用于存储用户 ID 集合:
CREATE database bitmapdb; USE bitmapdb; CREATE TABLE `bitmap_table` ( `tagname` varchar(65533) NOT NULL COMMENT "Tag name", `tagvalue` varchar(65533) NOT NULL COMMENT "Tag value", `userid` bitmap NOT NULL COMMENT "User ID" ) ENGINE=OLAP PRIMARY KEY(`tagname`, `tagvalue`) COMMENT "OLAP" DISTRIBUTED BY HASH(`tagname`) PROPERTIES ( "replication_num" = "3", "storage_format" = "DEFAULT" );2. 准备 JSON 数据文件
假设本地存在 JSON 文件simpledata,其中userid字段是 BitmapValue 序列化后的 Base64 字符串:
{ "tagname": "Product", "tagvalue": "Insurance", "userid":"AjowAAABAAAAAAACABAAAAABAAIAAwA=" }3. 通过 Stream Load 导入并在 columns 映射中调用函数
使用curl发起 Stream Load,核心在于-H "columns: ..."中用base64_to_bitmap(c3)将 JSON 中的第 3 个字段(Base64 字符串)转换为 BITMAP 值:
curl --location-trusted -u <username>:<password>\ -H "columns: c1,c2,c3,tagname=c1,tagvalue=c2,userid=base64_to_bitmap(c3)"\ -H "label:bitmap123"\ -H "format: json"\ -H "jsonpaths: [\"$.tagname\",\"$.tagvalue\",\"$.userid\"]"\ -T simpleData http://host:port/api/bitmapdb/bitmap_table/_stream_load其中jsonpaths按 JSON 字段顺序把tagname、tagvalue、userid分别映射为c1、c2、c3,再经columns完成「字段 → 列」的最终映射。<username>:<password>替换为实际账号,host:port替换为 FE 的 HTTP 服务地址。
4. 查询验证
导入完成后,使用bitmap_to_string把 BITMAP 还原为逗号分隔的 ID 列表进行验证:
mysql> select tagname,tagvalue,bitmap_to_string(userid) from bitmap_table; +--------------+----------+----------------------------+ | tagname | tagvalue | bitmap_to_string(`userid`) | +--------------+----------+----------------------------+ | Product | Insurance | 1,2,3 | +--------------+----------+----------------------------+ 1 rows in set (0.01 sec)查询结果中的1,2,3表明:JSON 里AjowAAABAAAAAAACABAAAAABAAIAAwA=解码还原出的 Bitmap 包含用户 ID 1、2、3,导入链路完全打通。
异常与边界处理速查
结合函数源码 bitmap_functions.cpp 与常量路径的专项测试 base64ToBitmapConstNullHandling,各边界行为总结如下:
| 输入情形 | 行为 |
|---|---|
NULL | 返回NULL |
空字符串'' | 返回NULL |
非法 Base64(如!!!invalid_base64!!!) | 返回NULL |
| Base64 合法但被截断(末组不完整,无法反序列化) | 返回NULL(allow_throw_exception开启时报错) |
| 合法 Base64 但非 BitmapValue 序列化内容 | 反序列化失败,返回NULL或报错 |
| 合法且完整的 Bitmap 序列化 Base64 | 返回对应 BITMAP(含空 Bitmap、Set、32bit、64bit 各形态) |
从测试用例可以看到,常量路径与通用路径对上述非法输入的行为保持一致,均产出NULL(only_null()列),确保导入任务不会因个别脏数据整批失败——实际导入时建议结合bitmap_to_string等函数对结果做抽样校验。
延伸:同一函数族的配套能力
bitmap_to_base64:base64_to_bitmap的逆函数,将 BITMAP 序列化并 Base64 编码为 VARCHAR,实现见 bitmap_functions.cpp,可用于导出数据或生成可复用的 Base64 样本;bitmap_to_string:将 BITMAP 转为1,2,3形式的可读字符串,是验证导入结果最直观的手段;- Hive UDF 参考实现:仓库在 UDFBase64ToBitmap.java 中提供了
GenericUDF风格的 Java 参考实现,通过java.util.Base64解码字符串并返回字节数组,展示了「客户端侧 Base64 解码 + 服务端反序列化」协作模型的 Java 侧写法; - 向量化测试覆盖:完整行为契约可在 bitmap_functions_test.cpp 的
bitmapToBase64Test、base64ToBitmapConstNullHandling、base64ToBitmapNonConst等用例中找到,它们是理解该函数边界语义的权威参考。
总结
base64_to_bitmap打通了「外部系统序列化 Bitmap → Base64 文本 → StarRocks BITMAP 列」的数据通路,是精确去重场景下导入用户 ID 集合等位图数据的标准入口。使用时务必牢记:输入必须是BitmapValue序列化字节的 Base64 编码;导入侧通过 Stream Load 的columns映射即可完成转换;查询侧用bitmap_to_string即可验证还原结果。其 BE 端实现通过常量快路径与通用路径的分离、valid_and_deserialize的严格校验,在保证性能的同时对脏数据提供了稳健的兜底行为。
【免费下载链接】starrocksThe world's 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),仅供参考