文章目录
- 创建 Bitmap 对象
- Bitmap 转换为整数数组
- 计算总数(去重)值
- 指定start, end 索引生成子 Bitmap
- 指定 start 索引和数量限制生成子 Bitmap
- 指定偏移量生成子 Bitmap
- 是否包含指定元素
- 两个 Bitmap 是否存在相同元素
- 一个是否为另一个 Bitmap 的子集
- 求最小值
- 求最大值
- And 求交集
- Or 求并集
- Andnot 求差集
- Xor 求并集元素减去交集元素
- 求交集元素个数
- 求并集元素个数
- 求差集元素个数
- 求异或元素个数
- 替换指定范围内的元素
Bitmap 类型说明
- ClickHouse中的Bitmap对象,本质上是聚合函数类型AggregateFunction(groupBitmap, UInt*)
- 使用 Bitmap 存储无符号整数,可以节省存储空间,无法直接查询Bitmap 中的数据,需要转换为数组才可以查看。
- 可以通过
groupBitmap(expr)
快速求去重后的总数,等价于count(distinct expr)
创建 Bitmap 对象
它有两种构造方法:
-
通过 bitmapBuild 将无符号整数数组转换为 Bitmap 对象
SELECT bitmapBuild([1,2,3]) AS res
-
使用聚合函数groupBitmapState创建Bitmap对象, 将无符号整数列转换为 Bitmap 对象。
SELECT groupBitmapState(UserID) AS res FROM hits_v1 where UserID IN ()
快速求去重后的数量:
# 等价于 count(distinct(UserID)) SELECT groupBitmap(UserID) AS res FROM hits_v1
输出如下:
Bitmap 转换为整数数组
bitmapBuild(array)
select bitmapBuild([1,2,3]) AS res, bitmapToArray(res) AS arr;
################
┌─res─┬─arr─────┐
│ │ [1,2,3] │
└─────┴─────────┘
计算总数(去重)值
bitmapCardinality(bitmap)
数组中的元素为 Uint64 类型的
SELECT bitmapCardinality(bitmapBuild([1,2,3,4,5,5,5])) AS res;
#################
┌─res─┐
│ 5 │
└─────┘
指定start, end 索引生成子 Bitmap
bitmapSubsetInRange(bitmap, range_start, range_end)
SELECT bitmapToArray(bitmapSubsetInRange(
bitmapBuild([0,1,2,3,4,5,6,7,8]), toUInt32(1), toUInt32(3))) AS res;
################
┌─res───┐
│ [1,2] │
└───────┘
指定 start 索引和数量限制生成子 Bitmap
bitmapSubsetLimit(bitmap, range_start, cardinality_limit)
SELECT bitmapToArray(bitmapSubsetLimit(
bitmapBuild([0,1,2,3,4,5,6,7,8]), toUInt32(3), toUInt32(30))) AS res;
################
┌─res───────────┐
│ [3,4,5,6,7,8] │
└───────────────┘
指定偏移量生成子 Bitmap
subBitmap(bitmap, offset, cardinality_limit)
偏移量从0开始
SELECT bitmapToArray(subBitmap(
bitmapBuild([0,1,2,3,4,5,6,7,8]), toUInt32(3), toUInt32(30))) AS res;
#######################
┌─res───────────┐
│ [3,4,5,6,7,8] │
└───────────────┘
是否包含指定元素
bitmapContains(bitmap, x)
包含返回1, 不包含返回0
SELECT
bitmapContains(bitmapBuild([1, 3, 5, 7, 9]), toUInt32(3)) AS res1,
bitmapContains(bitmapBuild([1, 3, 5, 7, 9]), toUInt32(4)) AS res2;
#######################
┌─res1─┬─res2─┐
│ 1 │ 0 │
└──────┴──────┘
两个 Bitmap 是否存在相同元素
bitmapHasAny(bitmap1,bitmap2)
存在返回1, 不存在返回0
SELECT
bitmapHasAny(bitmapBuild([1,2,3]), bitmapBuild([3,4,5])) as res1,
bitmapHasAny(bitmapBuild([1,2,3]), bitmapBuild([4,5])) as res2;
####################
┌─res1─┬─res2─┐
│ 1 │ 0 │
└──────┴──────┘
一个是否为另一个 Bitmap 的子集
bitmapHasAll(bitmap1,bitmap2)
SELECT
bitmapHasAll(bitmapBuild([1,2,3]), bitmapBuild([2,3])) as res1,
bitmapHasAll(bitmapBuild([1,2,3]), bitmapBuild([2,3,4])) as res2,
bitmapHasAll(bitmapBuild([1,2,3]), bitmapBuild(emptyArrayUInt8())) as res3;
#####################
┌─res1─┬─res2─┬─res3─┐
│ 1 │ 0 │ 1 │
└──────┴──────┴──────┘
求最小值
bitmapMin(bitmap)
数组为空返回0
SELECT
bitmapMin(bitmapBuild([1,2,3])) as res1,
bitmapMin(bitmapBuild(emptyArrayUInt8())) as res2;
#############
┌─res1─┬─res2─┐
│ 1 │ 0 │
└──────┴──────┘
求最大值
bitmapMax(bitmap)
数组为空,返回0
SELECT
bitmapMax(bitmapBuild([1,2,3])) as res1,
bitmapMin(bitmapBuild(emptyArrayUInt8())) as res2;
###################
┌─res1─┬─res2─┐
│ 3 │ 0 │
└──────┴──────┘
And 求交集
bitmapAnd(bitmap1,bitmap2)
SELECT bitmapToArray(bitmapAnd(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
));
#################
┌─bitmapToArray(bitmapAnd(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4])))─┐
│ [2,3] │
└──────────────────────────────────────────────────────────────────────────┘
Or 求并集
bitmapOr(bitmap1,bitmap2)
SELECT bitmapToArray(bitmapOr(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
));
#################
┌─bitmapToArray(bitmapOr(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4])))─┐
│ [1,2,3,4] │
└─────────────────────────────────────────────────────────────────────────┘
Andnot 求差集
bitmapAndnot(bitmap1,bitmap2)
SELECT bitmapToArray(bitmapAndnot(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
));
#################
┌─bitmapToArray(bitmapAndnot(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4])))─┐
│ [1] │
└─────────────────────────────────────────────────────────────────────────────┘
Xor 求并集元素减去交集元素
bitmapXor(bitmap1,bitmap2)
SELECT bitmapToArray(bitmapXor(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
));
###################
┌─bitmapToArray(bitmapXor(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4])))─┐
│ [1,4] │
└──────────────────────────────────────────────────────────────────────────┘
求交集元素个数
bitmapAndCardinality(bitmap1,bitmap2)
SELECT bitmapAndCardinality(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
);
#############
┌─bitmapAndCardinality(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4]))─┐
│ 2 │
└──────────────────────────────────────────────────────────────────────┘
求并集元素个数
bitmapOrCardinality(bitmap1,bitmap2)
SELECT bitmapOrCardinality(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
);
##################
┌─bitmapOrCardinality(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4]))─┐
│ 4 │
└─────────────────────────────────────────────────────────────────────┘
求差集元素个数
bitmapAndnotCardinality(bitmap1,bitmap2)
SELECT bitmapAndnotCardinality(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
);
##################
┌─bitmapAndnotCardinality(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4]))─┐
│ 1 │
└─────────────────────────────────────────────────────────────────────────┘
求异或元素个数
bitmapXorCardinality(bitmap1,bitmap2)
SELECT bitmapXorCardinality(
bitmapBuild([1,2,3]), bitmapBuild([2,3,4])
);
##################
┌─bitmapXorCardinality(bitmapBuild([1, 2, 3]), bitmapBuild([2, 3, 4]))─┐
│ 2 │
└──────────────────────────────────────────────────────────────────────┘
替换指定范围内的元素
bitmapTransform(bitmap, from_array, to_array)
将Bitmap 中的 [5,999,2] 元素替换为 [2,888,20]
SELECT bitmapToArray(
bitmapTransform(bitmapBuild([1,2,3,4,5,6,7,8,9,10]), [5,999,2], [2,888,20])
) as res;
#############
┌─res───────────────────┐
│ [1,3,4,6,7,8,9,10,20] │
└───────────────────────┘