全部產品
Search
文件中心

AnalyticDB:圈人函數(Roaring Bitmap)

更新時間:Oct 25, 2024

ROARING BITMAP是一種高效的Bitmap壓縮演算法,目前已被廣泛應用在各種語言和各種巨量資料平台,常用於去重、標籤篩選、時間序列等計算中。本文將為您介紹如何使用ROARING BITMAP函數。

版本要求

  • 3.1.6.4及以上版本,支援在OSS外表中使用ROARING BITMAP類型及相關函數。

  • 3.2.1.0及以上版本,支援在內表中使用ROARING BITMAP類型及相關函數。

說明

如何查看叢集核心版本,請參見如何查看執行個體版本資訊。如需升級核心版本,請聯絡支援人員。

使用限制

AnalyticDB for MySQL使用ROARING BITMAP函數,具體限制如下:

  • 不支援直接SELECT某個ROARING BITMAP類型。如需查看ROARING BITMAP欄位中的元素,請用Unnest操作,如:

    SELECT * FROM unnest(RB_BUILD(ARRAY[1,2,3]));
  • 3.2.1.0以下版本,ROARING BITMAP類型僅在OSS外表原生支援,不支援直接建立含有ROARING BITMAP類型列的表。如果查詢AnalyticDB for MySQL內表時使用ROARING BITMAP函數,需要使用rb_build_varbinary將VARBINARY類型轉換成ROARING BITMAP類型,如:

    // 定義內表
    CREATE TABLE test_rb_cstore (id INT, rb VARBINARY);
    
    // 通過ROARING BITMAPFunction Compute
    SELECT RB_CARDINALITY(RB_BUILD_VARBINARY(rb)) FROM test_rb_cstore;

函數列表

ROARING BITMAP函數包括純量涵式和彙總函式。

純量涵式

函數名

輸入資料類型

輸出資料類型

描述

樣本

RB_BUILD

INT

ROARING BITMAP

通過INT數組產生一個ROARING BITMAP。

RB_BUILD(ARRAY[1,2,3])

RB_BUILD_RANGE

INT,INT

ROARING BITMAP

通過開始(包含)、結束(不包含)的INT範圍產生一個ROARING BITMAP。

RB_BUILD_RANGE(0, 10000)

RB_BUILD_VARBINARY

VARBINARY

ROARING BITMAP

通過二進位類型產生一個ROARING BITMAP。

RB_BUILD_VARBINARY(RB_TO_VARBINARY (RB_BUILD(ARRAY[1,2,3])))

RB_CARDINALITY

ROARING BITMAP

BIGINT

計算ROARING BITMAP基數。

RB_CARDINALITY(RB_BUILD(ARRAY[1,2,3]))

RB_CONTAINS

ROARING BITMAP, INT

BOOLEAN

判斷ROARING BITMAP是否包含INT。

RB_CONTAINS(RB_BUILD(ARRAY[1,2,3]), 3)

RB_AND

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

兩個ROARING BITMAP求交集。

RB_AND(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[2,3,4]))

RB_OR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

兩個ROARING BITMAP求並集。

RB_OR(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[2,3,4]))

RB_XOR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

兩個ROARING BITMAP求異或。

RB_XOR(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[2,3,4]))

RB_AND_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

And計算。當輸入的某一個參數為Null時,輸出為另一個參數。當某一參數輸入為{}時,輸出為{}

RB_AND_NULL2EMPTY(RB_BUILD(null),RB_BUILD(ARRAY[3,4,5]))

RB_OR_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Or計算。當輸入為Null時,ROARING BITMAP會按空({})來處理。

RB_OR_NULL2EMPTY(RB_BUILD(null),RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

AndNot計算。當輸入為Null時,ROARING BITMAP會按空({})來處理。

RB_ANDNOT_NULL2EMPTY(RB_BUILD(null),RB_BUILD(ARRAY[3,4,5]))

RB_AND_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

And計算並返回基數。

RB_AND_CARDINALITY(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3,4,5]))

RB_AND_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

And計算並返回基數。當輸入為Null時,ROARING BITMAP會按空({})來處理。

RB_AND_NULL2EMPTY_CARDINALITY(RB_BUILD(null),RB_BUILD(ARRAY[3,4,5]))

RB_OR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

Or計算並返回基數。

RB_OR_CARDINALITY(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3,4,5]))

RB_OR_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

Or計算並返回基數。當輸入為Null時,ROARING BITMAP會按空({})來處理。

RB_OR_NULL2EMPTY_CARDINALITY(RB_BUILD(null),RB_BUILD(ARRAY[3,4,5]))

RB_XOR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

Xor計算並返回基數。

RB_XOR_CARDINALITY(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

AndNot計算並返回基數。

RB_ANDNOT_CARDINALITY(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

AndNot計算並返回基數。當輸入為Null時,ROARING BITMAP會按空({})來處理。

RB_ANDNOT_NULL2EMPTY_CARDINALITY(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3,4,5]))

RB_IS_EMPTY

ROARING BITMAP

BOOLEAN

判斷是否為空白的ROARING BITMAP。

RB_IS_EMPTY(RB_BUILD(ARRAY[]))

RB_CLEAR

ROARING BITMAP,BIGINT,BIGINT

ROARING BITMAP

清除指定範圍(不包括 range_end)。

RB_CLEAR(RB_BUILD('{1,2,3}'), 2, 3)

RB_CONTAINS

ROARING BITMAP, ROARING BITMAP

BOOLEAN

判斷第一個ROARING BITMAP是否包含第二個ROARING BITMAP。

RB_CONTAINS(RB_BUILD(ARRAY[1,2,3]),RB_BUILD(ARRAY[3]))

RB_FLIP

ROARING BITMAP, INTEGER, INTEGER

ROARING BITMAP

翻轉ROARING BITMAP中特定的Offset段。

RB_FLIP(RB_BUILD(ARRAY[1,2,3,4,5]), 2, 5)

RB_MINIMUM

ROARING BITMAP

INTEGER

返回ROARING BITMAP中最小的Offset,如果ROARING BITMAP為空白則返回異常。

RB_MINIMUM(RB_BUILD(ARRAY[1,2,3]))

RB_MAXIMUM

ROARING BITMAP

INTEGER

返回ROARING BITMAP中最大的Offset,如果ROARING BITMAP為空白則返回異常。

RB_MAXIMUM(RB_BUILD(ARRAY[1,2,3]))

RB_RANK

ROARING BITMAP,INTEGER

INTEGER

返回ROARING BITMAP中小於等於指定Offset的基數。

RB_RANK(RB_BUILD(ARRAY[1,2,3]),2)

RB_TO_ARRAY

ROARING BITMAP

INTEGER

返回ROARING BITMAP對應整型數組。

RB_TO_ARRAY(RB_BUILD(ARRAY[1,2,3]))

RB_TO_VARBINAR

ROARING BITMAP

VARBINARY

返回ROARING BITMAP對應VARBINARY類型。

RB_TO_VARBINARY(RB_BUILD(ARRAY[1,2,3]))

RB_RANGE_CARDINALITY

ROARING BITMAP, INTEGER, INTEGER

INTEGER

返回從起始位置(包含)到結束位置(不包含)範圍的基數,位置從1開始計數。

重要

僅3.1.10.0及以上版本支援該函數。

RB_RANGE_CARDINALITY(RB_BUILD(ARRAY [1,2,3]),2,3)

RB_SELECT

ROARING BITMAP, INTEGER, INTEGER

ROARING BITMAP

返回從起始位置(包含)到結束位置(不包含)範圍之間Bitmap的Offsets。

重要

僅3.1.10.0及以上版本支援該函數。

RB_SELECT(RB_BUILD(ARRAY [1,3,4,5,7,9]),2, 3)

彙總函式

函數名

輸入資料類型

輸出資料類型

描述

樣本

RB_BUILD_AGG

INTEGER

ROARING BITMAP

將Offset彙總成Bitmap。

RB_CARDINALITY(RB_BUILD_AGG(1))

RB_OR_AGG

ROARING BITMAP

ROARING BITMAP

Or彙總計算。

RB_CARDINALITY(RB_OR_AGG(RB_BUILD(array[1,2,3])))

RB_AND_AGG

ROARING BITMAP

ROARING BITMAP

And彙總計算。

RB_CARDINALITY(RB_AND_AGG(RB_BUILD(ARRAY[1,2,3])))

RB_XOR_AGG

ROARING BITMAP

ROARING BITMAP

Xor彙總計算。

RB_CARDINALITY(RB_XOR_AGG(RB_BUILD(ARRAY[1,2,3])))

RB_OR_CARDINALITY_AGG

ROARING BITMAP

INTEGER

Or彙總計算並返回其基數。

RB_OR_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

RB_AND_CARDINALITY_AGG

ROARING BITMAP

INTEGER

And彙總計算並返回其基數。

RB_AND_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

RB_XOR_CARDINALITY_AGG

ROARING BITMAP

INTEGER

Xor彙總計算並返回其基數。

RB_XOR_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

樣本

如下內容將為您介紹ROARING BITMAP函數完整的使用樣本。

內表

  1. 建立一個含有ROARING BITMAP類型的內表。

    CREATE TABLE `test_rb` (
      `id` INT,
      `rb` ROARINGBITMAP
    );
  2. 向表中寫入資料。

    INSERT INTO test_rb VALUES (1, '[1, 2, 3]');
    INSERT INTO test_rb VALUES (2, '[2, 3, 4, 5, 6]');
  3. 使用ROARING BITMAP純量涵式進行基數計算。

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;

    返回結果如下:

    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  5 |
    |    1 |                  3 |
    +------+--------------------+
  4. 使用ROARING BITMAP彙總函式進行彙總計算。

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;

    返回結果如下:

    +---------------------------+
    | rb_or_cardinality_agg(rb) |
    +---------------------------+
    |                         6 |
    +---------------------------+

外表

  1. 建立一個含有ROARING BITMAP類型的外表。

    CREATE TABLE `test_rb` (
      `id` INT,
      `rb` ROARINGBITMAP
      ) engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAIF****5FsE"",
    "accesskey":"Ccw****iWjv",
    "url":"oss://testBucketName/roaringbitmap/test_for_user/",
    "format":"parquet"
    }';
    說明

    外表相關的參數說明,請參見不帶分區的資料檔案建立OSS外表

  2. 向表中寫入資料。

    重要

    通過INSERT INTO寫入資料時效能較差,如果需要寫入的資料較多,建議在建立外表前使用ETL工具產生parquet格式的資料檔案並上傳到對應的OSS路徑。

    INSERT INTO test_rb SELECT 1, rb_build(ARRAY[1,2,3]);
    INSERT INTO test_rb SELECT 2, rb_build(ARRAY[2,3,4,5]);
  3. 使用ROARING BITMAP純量涵式進行基數計算。

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;

    返回結果如下:

    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  4 |
    |    1 |                  3 |
    +------+--------------------+
  4. 使用ROARING BITMAP彙總函式進行彙總計算。

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;

    返回結果如下:

    +---------------------------+
    | rb_or_cardinality_agg(rb) |
    +---------------------------+
    |                         5 |
    +---------------------------+

圈人情境實踐

實踐過程中,需要將原始標籤錶轉化成ROARING BITMAP標籤表,然後進行ROARING BITMAP計算。流程如下圖所示:1

步驟一:準備原始標籤表

  1. 建立測試用的原始標籤表users_base。

    CREATE TABLE users_base(
       uid INT,
       tag1 STRING, // tag1取值範圍是:x,y,z。
       tag2 STRING, // tag2取值範圍是:a,b。
       tag3 INT // tag3取值範圍是:1~10。
    );
  2. 產生1億行隨機資料,假設產生的資料為使用者標籤資料。

    SUBMIT JOB
    INSERT OVERWRITE users_base
    SELECT CAST(ROW_NUMBER() OVER (ORDER BY c1) AS INT) AS uid, SUBSTRING('xyz', FLOOR(RAND() * 3) + 1, 1) AS tag1, SUBSTRING('ab', FLOOR(RAND() * 2) + 1, 1) AS tag2, CAST(FLOOR(RAND() * 10) + 1 AS INT) as tag3 FROM  
    (
    SELECT A.c1 FROM
    UNNEST(RB_BUILD_RANGE(0, 10000)) AS A(c1)
      JOIN
      (SELECT c1 FROM
    UNNEST(RB_BUILD_RANGE(0, 10000)) AS B(c1)
    ));
  3. 查詢原始標籤表users_base的10行資料。

    SELECT * FROM users_base LIMIT 10;

    返回結果如下:

    +--------+------+------+------+
    | uid    | tag1 | tag2 | tag3 |
    +--------+------+------+------+
    |  74526 | y    | b    |    3 |
    |  75611 | z    | b    |   10 |
    |  80850 | x    | b    |    5 |
    |  81656 | z    | b    |    7 |
    | 163845 | x    | b    |    2 |
    | 167007 | y    | b    |    4 |
    | 170541 | y    | b    |    9 |
    | 213108 | x    | a    |   10 |
    |  66056 | y    | b    |    4 |
    |  67761 | z    | a    |    2 |
    +--------+------+------+------+

步驟二:原始標籤表分組

在設計ROARING BITMAP標籤表時,可以利用分散式運算引擎的並發能力,建議引入一個分組欄位(本例中使用user_group),將uid分組並行計算。分組的大小可以根據叢集ACU總數和實際業務情況進行取捨,遵循以下原則:

  • 一般分組越多計算能力越強,但是分組過多又會導致每個ROARING BITMAP欄位中的元素太少,不能充分利用Bitmap的計算特性。

  • 實踐過程中建議保證每個分組的ROARING BITMAP空間中資料小於1億條。例如,原始的uid空間是100億,可以使用100個分組,每個分組空間為1億。

本樣本使用16個分組,根據uid%16 分組並記錄在user_group欄位,根據uid/16計算位移並記錄在offset欄位,uid = 16 * offset + user_goup。後續使用offset來計算ROARING BITMAP。

該分組方式只是一個例子,實際業務中請根據需求設計分組函數。

  1. 建立添加分組欄位後的標籤表users。

    CREATE TABLE users(
       uid INT,
       tag1 STRING,
       tag2 STRING,
       tag3 INT,
       user_group INT, // 分組欄位
       offset INT //位移欄位
    );
  2. 將users_base表中的資料寫入users表。

    SUBMIT JOB INSERT OVERWRITE users SELECT uid, tag1, tag2, tag3, CAST(uid%16 AS INT), CAST(FLOOR(uid/16) AS INT) FROM users_base;
  3. 查詢users表的10行資料。

    SELECT * FROM users LIMIT 10;

    返回結果如下:

    +---------+------+------+------+------------+--------+
    | uid     | tag1 | tag2 | tag3 | user_group | offset |
    +---------+------+------+------+------------+--------+
    |  377194 | z    | b    |   10 |         10 |  23574 |
    |  309440 | x    | a    |    1 |          0 |  19340 |
    |  601745 | z    | a    |    7 |          1 |  37609 |
    |  753751 | z    | b    |    3 |          7 |  47109 |
    |  988186 | y    | a    |   10 |         10 |  61761 |
    |  883822 | x    | a    |    9 |         14 |  55238 |
    |  325065 | x    | b    |    6 |          9 |  20316 |
    | 1042875 | z    | a    |   10 |         11 |  65179 |
    |  928606 | y    | b    |    5 |         14 |  58037 |
    |  990858 | z    | a    |    8 |         10 |  61928 |
    +---------+------+------+------+------------+--------+

步驟三:構建ROARING BITMAP標籤表

內表

  1. 建立tag1的ROARING BITMAP標籤表tag_tbl_1。

    CREATE TABLE `tag_tbl_1` (
      `tag1` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
    );
  2. 將users表的資料寫入tag_tbl_1表。

    INSERT OVERWRITE tag_tbl_1 SELECT tag1, RB_BUILD_AGG(offset), user_group FROM users GROUP BY tag1, user_group;
  3. 查詢tag_tbl_1標籤表的資料。

    SELECT tag1, user_group, RB_CARDINALITY(rb) FROM tag_tbl_1;

    返回結果如下:

    +------+------------+--------------------+
    | tag1 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | y    |         13 |             563654 |
    | x    |         11 |             565013 |
    | z    |          2 |             564428 |
    | x    |          4 |             564377 |
    ...                                 
    | z    |          5 |             564333 |
    | x    |          8 |             564808 |
    | x    |          0 |             564228 |
    | y    |          3 |             563325 |
    +------+------------+--------------------+
  4. 建立tag2的ROARING BITMAP標籤表tag_tbl_2。

    CREATE TABLE `tag_tbl_2` (
      `tag2` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
    );
  5. 將users表的資料寫入tag_tbl_2表。

    INSERT OVERWRITE tag_tbl_2 SELECT tag2, RB_BUILD_AGG(offset), user_group FROM users GROUP BY tag2, user_group;
  6. 查詢tag_tbl_2標籤表的資料。

    SELECT tag2, user_group, RB_CARDINALITY(rb) FROM tag_tbl_2;

    返回結果如下:

    +------+------------+--------------------+
    | tag2 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | a    |          9 |            3123039 |
    | a    |          5 |            3123973 |
    | a    |         12 |            3122414 |
    | a    |          7 |            3127218 |
    | a    |         15 |            3125403 |
    ...                                  
    | a    |         10 |            3122698 |
    | b    |          4 |            3126091 |
    | b    |          3 |            3124626 |
    | b    |          9 |            3126961 |
    | b    |         14 |            3125351 |
    +------+------------+--------------------+

外表

  1. 建立tag1的ROARING BITMAP標籤表tag_tbl_1。

    CREATE TABLE `tag_tbl_1` (
      `tag1` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
     ) engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAIF****5FsE"",
    "accesskey":"Ccw****iWjv",
    "url":"oss://testBucketName/roaringbitmap/tag_tbl_1/",
    "format":"parquet"
    }';
  2. 將users表的資料寫入tag_tbl_1表。

    INSERT OVERWRITE tag_tbl_1 SELECT tag1, RB_BUILD_AGG(offset), user_group FROM users GROUP BY tag1, user_group;
  3. 查詢tag_tbl_1標籤表的資料。

    SELECT tag1, user_group, RB_CARDINALITY(rb) FROM tag_tbl_1;

    返回結果如下:

    +------+------------+--------------------+
    | tag1 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | z    |          7 |            2082608 |
    | x    |         10 |            2082953 |
    | y    |          7 |            2084730 |
    | x    |         14 |            2084856 |
    ...                                  
    | z    |         15 |            2084535 |
    | z    |          5 |            2083204 |
    | x    |         11 |            2085239 |
    | z    |          1 |            2084879 |
    +------+------------+--------------------+
  4. 建立tag2的ROARING BITMAP標籤表tag_tbl_2。

    CREATE TABLE `tag_tbl_2` (
      `tag2` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
     ) engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAIF****5FsE"",
    "accesskey":"Ccw****iWjv",
    "url":"oss://testBucketName/roaringbitmap/tag_tbl_2/",
    "format":"parquet"
    }';
  5. 將users表的資料寫入tag_tbl_2表。

    INSERT OVERWRITE tag_tbl_2 SELECT tag2, RB_BUILD_AGG(offset), user_group FROM users GROUP BY tag2, user_group;
  6. 查詢tag_tbl_2標籤表的資料。

    SELECT tag2, user_group, RB_CARDINALITY(rb) FROM tag_tbl_2;

    返回結果如下:

    +------+------------+--------------------+
    | tag2 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | b    |         11 |            3121361 |
    | a    |          6 |            3124750 |
    | a    |          1 |            3125433 |
    ...                                    
    | b    |          2 |            3126523 |
    | b    |         12 |            3123452 |
    | a    |          4 |            3126111 |
    | a    |         13 |            3123316 |
    | a    |          2 |            3123477 |
    +------+------------+--------------------+

步驟四:使用ROARING BITMAP標籤表計算分析

情境一:過濾篩選分析

情境一以分析tag1 in (x, y)的使用者在tag2維度柱狀圖為例。

  1. 為了方便理解,先查詢出滿足tag1 in (x, y)條件的使用者。

    SELECT tag2, t1.user_group AS user_group, RB_CARDINALITY(RB_AND(t2.rb, rb1)) AS rb FROM tag_tbl_2 AS t2
    JOIN (
    SELECT user_group, rb AS rb1 FROM tag_tbl_1 WHERE tag1 IN ('x', 'y'))
    AS t1
    ON t1.user_group = t2.user_group;

    返回結果如下:

    +------+------------+---------+
    | tag2 | user_group | rb      |
    +------+------------+---------+
    | b    |          3 | 1041828 |
    | a    |          15| 1039859 |
    | a    |          9 | 1039140 |
    | b    |          1 | 1041524 |
    | a    |          4 | 1041599 |
    | b    |          1 | 1041381 |
    | b    |          10| 1041026 |
    | b    |          6 | 1042289 |
    +------+------------+---------+
  2. 查詢滿足tag1 in (x, y)的使用者在tag2維度柱狀圖。

    SELECT tag2, SUM(cnt) FROM ( 
    SELECT tag2, t1.user_group AS user_group, RB_CARDINALITY(RB_AND(t2.rb, rb1)) AS cnt FROM tag_tbl_2 AS t2
    JOIN (
    SELECT user_group, rb AS rb1 FROM tag_tbl_1 WHERE tag1 IN ('x', 'y'))
    AS t1
    ON t1.user_group = t2.user_group
    ) GROUP BY tag2;

    返回結果如下:

    +------+----------+
    | tag2 | sum(cnt) |
    +------+----------+
    | a    | 33327868 |
    | b    | 33335220 |
    +------+----------+

情境二:ROARING BITMAP標籤表交並差計算

從tag1的ROARING BITMAP標籤表tag_tbl_1讀取滿足tag1 = 'x' or tag1 = 'y'條件的資料,從tag2的ROARING BITMAP標籤表tag_tbl_2讀取滿足tag2 = 'b'條件的資料,對兩個標籤表的資料進行交並差計算,得到同時滿足tag1 = 'x' or tag1 = 'y'tag2 = 'b'的使用者。

SELECT user_group, RB_CARDINALITY(rb) FROM (
    SELECT
      t1.user_group AS user_group,
      RB_AND(rb1, rb2) AS rb
    FROM
      (
        SELECT
          user_group,
          RB_OR_AGG(rb) AS rb1
        FROM
          tag_tbl_1
        WHERE
          tag1 = 'x'
          OR tag1 = 'y'
        GROUP BY
          user_group
      ) AS t1
      JOIN (
        SELECT
          user_group,
          RB_OR_AGG(rb) AS rb2
        FROM
          tag_tbl_2
        WHERE
          tag2 = 'b'
        GROUP BY
          user_group
      ) AS t2 ON t1.user_group = t2.user_group
  GROUP BY user_group);

返回結果如下:

+------------+--------------------+
| user_group | rb_cardinality(rb) |
+------------+--------------------+
|         10 |            2083679 |
|          3 |            2082370 |
|          9 |            2082847 |
|          2 |            2086511 |
...                              
|          1 |            2082291 |
|          4 |            2083290 |
|         14 |            2083581 |
|         15 |            2084110 |
+------------+--------------------+

情境三:原始標籤表和ROARING BITMAP標籤表交並差計算

從tag1的ROARING BITMAP標籤表tag_tbl_1讀取滿足tag1 = 'x' or tag1 = 'y'條件的資料,從原始標籤表users讀取滿足tag2 = 'b'條件的資料,對兩個標籤表的資料進行交並差計算,得到同時滿足tag1 = 'x' or tag1 = 'y'tag2 = 'b'的資料。

SELECT user_group, RB_CARDINALITY(rb) FROM (
    SELECT
      t1.user_group AS user_group,
      RB_AND(rb1, rb2) AS rb
    FROM
      (
        SELECT
          user_group,
          RB_OR_AGG(rb) AS rb1
        FROM
          tag_tbl_1
        WHERE
          tag1 = 'x'
          OR tag1 = 'y'
        GROUP BY
          user_group
      ) AS t1
      JOIN (
        SELECT
          user_group,
          RB_BUILD_AGG(offset) AS rb2
        FROM
          users
        WHERE
          tag2 = 'b'
        GROUP BY
          user_group
      ) AS t2 ON t1.user_group = t2.user_group
  GROUP BY user_group);

返回結果如下:

+------------+--------------------+
| user_group | rb_cardinality(rb) |
+------------+--------------------+
|          3 |            2082370 |
|          1 |            2082291 |
|          0 |            2082383 |
|          4 |            2083290 |
|         11 |            2081662 |
|         13 |            2085280 |
...                              
|         14 |            2083581 |
|         15 |            2084110 |
|          9 |            2082847 |
|          8 |            2084860 |
|          5 |            2083056 |
|          7 |            2083275 |
+------------+--------------------+

情境四:將滿足情境二的ROARING BITMAP匯出到OSS(適用於外表)

  1. 建立用於匯出計算結果的標籤表tag_tbl_3。

    CREATE TABLE `tag_tbl_3` (
      `user_group` INT,
      `rb` ROARINGBITMAP
      )engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAIF****5FsE"",
    "accesskey":"Ccw****iWjv",
    "url":"oss://testBucketName/roaringbitmap/tag_tbl_3/",
    "format":"parquet"
    }';
  2. 將滿足情境二的計算結果匯出到標籤表tag_tbl_3。

    INSERT OVERWRITE tag_tbl_3
        SELECT
          t1.user_group AS user_group,
          RB_AND(rb1, rb2) AS rb
        FROM
          (
            SELECT
              user_group,
              RB_OR_AGG(rb) AS rb1
            FROM
              tag_tbl_1
            WHERE
              tag1 = 'x'
              OR tag1 = 'y'
            GROUP BY
              user_group
          ) AS t1
          JOIN (
            SELECT
              user_group,
              RB_OR_AGG(rb) AS rb2
            FROM
              tag_tbl_2
            WHERE
              tag2 = 'b'
            GROUP BY
              user_group
          ) AS t2 ON t1.user_group = t2.user_group;
    說明

    SQL語句執行結束後,檔案會以parquet格式存放在oss://testBucketName/roaringbitmap/tag_tbl_3/路徑中。

情境五:加速查詢(適用於外表)

將tag1標籤表的資料匯入內表實現加速查詢效果。

  1. 建立一個內表tag_tbl_1_cstore,並將rb欄位定義為VARBINARY類型。

    CREATE TABLE `tag_tbl_1_cstore` (
     `tag1` VARCHAR,
     `rb` VARBINARY,
     `user_group` INT
    );
  2. 將tag1的標籤表的資料從OSS匯入到內表tag_tbl_1_cstore。

    INSERT INTO tag_tbl_1_cstore SELECT tag1, RB_TO_VARBINARY(rb), user_group FROM tag_tbl_1;
  3. 查詢tag_tbl_1_cstore表的資料。

    SELECT tag1, user_group, RB_CARDINALITY(RB_OR_AGG(RB_BUILD_VARBINARY(rb))) FROM tag_tbl_1_cstore GROUP BY tag1, user_group;

    返回結果如下:

    +------+------------+---------------------------------------------------+
    | tag1 | user_group | rb_cardinality(rb_or_agg(rb_build_varbinary(rb))) |
    +------+------------+---------------------------------------------------+
    | y    |          3 |                                           2082919 |
    | x    |          9 |                                           2083085 |
    | x    |          3 |                                           2082140 |
    | y    |         11 |                                           2082268 |
    | z    |          4 |                                           2082451 |
    ...                                                                    
    | z    |          2 |                                           2081560 |
    | y    |          6 |                                           2082194 |
    | z    |          7 |                                           2082608 |
    +------+------------+---------------------------------------------------+