BITMAP
BITMAP 是云器 Lakehouse 的原生位图类型,基于 Roaring Bitmap 压缩算法,用于高效存储和计算大规模整数集合 。它是用户行为分析、标签系统、UV 统计等场景的核心数据结构——将用户 ID 或标签 ID 压缩存入一列,再通过集合运算(交集/并集/差集)直接在数据库层完成人群圈选,无需把数据拉到应用层处理。
选型建议
场景 推荐类型 原因 用户标签、人群圈选、UV 统计 BITMAPBITMAP
集合运算在 DB 层完成,性能远优于 ARRAY 小规模整数集合(<1000 个元素) ARRAYARRAY
BITMAP 有序列化开销,小集合不划算 需要存储非整数元素 ARRAYARRAY
BITMAP 只支持非负整数 需要排序、分组、比较 其他类型 BITMAP 列不支持 ORDER BY / GROUP BY
BITMAP vs ARRAY 性能对比 :对千万级用户 ID 集合做交集,BITMAP 通常比 ARRAY 快 10-100 倍,且存储空间小 5-10 倍。
语法
BITMAP
BITMAP 列存储非负整数集合(0 到 2⁶⁴-1),使用 Roaring Bitmap 压缩,元素自动去重、自动排序。
CREATE TABLE user_tags (
user_id BIGINT,
tag_ids BITMAP
);
构建 BITMAP
bitmap_build — 从数组构建
bitmap_build(array<integer>) → bitmap
SELECT bitmap_to_array(bitmap_build(array(1, 3, 5, 7, 9)));
-- [1, 3, 5, 7, 9]
string_to_bitmap — 从逗号分隔字符串构建
string_to_bitmap(str) → bitmap
SELECT bitmap_to_array(string_to_bitmap('10,20,30'));
-- [10, 20, 30]
⚠️ 字符串中包含负数或格式不正确时返回 NULL。
to_bitmap — 构建单元素 BITMAP
to_bitmap(expr) → bitmap
SELECT bitmap_to_array(to_bitmap(42)); -- [42]
SELECT to_bitmap(-1); -- NULL(负数返回 NULL)
SELECT to_bitmap(NULL); -- NULL
bitmap_empty — 构建空 BITMAP
SELECT bitmap_cardinality(bitmap_empty()); -- 0
GROUP_BITMAP_STATE — 聚合构建(自动去重)
将分组内的整数值聚合为一个 BITMAP,重复值自动去重:
GROUP_BITMAP_STATE(expr) → bitmap
-- 原始数据:user 1 有重复的 tag 20
SELECT user_id, bitmap_to_array(group_bitmap_state(tag_id)) AS tags
FROM (VALUES (1,10),(1,20),(1,20),(1,30),(2,10),(2,40)) AS t(user_id, tag_id)
GROUP BY user_id
ORDER BY user_id;
user_id tags 1 [10, 20, 30] 2 [10, 40]
集合运算
bitmap_and — 交集
bitmap_and(bitmap1, bitmap2) → bitmap
-- user 1: {1,3,5,7,9} user 3: {1,2,3,4,5} → 交集: {1,3,5}
SELECT bitmap_to_array(
bitmap_and(bitmap_build(array(1,3,5,7,9)), bitmap_build(array(1,2,3,4,5)))
);
-- [1, 3, 5]
bitmap_or — 并集
bitmap_or(bitmap1, bitmap2) → bitmap
-- user 1: {1,3,5,7,9} user 2: {2,4,6,8,10} → 并集
SELECT bitmap_to_array(
bitmap_or(bitmap_build(array(1,3,5,7,9)), bitmap_build(array(2,4,6,8,10)))
);
-- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
bitmap_xor — 对称差(只在其中一个集合中出现的元素)
bitmap_xor(bitmap1, bitmap2) → bitmap
-- {1,3,5,7,9} XOR {1,2,3,4,5} → {2,4,7,9}
SELECT bitmap_to_array(
bitmap_xor(bitmap_build(array(1,3,5,7,9)), bitmap_build(array(1,2,3,4,5)))
);
-- [2, 4, 7, 9]
bitmap_andnot — 差集(在第一个集合中但不在第二个中)
bitmap_andnot(bitmap1, bitmap2) → bitmap
⚠️ 函数名是
bitmap_andnotbitmap_andnot
,不是
bitmap_and_notbitmap_and_not
(后者不存在)。
-- {1,2,3,4,5} 减去 {3,4,5,6,7} → {1,2}
SELECT bitmap_to_array(
bitmap_andnot(bitmap_build(array(1,2,3,4,5)), bitmap_build(array(3,4,5,6,7)))
);
-- [1, 2]
查询与统计
bitmap_cardinality — 元素个数
bitmap_cardinality(bitmap) → bigint
SELECT bitmap_cardinality(bitmap_build(array(1,3,5,7,9))); -- 5
SELECT bitmap_cardinality(bitmap_empty()); -- 0
bitmap_contains — 是否包含某元素
bitmap_contains(bitmap, element) → boolean
SELECT bitmap_contains(bitmap_build(array(1,3,5,7,9)), 5); -- true
SELECT bitmap_contains(bitmap_build(array(1,3,5,7,9)), 4); -- false
bitmap_to_array — 转为数组(用于展示)
bitmap_to_array(bitmap) → array<string>
⚠️ 返回的数组元素类型是 STRING ,不是整数。如需整数比较,需显式 CAST:
CAST(elem AS BIGINT)CAST(elem AS BIGINT)
。
SELECT bitmap_to_array(bitmap_build(array(1,3,5))); -- ["1", "3", "5"]
聚合函数
以下聚合函数对多行 BITMAP 进行运算,返回基数(BIGINT),不是 BITMAP 对象 :
函数 说明 返回类型 GROUP_BITMAP(expr)GROUP_BITMAP(expr)
对整数列去重计数(等价于 COUNT DISTINCT) BIGINT GROUP_BITMAP_OR(bitmap_col)GROUP_BITMAP_OR(bitmap_col)
多行 BITMAP 并集的基数 BIGINT GROUP_BITMAP_AND(bitmap_col)GROUP_BITMAP_AND(bitmap_col)
多行 BITMAP 交集的基数 BIGINT GROUP_BITMAP_XOR(bitmap_col)GROUP_BITMAP_XOR(bitmap_col)
多行 BITMAP 异或集的基数 BIGINT GROUP_BITMAP_STATE(expr)GROUP_BITMAP_STATE(expr)
对整数列聚合为 BITMAP 对象 BITMAP
SELECT
group_bitmap(tag_id) AS distinct_tags, -- 3(去重计数)
group_bitmap_or(bm) AS or_cardinality, -- 5(并集大小)
group_bitmap_and(bm) AS and_cardinality -- 1(交集大小)
FROM (
SELECT 1 AS tag_id, bitmap_build(array(1,2,3)) AS bm
UNION ALL SELECT 2, bitmap_build(array(2,3,4))
UNION ALL SELECT 3, bitmap_build(array(3,4,5))
) t;
distinct_tags or_cardinality and_cardinality 3 5 1
类型转换
转换方向 函数 说明 BITMAP → ARRAY bitmap_to_array(bm)bitmap_to_array(bm)
元素为 STRING 类型 BITMAP → BINARY bitmap_to_binary(bm)bitmap_to_binary(bm)
Roaring Bitmap 序列化格式 BINARY → BITMAP binary_to_bitmap(bin)binary_to_bitmap(bin)
输入必须是 bitmap_to_binarybitmap_to_binary
的输出
-- 序列化后反序列化,结果不变
SELECT bitmap_to_array(
binary_to_bitmap(bitmap_to_binary(bitmap_build(array(1,3,5))))
);
-- ["1", "3", "5"]
完整场景示例:用户标签人群圈选
-- 建表
CREATE TABLE user_tags (
user_id BIGINT,
tags BITMAP
);
-- 插入数据(每行代表一个用户的标签集合)
INSERT INTO user_tags VALUES
(1, bitmap_build(array(1, 3, 5, 7, 9))),
(2, bitmap_build(array(2, 4, 6, 8, 10))),
(3, bitmap_build(array(1, 2, 3, 4, 5))),
(4, bitmap_build(array(5, 6, 7, 8, 9, 10)));
-- 查询:有标签 5 的用户
SELECT user_id
FROM user_tags
WHERE bitmap_contains(tags, 5);
-- user_id: 1, 3, 4
-- 查询:user 1 和 user 3 的共同标签
SELECT bitmap_to_array(
bitmap_and(
(SELECT tags FROM user_tags WHERE user_id = 1),
(SELECT tags FROM user_tags WHERE user_id = 3)
)
) AS common_tags;
-- ["1", "3", "5"]
-- 统计:每个用户的标签数量
SELECT user_id, bitmap_cardinality(tags) AS tag_count
FROM user_tags
ORDER BY user_id;
使用限制
BITMAP 列不支持 ORDER BYORDER BY
、GROUP BYGROUP BY
、DISTINCTDISTINCT
、==
、<<
、>>
等比较操作
BITMAP 不能作为 PRIMARY KEY、PARTITION KEY 或 CLUSTER KEY
只支持非负整数(0 到 2⁶⁴-1),负数输入返回 NULL
bitmap_to_arraybitmap_to_array
返回元素为 STRING 类型,需要整数比较时须显式 CAST
SDK 写入
Java
import org.roaringbitmap.longlong.Roaring64NavigableMap;
Roaring64NavigableMap bitmap = new Roaring64NavigableMap();
bitmap.add(1L);
bitmap.add(3L);
bitmap.add(5L);
row.setValue("tags", bitmap);
Maven 依赖(版本需 ≥ 3.0.23):
<dependency>
<groupId>com.clickzetta</groupId>
<artifactId>clickzetta-java</artifactId>
<version>${version}</version>
</dependency>
Python
pip install clickzetta clickzetta-ingestion pyroaring
import pyroaring
bitmap = pyroaring.BitMap64([1, 3, 5, 7, 9])
row.set_value('tags', bitmap)
函数速查表
构建函数
函数 说明 链接 bitmap_build(array)bitmap_build(array)
从整数数组构建 BITMAP → bitmap_empty()bitmap_empty()
构建空 BITMAP → to_bitmap(expr)to_bitmap(expr)
将单个整数/字符串构建为单元素 BITMAP,负数/NULL 返回 NULL → string_to_bitmap(str)string_to_bitmap(str)
将逗号分隔的字符串构建为 BITMAP → bitmap_hash(expr)bitmap_hash(expr)
将任意类型的值哈希为 32 位 BITMAP → bitmap_hash64(expr)bitmap_hash64(expr)
将任意类型的值哈希为 64 位 BITMAP →
集合运算函数
函数 说明 链接 bitmap_and(b1, b2)bitmap_and(b1, b2)
交集,返回 BITMAP → bitmap_or(b1, b2)bitmap_or(b1, b2)
并集,返回 BITMAP → bitmap_xor(b1, b2)bitmap_xor(b1, b2)
对称差(只在其中一个集合中),返回 BITMAP → bitmap_andnot(b1, b2)bitmap_andnot(b1, b2)
差集(在 b1 中但不在 b2 中),返回 BITMAP → bitmap_and_cardinality(b1, b2)bitmap_and_cardinality(b1, b2)
交集的元素个数,返回 BIGINT → bitmap_or_cardinality(b1, b2)bitmap_or_cardinality(b1, b2)
并集的元素个数,返回 BIGINT → bitmap_xor_cardinality(b1, b2)bitmap_xor_cardinality(b1, b2)
对称差的元素个数,返回 BIGINT → bitmap_andnot_cardinality(b1, b2)bitmap_andnot_cardinality(b1, b2)
差集的元素个数,返回 BIGINT →
查询与统计函数
函数 说明 链接 bitmap_cardinality(bitmap)bitmap_cardinality(bitmap)
元素个数,返回 BIGINT → bitmap_count(bitmap)bitmap_count(bitmap)
元素个数,bitmap_cardinalitybitmap_cardinality
的别名 → bitmap_contains(bitmap, elem)bitmap_contains(bitmap, elem)
是否包含指定元素,返回 BOOLEAN → bitmap_has_any(b1, b2)bitmap_has_any(b1, b2)
b1 和 b2 是否有公共元素,返回 BOOLEAN → bitmap_has_all(b1, b2)bitmap_has_all(b1, b2)
b2 是否是 b1 的子集,返回 BOOLEAN → bitmap_min(bitmap)bitmap_min(bitmap)
BITMAP 中的最小值 → bitmap_max(bitmap)bitmap_max(bitmap)
BITMAP 中的最大值 →
转换函数
函数 说明 链接 bitmap_to_array(bitmap)bitmap_to_array(bitmap)
转为数组,元素类型为 STRING → bitmap_to_string(bitmap)bitmap_to_string(bitmap)
转为逗号分隔字符串 → bitmap_to_binary(bitmap)bitmap_to_binary(bitmap)
序列化为 BINARY(Roaring Bitmap 格式) → binary_to_bitmap(binary)binary_to_bitmap(binary)
从 BINARY 反序列化为 BITMAP → bitmap_to_rb32(bitmap)bitmap_to_rb32(bitmap)
转为 32 位 Roaring Bitmap → bitmap_to_rb64(bitmap)bitmap_to_rb64(bitmap)
转为 64 位 Roaring Bitmap → rb32_to_bitmap(expr)rb32_to_bitmap(expr)
从 32 位 Roaring Bitmap 转为 BITMAP → rb64_to_bitmap(expr)rb64_to_bitmap(expr)
从 64 位 Roaring Bitmap 转为 BITMAP →
子集与变换函数
函数 说明 链接 bitmap_remove(bitmap, value)bitmap_remove(bitmap, value)
删除 BITMAP 中的某个元素 → bitmap_subset_in_range(bm, start, end)bitmap_subset_in_range(bm, start, end)
提取值在 [start, end) 范围内的子集(左闭右开) → bitmap_subset_limit(bm, start, limit)bitmap_subset_limit(bm, start, limit)
从值 start 开始,提取最多 limit 个元素 → sub_bitmap(bm, offset, limit)sub_bitmap(bm, offset, limit)
跳过前 offset 个元素,提取后续 limit 个元素 → bitmap_transform(bm, from_arr, to_arr)bitmap_transform(bm, from_arr, to_arr)
将 BITMAP 中指定元素替换为另一组元素 →
聚合函数
函数 返回类型 说明 链接 GROUP_BITMAP_STATE(expr)GROUP_BITMAP_STATE(expr)
BITMAP 将整数列聚合为 BITMAP 对象(自动去重) — GROUP_BITMAP(expr)GROUP_BITMAP(expr)
BIGINT 整数列去重计数,等价于 COUNT DISTINCT — GROUP_BITMAP_OR(bm_col)GROUP_BITMAP_OR(bm_col)
BIGINT 多行 BITMAP 并集的基数 — GROUP_BITMAP_AND(bm_col)GROUP_BITMAP_AND(bm_col)
BIGINT 多行 BITMAP 交集的基数 — GROUP_BITMAP_XOR(bm_col)GROUP_BITMAP_XOR(bm_col)
BIGINT 多行 BITMAP 异或集的基数 —
相关文档