すべてのプロダクト
Search
ドキュメントセンター

AnalyticDB:Roaring ビットマップ関数

最終更新日:Apr 07, 2025

Roaring ビットマップは効率的に圧縮されたビットマップであり、さまざまなプログラミング言語やビッグデータプラットフォームで、重複排除、タグベースのフィルタリング、時系列データの計算に広く使用されています。このトピックでは、Roaring ビットマップ関数の使用方法について説明します。

サポートされているバージョン

  • V3.1.6.4 以降の AnalyticDB for MySQL クラスタの場合、ROARING BITMAP タイプと Roaring ビットマップ関数は Object Storage Service (OSS) 外部テーブルでサポートされています。

  • V3.2.1.0 以降の AnalyticDB for MySQL クラスタの場合、ROARING BITMAP タイプと Roaring ビットマップ関数は OSS 外部テーブルと AnalyticDB for MySQL 内部テーブルでサポートされています。

説明

表示および更新するには、AnalyticDB for MySQL Data Warehouse Edition クラスタの マイナーバージョン については、AnalyticDB for MySQL コンソール にログインし、構成情報 セクションの クラスター情報 ページ に移動します。 詳細については、「クラスタのマイナーバージョンを更新する」をご参照ください。

制限事項

AnalyticDB for MySQL で Roaring ビットマップ関数を使用する場合は、次の制限事項に注意してください。

  • SELECT 文を実行して ROARING BITMAP タイプのフィールドのデータをクエリすることはできません。UNNEST 演算子を使用して、ROARING BITMAP タイプのフィールドの要素をクエリする必要があります。サンプル文:

    SELECT * FROM unnest(RB_BUILD(ARRAY[1,2,3]));
  • V3.2.1.0 より前のバージョンの AnalyticDB for MySQL クラスタの場合、ROARING BITMAP タイプは OSS 外部テーブルでのみサポートされており、ROARING BITMAP タイプの列を含む AnalyticDB for MySQL 内部テーブルを作成することはできません。AnalyticDB for MySQL 内部テーブルで Roaring ビットマップ関数を使用する場合は、最初に RB_BUILD_VARBINARY 関数を使用して VARBINARY データを ROARING BITMAP タイプに変換します。サンプル文:

    // 内部テーブルを作成します。
    CREATE TABLE test_rb_cstore (id INT, rb VARBINARY);
    
    // Roaring ビットマップ関数を呼び出します。
    SELECT RB_CARDINALITY(RB_BUILD_VARBINARY(rb)) FROM test_rb_cstore;

関数

Roaring ビットマップ関数には、スカラー関数と集約関数が含まれます。

スカラー関数

関数

入力データ型

出力データ型

説明

RB_BUILD

INT

ROARING BITMAP

整数配列から Roaring ビットマップを生成します。

RB_BUILD(ARRAY[1,2,3])

RB_BUILD_RANGE

INT,INT

ROARING BITMAP

開始値 (含む) から終了値 (含まない) までの整数範囲に基づいて Roaring ビットマップを生成します。

RB_BUILD_RANGE(0, 10000)

RB_BUILD_VARBINARY

VARBINARY

ROARING BITMAP

VARBINARY データから Roaring ビットマップを生成します。

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

RB_CARDINALITY

ROARING BITMAP

BIGINT

Roaring ビットマップのカーディナリティを計算します。

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

RB_CONTAINS

ROARING BITMAP, INT

BOOLEAN

Roaring ビットマップに整数が含まれているかどうかを確認します。

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

RB_AND

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

2 つの Roaring ビットマップの積集合を取得します。

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

RB_OR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

2 つの Roaring ビットマップの和集合を取得します。

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

RB_XOR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

2 つの Roaring ビットマップの XOR 値を取得します。

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 の場合、関数は空の波括弧 ({}) を入力として使用します。

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

RB_ANDNOT_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

ANDNOT 演算を実行します。入力値が null の場合、関数は空の波括弧 ({}) を入力として使用します。

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

RB_AND_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して 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

2 つの Roaring ビットマップに対して AND 演算を実行してカーディナリティを計算します。入力値が null の場合、関数は空の波括弧 ({}) を入力として使用します。

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

RB_OR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して 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

2 つの Roaring ビットマップに対して OR 演算を実行してカーディナリティを計算します。入力値が null の場合、関数は空の波括弧 ({}) を入力として使用します。

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

RB_XOR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して XOR 演算を実行してカーディナリティを計算します。

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

RB_ANDNOT_CARDINALITY

ROARING BITMAP, ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して 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

2 つの Roaring ビットマップに対して ANDNOT 演算を実行してカーディナリティを計算します。入力値が null の場合、関数は空の波括弧 ({}) を入力として使用します。

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

RB_IS_EMPTY

ROARING BITMAP

BOOLEAN

Roaring ビットマップが空かどうかを確認します。

RB_IS_EMPTY(RB_BUILD(ARRAY[]))

RB_CLEAR

ROARING BITMAP,BIGINT,BIGINT

ROARING BITMAP

Roaring ビットマップ内の指定された範囲 (範囲の終点は含まない) をクリアします。

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

RB_CONTAINS

ROARING BITMAP, ROARING BITMAP

BOOLEAN

最初の Roaring ビットマップに 2 番目の Roaring ビットマップが含まれているかどうかを確認します。

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

RB_FLIP

ROARING BITMAP, INTEGER, INTEGER

ROARING BITMAP

Roaring ビットマップ内の指定されたオフセットを反転します。

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

RB_MINIMUM

ROARING BITMAP

INTEGER

Roaring ビットマップ内の最小オフセットを返します。Roaring ビットマップが空の場合、エラーが返されます。

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

RB_MAXIMUM

ROARING BITMAP

INTEGER

Roaring ビットマップ内の最大オフセットを返します。Roaring ビットマップが空の場合、エラーが返されます。

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

RB_RANK

ROARING BITMAP,INTEGER

INTEGER

Roaring ビットマップ内の特定のオフセット以下の要素の数を返します。

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

RB_TO_ARRAY

ROARING BITMAP

INTEGER

Roaring ビットマップの作成元の整数配列を返します。

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

RB_TO_VARBINARY

ROARING BITMAP

VARBINARY

Roaring ビットマップの作成元の VARBINARY 配列を返します。

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

RB_RANGE_CARDINALITY

ROARING BITMAP, INTEGER, INTEGER

INTEGER

開始位置 (含む) から終了位置(含まない) までの範囲のカーディナリティを返します。開始位置は 1 です。

重要

この関数は、AnalyticDB for MySQL V3.1.10.0 以降でのみサポートされています。

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

RB_SELECT

ROARING BITMAP, INTEGER, INTEGER

ROARING BITMAP

開始位置 (含む) から終了位置 (含まない) までの範囲の Roaring ビットマップのオフセットを返します。

重要

この関数は、AnalyticDB for MySQL V3.1.10.0 以降でのみサポートされています。

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

集約関数

関数

入力データ型

出力データ型

説明

RB_BUILD_AGG

INTEGER

ROARING BITMAP

オフセットのグループから Roaring ビットマップを作成します。

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

2 つの Roaring ビットマップに対して OR 集約演算を実行してカーディナリティを計算します。

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

RB_AND_CARDINALITY_AGG

ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して AND 集約演算を実行してカーディナリティを計算します。

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

RB_XOR_CARDINALITY_AGG

ROARING BITMAP

INTEGER

2 つの Roaring ビットマップに対して XOR 集約演算を実行してカーディナリティを計算します。

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

次の例では、内部テーブルと外部テーブルで Roaring ビットマップ関数を使用する方法について説明します。

内部テーブル

  1. Roaring ビットマップをサポートする内部テーブルを作成します。

    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 ビットマップのカーディナリティを取得します。

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;

    サンプル結果:

    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  5 |
    |    1 |                  3 |
    +------+--------------------+
  4. Roaring ビットマップに対して集約を実行します。

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;

    サンプル結果:

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

外部テーブル

  1. Roaring ビットマップをサポートする外部テーブルを作成します。

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

    外部テーブルのパラメータについては、「外部テーブルを使用して Data Warehouse Edition にデータをインポートする」トピックの「パーティション化されていないオブジェクトの 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 ビットマップのカーディナリティを取得します。

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;

    サンプル結果:

    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  4 |
    |    1 |                  3 |
    +------+--------------------+
  4. Roaring ビットマップに対して集約を実行します。

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;

    サンプル結果:

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

例: ターゲット顧客の特定

この例では、タグテーブルを Roaring ビットマップテーブルに変換し、次の図に示すように、Roaring ビットマップに基づいて分析を実行します。1

手順 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 |
    +--------+------+------+------+

手順 2: タグテーブルをグループ化する

AnalyticDB for MySQL の分散コンピューティングエンジンの並列処理機能を活用するには、uid でデータをグループ化できる列を追加することをお勧めします。この例では、グループ化のために user-group という名前の列が作成されます。グループサイズは、クラスタ内の AnalyticDB Compute Unit (ACU) の総数によって異なります。

  • 多数のグループは計算効率が高くなります。ただし、各 Roaring ビットマップに含まれる要素の数が少ない場合、システムは Roaring ビットマップの利点を十分に活用できません。

  • 実際のシナリオでは、各グループ内のレコード数を 1 億未満に制限することをお勧めします。たとえば、uid 値の総数が 100 億の場合、それぞれ 1 億行のデータを持つ 100 個のグループを作成できます。

この例では、uid 値は 16 個のグループに分類されます。user_group 列には、uid 値を 16 で割った余りが格納されます。offset 列には、除算の商が格納されます。offset 列は、Roaring ビットマップの計算に使用されます。uid は、次の式に基づいて計算できます。uid = 16 × offset + user_group

このグループ化方法はあくまでも参考です。ビジネス要件に基づいてグループ化を設計する必要があります。

  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 |
    +---------+------+------+------+------------+--------+

手順 3: Roaring ビットマップを作成する

内部テーブル

  1. タグ 1 用の tag_tbl_1 という名前の Roaring ビットマップテーブルを作成します。

    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. タグ 2 用の tag_tbl_2 という名前の Roaring ビットマップテーブルを作成します。

    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. タグ 1 用の tag_tbl_1 という名前の Roaring ビットマップテーブルを作成します。

    CREATE TABLE `tag_tbl_1` (
      `tag1` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
     ) engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAI****************"",
    "accesskey":"yourAccessKeySecret",
    "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. タグ 2 用の tag_tbl_2 という名前の Roaring ビットマップテーブルを作成します。

    CREATE TABLE `tag_tbl_2` (
      `tag2` STRING,
      `rb` ROARINGBITMAP,
      `user_group` INT
     ) engine = 'oss'
    TABLE_PROPERTIES = '{
    "endpoint":"oss-cn-zhangjiakou.aliyuncs.com",
    "accessid":"LTAI****************"",
    "accesskey":"yourAccessKeySecret",
    "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 |
    +------+------------+--------------------+

手順 4: Roaring ビットマップに基づいて分析を実行する

シナリオ 1: フィルタリング分析

この例では、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 |
    +------+----------+

シナリオ 2: Roaring ビットマップの積集合、和集合、XOR を計算する

tag1 = 'x' or tag1 = 'y' を満たす tag_tbl_1 テーブルのデータと、tag2 = 'b' を満たす tag_tbl_2 テーブルのデータを取得し、両方の条件を満たすデータを取得します。

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 |
+------------+--------------------+

シナリオ 3: Roaring ビットマップと元のタグテーブルの積集合、和集合、XOR を計算する

tag1 = 'x' or tag1 = 'y' を満たす tag_tbl_1 テーブルのデータと、tag2 = 'b' を満たす users テーブルのデータを取得し、両方の条件を満たすデータを取得します。

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 |
+------------+--------------------+

シナリオ 4: OSS 外部テーブルを使用して結果を 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":"LTAI****************"",
    "accesskey":"yourAccessKeySecret",
    "url":"oss://testBucketName/roaringbitmap/tag_tbl_3/",
    "format":"parquet"
    }';
  2. シナリオ 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;
    説明

    文が実行されると、ファイルは oss://testBucketName/roaringbitmap/tag_tbl_3/ ディレクトリに Parquet ファイルとして保存されます。

シナリオ 5: 外部テーブルのクエリを高速化する

tag_tbl_1 テーブルから内部テーブルにデータをインポートして、クエリのパフォーマンスを向上させることができます。

  1. tag_tbl_1_cstore という名前の内部テーブルを作成し、rb フィールドのデータ型を VARBINARY に設定します。

    CREATE TABLE `tag_tbl_1_cstore` (
     `tag1` VARCHAR,
     `rb` VARBINARY,
     `user_group` INT
    );
  2. tag_tbl_1 テーブルのデータを 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 |
    +------+------------+---------------------------------------------------+