BITMAP精准去重

本文介绍云数据库 SelectDB 版提供的Bitmap去重功能,帮助您进行数据去重,加速查询。

概述

云数据库 SelectDB 版支持Bitmap类型,在Aggregate数据模型中,Bitmap类型的Value字段可以和集合的交并集聚合函数配合,实现数据的精确去重功能。

传统数据仓库中的Bitmap去重功能,对亿级别以上Bitmap大基数的交并集计算性能较差,有两个主要原因:一是当Bitmap基数较大(超过1 GB)时,网络和磁盘IO处理时间比较长;二是集群在扫描数据后,会全部传输到顶层节点进行并集运算,给顶层单节点带来压力。

SelectDB针对分布式环境进行了优化设计,可以将Bitmap列的值按照Hash分桶划分打散,使得不同值存储在不同的分桶中,保证不同分桶的Bitmap值是正交的,基数大幅降低。当查询时,先分别对不同分桶中的正交Bitmap进行聚合计算,然后再由顶层节点将聚合计算后的值合并输出。如此会大大提高计算效率,也解决了顶层节点的单点计算瓶颈问题。

使用示例

  1. 建表时需要使用Aggregate数据模型,Value字段的数据类型是Bitmap,聚合函数是集合的交并集函数,例如Bitmap_UNION,同时需要创建一个列用来表示分桶ID,示例如下。

    说明

    用于分桶ID的列和BUCKETS要设置合理,用于分桶ID的列的基数至少是BUCKETS的5倍以上,以使数据Hash分桶后尽量均衡。

    CREATE TABLE `user_tag_Bitmap` (
      `tag` bigint(20) NULL COMMENT "用户标签",
      `hid` smallint(6) NULL COMMENT "分桶id",
      `user_id` Bitmap Bitmap_UNION NULL COMMENT ""
    ) ENGINE=OLAP
    AGGREGATE KEY(`tag`, `hid`)
    COMMENT "OLAP"
    DISTRIBUTED BY HASH(`hid`) BUCKETS 3

    在创建表的Schema中增加了列hid,作为Hash分桶列,可代表user_id列值的范围。

  2. 数据导入。

    LOAD LABEL user_tag_Bitmap_test
    (
        DATA INFILE('hdfs://abc')
        INTO TABLE user_tag_Bitmap
        COLUMNS TERMINATED BY ','
        (tmp_tag, tmp_user_id)
        SET (
            tag = tmp_tag,
            hid = ceil(tmp_user_id/500),
            user_id = to_Bitmap(tmp_user_id)
        )
    )
    # 注意:500这个数不固定,可按需调整
  3. 导入数据的格式如下,两列数据分别为tag、user_id。

    11111111,1
    11111112,2
    11111113,3
    11111114,4
    ...

    在导入数据时,SelectDB会对列user_id的Bitmap值的Range进行切割。例如,user_id在[1,5000000)区间时hid值相同,会分配到一个分桶内,因此每个分桶内到的Bitmap都是正交的。以这种方式进行切割,可以利用桶间Bitmap值正交的特性,大幅降低集合交并集的计算量。

  4. 在完成导入之后,可以通过调用Bitmap函数来进行Bitmap的相关操作。具体可调用的Bitmap函数,可以参考SQL手册中的Bitmap函数章节。

正交Bitmap函数

Bitmap查询提供了Bitmap_orthogonal_intersect函数、orthogonal_Bitmap_intersect_count函数、orthogonal_Bitmap_union_count函数、orthogonal_Bitmap_expr_calculate函数、orthogonal_Bitmap_expr_calculate_count函数供正交场景使用。下文将分别介绍这五种函数。

说明

正交Bitmap函数不能用在分区表。因为分区表只保证分区内正交,分区之间的数据无法保证正交,即计算结果无法预估。

Bitmap_orthogonal_intersect

对字段的Bitmap交集,求计算出的具体值。

语法

orthogonal_Bitmap_intersect(Bitmap_column, column_to_filter, filter_values)

参数说明

参数名称

参数说明

Bitmap_column

Bitmap列名称。

column_to_filter

用来过滤的维度列名称。

filter_values

变长参数,过滤维度列的不同取值。

示例

SELECT Bitmap_COUNT(orthogonal_Bitmap_intersect(user_id, tag, 13080800, 11110200)) FROM user_tag_Bitmap WHERE tag IN (13080800, 11110200);

查询执行时聚合分为2层:在第一层,SelectDB先按filter_values对tag进行过滤,然后对SQL中的所有聚合Key列(此处为tag列)的Bitmap求交集;在第二层,SelectDB对所有来源于第一层的Bitmap值循环求并集。

orthogonal_Bitmap_intersect_count​

对字段的Bitmap交集,求值的数量。语法同intersect_count,但实现不同。

语法

orthogonal_Bitmap_intersect_count(Bitmap_column, column_to_filter, filter_values)

参数说明

参数名称

参数说明

Bitmap_column

Bitmap列名称。

column_to_filter

用来过滤的维度列名称。

filter_values

变长参数,过滤维度列的不同取值。

示例

SELECT orthogonal_Bitmap_intersect_count(user_id, tag, 1150000, 1150001, 390006) FROM user_tag_Bitmap WHERE tag IN (1150000, 1150001, 390006);

查询执行时聚合分为2层:在第一层,SelectDB先按filter_values对tag进行过滤,然后对SQL中的所有聚合Key列(此处为tag列)的Bitmap求交集,再计算结果Bitmap的count值;在第二层,SelectDB对所有来源于第一层的count值循环求sum。

orthogonal_Bitmap_union_count

对字段的Bitmap并集,求值的数量。语法同Bitmap_union_count,但实现不同。

语法

orthogonal_Bitmap_union_count(Bitmap_column)

参数说明

参数名称

参数说明

Bitmap_column

待求并集count的Bitmap列名称。

示例

SELECT orthogonal_Bitmap_union_count(user_id) FROM user_tag_Bitmap WHERE tag IN (1150000, 1150001, 390006);

查询执行时聚合分为2层:在第一层,SelectDB先对所有Bitmap求并集,再计算结果Bitmap的count值;在第二层,SelectDB对所有来源于第一层的count值循环求sum。

orthogonal_Bitmap_expr_calculate

对表达式的Bitmap交/并/差集合,求计算出的具体值。

语法

orthogonal_Bitmap_expr_calculate(Bitmap_column, filter_column, input_string)

参数说明

参数名称

参数说明

Bitmap_column

待求并集count的Bitmap列名称。

filter_column

用来过滤的维度列,即计算的Key列。

input_string

计算表达式字符串,用来依据Key列进行Bitmap交并差集表达式计算。

表达式支持的计算符:

&代表交集计算,|代表并集计算,-代表差集计算,^代表异或计算,\代表转义字符。

示例

SELECT orthogonal_Bitmap_expr_calculate(user_id, tag, '(833736|999777)&(1308083|231207)&(1000|20000-30000)') FROM user_tag_Bitmap WHERE tag IN (833736,999777,130808,231207,1000,20000,30000);

查询执行时聚合分为2层:在第一层,SelectDB先解析input_string获取tag过滤条件,然后进行数据过滤,过滤后的数据按照input_string表达式进行Bitmap计算;在第二层,SelectDB对所有来源于第一层的Bitmap值求并集,并返回最终Bitmap结果。

orthogonal_Bitmap_expr_calculate_count

对表达式的Bitmap交/并/差集合,求计算出的值的数量,语法和参数同orthogonal_Bitmap_expr_calculate

语法

orthogonal_Bitmap_expr_calculate_count(Bitmap_column, filter_column, input_string)

参数说明

参数名称

参数说明

Bitmap_column

待求并集count的Bitmap列名称。

filter_column

用来过滤的维度列,即计算的Key列。

input_string

计算表达式字符串,用来依据Key列进行Bitmap交并差集表达式计算。

表达式支持的计算符:

&代表交集计算,|代表并集计算,-代表差集计算,^代表异或计算,\代表转义字符。

示例

SELECT orthogonal_Bitmap_expr_calculate_count(user_id, tag, '(833736|999777)&(1308083|231207)&(1000|20000-30000)') FROM user_tag_Bitmap WHERE tag IN (833736,999777,130808,231207,1000,20000,30000);

查询执行时聚合分为2层:在第一层,SelectDB先解析input_string获取tag过滤条件,然后进行数据过滤,过滤后的数据按照input_string表达式进行Bitmap计算,最后计算结果Bitmap的count值;在第二层,SelectDB对所有来源于第一层的Bitmap值求并集,并返回最终Bitmap结果。