Bitmap 类型说明
Bitmap(位图)是云器 Lakehouse 中用于存储和处理集合类型数据的高效数据类型。云器 Lakehouse 中的 Bitmap 是 64 位的,使用 Roaring Bitmap 压缩算法进行优化,能够高效地存储和处理大规模的整数集合。
Bitmap 通过位级操作来表示整数集合,提供极高的空间压缩率。相比于直接存储数组,Bitmap 能够显著降低存储成本,同时提供快速的集合操作性能。
Bitmap 的特点
- 64 位整数支持:支持存储 0 到 264-1 范围内的整数
- 高效压缩:使用 Roaring Bitmap 算法,空间占用极小
- 快速运算:支持并集、交集、补集等集合操作,性能优异
- 二进制序列化:可与 binary 类型相互转换,方便数据交换
- 灵活查询:支持集合包含检查、基数计算等操作
语法
创建包含 Bitmap 列的表
示例:
构建 Bitmap 数据
使用 bitmap_build 函数
从整数数组构建 Bitmap 对象:
示例:
使用 GROPU_BITMAP_STATE 函数
根据输入的表达式(expr)构建一个 bitmap 类型的结果,函数通常用于对整数类型的数据进行分组操作,并将每个分组的唯一值转换为一个 bitmap 数组。
示例:
注意事项
功能限制
- 不支持比较操作:Bitmap 类型不支持直接的比较操作(<、>、=、!=等)
- 不支持排序和分组:Bitmap 列不能用于 ORDER BY、GROUP BY 或 DISTINCT 操作
- 不支持作为键:Bitmap 不能作为表的 PRIMARY KEY、PARTITION KEY 或 CLUSTER KEY
- 查询屏显示:clickzetta-java 的版本是 >3.0.21
数据有效性
- 有效的整数范围:bitmap_build 函数的输入数组必须包含有效的整数值
- Binary 转换:使用 binary_to_bitmap 进行转换时,输入的 binary 数据使用bitmap_to_binary转化必须是有效的 Bitmap 序列化格式
- 空值处理:Bitmap 本身可以是 NULL,但数组中的 NULL 值会被忽略
性能考虑
- 适用场景:Bitmap 最适合存储稀疏的整数集合或大整数集合
- 集合运算:大规模的集合运算应在数据库层完成,而不是在应用层处理
常见 Bitmap 函数
更多Bitmap函数参考Bitmap文档
数据构造函数
bitmap_build
从整数数组构建 Bitmap 对象。
| 参数 | 说明 |
|---|---|
| array | 包含整数的数组表达式 |
返回值: bitmap
数据转换函数
bitmap_to_array
将 Bitmap 转换为整数数组。
返回值: array<integer>
bitmap_to_binary
将 Bitmap 转换为 binary 类型。
返回值: binary
binary_to_bitmap
将 binary 类型转换为 Bitmap。
返回值: bitmap
集合运算函数
bitmap_and
计算两个 Bitmap 的交集(与操作)。
返回值: bitmap
bitmap_or
计算两个 Bitmap 的并集(或操作)。
返回值: bitmap
bitmap_xor
计算两个 Bitmap 的异或集(异或操作)。
返回值: bitmap
统计函数
bitmap_cardinality
计算 Bitmap 中元素的个数(基数)。
返回值: bigint
查询函数
bitmap_contains
检查 Bitmap 中是否包含指定的整数。
| 参数 | 说明 |
| bitmap | Bitmap 对象 |
| element | 要检查的整数值 |
返回值: boolean
案例
案例 1:创建表并插入数据
案例 2:查询 Bitmap 中的元素
执行结果:
| user_id | tags |
| 1 | [1, 3, 5, 7, 9] |
| 2 | [2, 4, 6, 8, 10] |
| 3 | [1, 2, 3, 4, 5] |
| 4 | [5, 6, 7, 8, 9, 10] |
案例 3:计算 Bitmap 基数(元素个数)
执行结果:
| user_id | tag_count |
|---|---|
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 4 | 6 |
案例 4:检查 Bitmap 中是否包含特定元素
SQL 执行:
执行结果:
| user_id | my_tags | has_tag_5 |
|---|---|---|
| 1 | [1, 3, 5, 7, 9] | TRUE |
| 2 | [2, 4, 6, 8, 10] | FALSE |
| 3 | [1, 2, 3, 4, 5] | TRUE |
| 4 | [5, 6, 7, 8, 9, 10] | TRUE |
案例 5:计算两个用户的共同标签(交集)
SQL 执行:
执行结果:
| common_tags |
| [1, 3, 5] |
案例 6:计算两个用户的所有标签(并集)
SQL 执行:
执行结果:
| union_tags |
|---|
| [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] |
案例 7:Bitmap 与 Binary 的转换
SQL 执行:
执行结果:
| user_id | original_tags | restored_tags |
|---|---|---|
| 1 | [1, 3, 5, 7, 9] | [1, 3, 5, 7, 9] |
| 2 | [2, 4, 6, 8, 10] | [2, 4, 6, 8, 10] |
| 3 | [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5] |
| 4 | [5, 6, 7, 8, 9, 10] | [5, 6, 7, 8, 9, 10] |
使用 SDK 方式写入 Bitmap 数据
Java SDK 示例
使用 ClickZetta Java SDK 中的 BulkloadStream 来批量写入 Bitmap 数据。需要使用 RoaringBitmap 构建 Bitmap 对象。
构建bitmap对象:
Maven 依赖
在 pom.xml 中添加以下依赖要求版本大于3.0.23:
Python SDK 示例
Python依赖:
构建bitmap对象:
最佳实践
-
选择合适的数据类型:当需要存储整数集合时,优先考虑 Bitmap,尤其是集合较大或稀疏的场景
-
在数据库层完成运算:充分利用 Bitmap 的集合运算函数,在数据库层完成交集、并集等操作,减少数据传输
-
合理使用转换函数:
- 使用
bitmap_to_array进行展示和调试 - 使用
bitmap_to_binary进行持久化存储
- 使用
-
性能优化:
- 对大规模数据集进行集合运算时,使用 Bitmap 而非 Array
- 使用
bitmap_cardinality进行计数而非转换为数组后计数
