用户画像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 – 范围起始点(含),类型为UInt32range_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 – 范围起始点(含),类型为UInt32limit – 子位图基数上限,类型为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)
  • 参数介绍:
  1. bitmap – 位图对象,类型为AggregateFunction(groupBitmap, UInt64)
  2. from_array – 类型为Array(UInt32)。对于范围[0,from_array.size()]中的idx,如果bitmap包含from_array[idx],则将其替换为to_array[idx]。注意,如果from_arrayto_array之间有公共元素,则结果取决于数组排序。
  3. 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用户画像标签圈人

Spark+ES+ClickHouse 构建DMP用户画像

基于Flink+ClickHouse构建实时游戏数据分析最佳实践

我用MRS-ClickHouse构建的用户画像系统,让老板拍手称赞