用户画像Clickhouse位图函数实践总结
Posted 扫地增
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户画像Clickhouse位图函数实践总结相关的知识,希望对你有一定的参考价值。
文章目录
1 位图概念
说到位图我们就不得不从位算开始,虽然大部分语言都有提供位运算,但是,并没有提供一种类似于位数组的类型,要使用这些位运算,我们只能通过数字类型来实现,比如Java中的int/long等类型。而这些数字类型的数组,我们一般可以称之为“位图”(BitMap)。
位图bitmap
是一种非常常用的结构,在索引,数据压缩等方面有广泛应用。所谓的 bitmap 就是用一个 bit 位来标记某个元素对应的 value, 而 key 即是该元素。由于采用了 bit 为单位来存储数据,因此在存储空间方面,可以大大节省。
2 位图函数
2.1 位图函数作用
位图函数用于对两个位图对象进行计算,对于任何一个 位图函数
,它都将返回一个 位图对象
,例如and,or,xor,not等等。比如:x y
就是位图对象,f
就是位图函数,f(x,y)
就是位图对象。
2.2 位图函数构造方法
位图对象有两种构造方法。一个是由聚合函数groupBitmapState
构造的,另一个是由Array Object
构造的。同时还可以将位图对象转化为数组对象。
我们使用RoaringBitmap
实际存储位图对象,当基数小于或等于32时,它使用Set保存。当基数大于32时,它使用RoaringBitmap
保存。这也是为什么低基数集的存储更快的原因。
2.3 位图函数的基本分类
2.4 位图函数基本使用
2.4.1 数据准备
CREATE TABLE test.bit_map
(
`user_id` UInt64
)
ENGINE = MergeTree
ORDER BY user_id
SETTINGS index_granularity = 8192
数据如下:
┌─user_id─┐
│ 1 │
│ 2 │
│ 3 │
│ 4 │
│ 5 │
│ 6 │
│ 7 │
│ 8 │
│ 9 │
│ 10 │
│ 11 │
└─────────┘
2.4.2 构造位图
2.4.2.1 groupBitmapState
- 参数类型: 函数的参数必须为
UInt64
。 - 返回值类型 :
AggregateFunction(groupBitmap,UInt64)
- 使用实例:
SELECT groupBitmapState(toUInt64(user_id)) as a,
toTypeName(a)
from test.bit_map;
2.4.2.2 bitmapBuild
- 参数类型: 无符号整数数组
array
。 - 返回值类型: 位图对象
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))) AS user_bit_map,
toTypeName(user_bit_map)
FROM test.bit_map
2.4.3 位图对象转化为数组对象
2.4.3.1 bitmapToArray(bitmap)
- 作用: 将位图转换为整数数组。
- 参数类型: bitmap-位图对象
AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 整数数组
- 使用实例:
SELECT
bitmapToArray(groupBitmapState(toUInt64(user_id))) AS user_bit_map,
toTypeName(user_bit_map)
FROM test.bit_map
2.4.4 位图对象的属性
2.4.4.1 bitmapContains
- 语法:
bitmapContains(haystack, needle)
- 作用: 检查位图是否包含指定元素
- 参数类型:
haystack
- 位图对象,AggregateFunction(groupBitmap, UInt64)
。needle
- 元素,类型UInt32
。 - 返回值: 返回值为1,0。包含为1,反之为0。本质在这里可以理解为
boolean
类型,或者枚举类型。 - 使用实例:
SELECT bitmapContains(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(9))AS user_bit_map,
toTypeName(user_bit_map)
FROM test.bit_map
2.4.4.2 bitmapCardinality
- 语法:
bitmapCardinality(bitmap)
- 作用: 返回一个
UInt64
类型的数值,表示位图对象的基数。 - 参数类型: bitmap – 位图对象,
AggregateFunction(groupBitmap, UInt64)
。 - 返回值:
UInt64
,可以理解为位图对象数组中元素的个数。 - 使用实例:
SELECT bitmapCardinality(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id))))) AS user_bit_map,
toTypeName(user_bit_map)
FROM test.bit_map
2.4.4.3 bitmapMin
- 语法:
bitmapMin(bitmap)
- 作用: 返回位图中的最小值。
- 参数类型: bitmap – 位图对象,
AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个
UInt64
类型的数值,表示位图中的最小值。如果位图为空则返回UINT32_MAX
。 - 使用实例:
SELECT bitmapMin(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id))))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type,
bitmapMin(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(nan))))) AS user_bit_map_1,
toTypeName(user_bit_map) AS user_bit_map_1_type
FROM test.bit_map
2.4.4.4 bitmapMax
- 作用: 返回位图中的最大值。
- 语法:
bitmapMax(bitmap)
- 参数类型: bitmap – 位图对象,
AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个
UInt64
类型的数值,表示位图中的最大值。如果位图为空则返回0
。 - 使用实例:
SELECT bitmapMax(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id))))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type,
bitmapMax(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(nan))))) AS user_bit_map_1,
toTypeName(user_bit_map) AS user_bit_map_1_type
FROM test.bit_map
2.4.5 位图转换为新位图
2.4.5.1 bitmapSubsetInRange
- 语法:
bitmapSubsetInRange(bitmap, range_start, range_end)
- 作用: 返回一个新的子位图。
- 参数类型:
bitmap
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。range_start
– 范围起始点(含),类型为UInt32
。range_end
– 范围结束点(不含),类型UInt32
。 - 返回值类型: 返回一个新的子位图。
- 使用实例:
SELECT bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.5.2 bitmapSubsetLimit
- 语法:
bitmapSubsetLimit(bitmap, range_start, limit)
- 作用: 将位图指定范围(起始点和数目上限)转换为另一个位图
- 参数:
bitmap
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。range_start
– 范围起始点(含),类型为UInt32
。limit
– 子位图基数上限,类型为UInt32
。 - 返回值类型: 返回一个新的子位图,
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapSubsetLimit(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6 位图运算
2.4.6.1 bitmapHasAny
- 作用: 与
hasAny(array,array)
类似,判断两个位图对象是包含相同的元素。 - 语法:
bitmapHasAny(bitmap,bitmap)
- 参数类型:
bitmap
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 如果位图有任何公共元素则返回1,否则返回0。
对于空位图,返回0。 - 使用实例:
SELECT bitmapHasAny(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(1),toUInt32(7))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.2 bitmapHasAll
- 作用: 与
hasAll(array,array)
类似,判断第一个位图是否包含第二个位图的所有元素。 - 语法:
bitmapHasAll(bitmap,bitmap)
- 参数类型:
bitmap
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 如果第一个位图包含第二个位图的所有元素,则返回1,否则返回0。如果第二个参数是空位图,则返回1。
- 使用实例:
SELECT bitmapHasAll(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.3 bitmapAnd 与
- 作用: 为两个位图对象进行与操作,返回一个新的位图对象。
- 语法:
bitmapAnd(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个新的位图对象。类型为
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapAnd(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.4 bitmapOr 或
- 作用: 为两个位图对象进行或操作,返回一个新的位图对象
- 语法:
bitmapOr(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个新的位图对象。类型为
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapOr(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.5 bitmapXor 异或
- 作用: 为两个位图对象进行异或操作,返回一个新的位图对象。
- 语法:
bitmapXor(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个新的位图对象。类型为
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapXor(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.6 bitmapAndnot
- 作用: 计算两个位图的差异,返回一个新的位图对象。
- 语法:
bitmapAndnot(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回一个新的位图对象。类型为
AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapAndnot(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.7 bitmapAndCardinality
- 作用: 为两个位图对象进行与操作,返回结果位图的基数。
- 语法:
bitmapAndCardinality(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回结果位图的基数。类型为
UInt64
。 - 使用实例:
SELECT bitmapAndCardinality(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.8 bitmapOrCardinality
- 作用: 为两个位图进行或运算,返回结果位图的基数。
- 语法:
bitmapOrCardinality(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回结果位图的基数。类型为
UInt64
。 - 使用实例:
SELECT bitmapOrCardinality(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.9 bitmapXorCardinality
- 作用: 为两个位图进行异或运算,返回结果位图的基数。
- 语法:
bitmapXorCardinality(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回结果位图的基数。类型为
UInt64
。 - 使用实例:
SELECT bitmapXorCardinality(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.10 bitmapAndnotCardinality
- 作用: 计算两个位图的差异,返回结果位图的基数。
- 语法:
bitmapAndnotCardinality(bitmap1,bitmap2)
- 参数类型:
bitmap1
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。bitmap2
– 位图对象,AggregateFunction(groupBitmap, UInt64)
。 - 返回值类型: 返回结果位图的基数。类型为
UInt64
。 - 使用实例:
SELECT bitmapAndnotCardinality(bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(6),toUInt32(10)),bitmapSubsetInRange(bitmapBuild(bitmapToArray(groupBitmapState(toUInt64(user_id)))),toUInt32(7),toUInt32(9))) AS user_bit_map,
toTypeName(user_bit_map) AS user_bit_map_type
FROM test.bit_map
2.4.6.11 bitmapTransform
- 作用: 将位图中的值数组转换为另一个值数组,结果是一个新的位图。
- 语法:
bitmapTransform(bitmap, from_array, to_array)
- 参数介绍:
bitmap
– 位图对象,类型为AggregateFunction(groupBitmap, UInt64)
。from_array
– 类型为Array(UInt32)
。对于范围[0,from_array.size()]
中的idx
,如果bitmap
包含from_array[idx]
,则将其替换为to_array[idx]
。注意,如果from_array
和to_array
之间有公共元素,则结果取决于数组排序。to_array
– 类型为Array(UInt32)
, 它的大小应该与from_array
相同。
- 返回值类型:
返回结果位图对象。类型为AggregateFunction(groupBitmap, UInt64)
。 - 使用实例:
SELECT bitmapToArray(bitmapTransform(bitmapBuild([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), cast([5,999,2] as Array(UInt32)), cast([2,888,20] as Array(UInt32)))) AS res
位图总结:
通过以上我们了解到位图对象有两种构造方法。其一是由聚合函数groupBitmapState构造的,其二是由Array Object构造的。同时还可以将位图对象转化为数组对象。对于任何一个位图函数,计算结果都将返回一个位图对象。带有Has的判断函数返回的数值是逻辑值0或者1;其中带有Cardinality后缀的函数返回的数值是运算后的结果位图的基数;其他的位图运算返回的是结果位图,例如And,Or,Xor,Andnot等。到此我们关于clickhouse位图的讲解就结束了,希望可以帮到大家。
以上是关于用户画像Clickhouse位图函数实践总结的主要内容,如果未能解决你的问题,请参考以下文章
一文搞定ClickHouse在苏宁用户画像场景的实践(建议收藏)
《ClickHouse企业级应用:入门进阶与实战》8 基于ClickHouse Bitmap实现DMP用户画像标签圈人
《ClickHouse企业级应用:入门进阶与实战》8 基于ClickHouse Bitmap实现DMP用户画像标签圈人