Roaring Bitmap は、積集合、和集合、差集合、重複排除などの集合演算に最適化された圧縮ビットマップです。従来のビットマップよりも大幅に少ないメモリ使用量で、より高速なパフォーマンスを実現するため、ユーザープロファイリング、パーソナライズドレコメンデーション、精密マーケティングなどのワークロードに適しています。
前提条件
開始する前に、以下を確認してください:
V6.3.8.9 以降を実行している AnalyticDB for PostgreSQL インスタンス。インスタンスのマイナーバージョンを確認するには、「マイナーエンジンバージョンの表示」をご参照ください。
インスタンスに
roaringbitmap拡張機能がインストールされていること。詳細については、「拡張機能のインストール、更新、アンインストール」をご参照ください。
仕組み
Roaring Bitmap は、各 32 ビット整数を上位 16 ビット (チャンクキーとして格納) と下位 16 ビット (コンテナに格納) に分割してエンコードします。各チャンクは最大 2^16 個の整数を保持し、チャンクは動的に拡張される配列にソートされるため、二分探索によって任意の値が迅速に特定できます。
コンテナは、データ特性に基づいて自動的に選択されます:
| コンテナタイプ | 使用される条件 | 容量 |
|---|---|---|
| 配列コンテナ | スパースで非連続な値 | 4,096 未満の整数 |
| ビットマップコンテナ | デンスで連続した整数 | 4,096 以上の整数 |
| コンテナの実行 | 連続した昇順の値が長く続く場合 | 配列コンテナとビットマップコンテナの両方より小さい |
この適応型ストレージレイアウトにより、高い圧縮率が維持され、コンテナタイプ間で直接 AND、OR、XOR 演算が可能になります。基盤となるデータ構造の詳細については、「CRoaring リポジトリ」をご参照ください。
利用手順
以下の手順では、拡張機能のインストール、テーブルの作成、データの挿入、ビットマップクエリの実行までの一連のワークフローを説明します。
1. 拡張機能のインストール
インスタンスの[拡張]ページで、roaringbitmap 拡張をインストールします。
2. roaringbitmap 列を持つテーブルの作成
CREATE TABLE t1 (id integer, bitmap roaringbitmap);3. roaringbitmap データの挿入
RB_BUILD を使用して明示的な整数配列からビットマップを構築するか、RB_BUILD_AGG を使用して一連の整数を集計してビットマップを構築します。
-- 明示的な配列からビットマップを構築 (位置 1-9 と 200 にビットをセット)
INSERT INTO t1 SELECT 1, RB_BUILD(ARRAY[1,2,3,4,5,6,7,8,9,200]);
-- 生成された 1-100 の整数シリーズを集計してビットマップを構築
INSERT INTO t1 SELECT 2, RB_BUILD_AGG(e) FROM GENERATE_SERIES(1,100) e;4. ビット位置のクエリ
RB_ITERATE は、ビットが 1 に設定されている各整数位置を返します。
SELECT RB_ITERATE(bitmap) FROM t1 WHERE id = 1;5. ビットマップ集合演算の実行
関数構文または同等の演算子構文を使用します。どちらも同じ結果を生成します。
-- OR: 2 つのビットマップの和集合 (関数構文)
SELECT RB_OR(a.bitmap, b.bitmap)
FROM (SELECT bitmap FROM t1 WHERE id = 1) AS a,
(SELECT bitmap FROM t1 WHERE id = 2) AS b;
-- OR: 2 つのビットマップの和集合 (演算子構文)
SELECT a.bitmap | b.bitmap
FROM (SELECT bitmap FROM t1 WHERE id = 1) AS a,
(SELECT bitmap FROM t1 WHERE id = 2) AS b;6. 行をまたがるビットマップの集計
SELECT RB_OR_AGG(bitmap) FROM t1; -- すべてのビットマップの和集合
SELECT RB_AND_AGG(bitmap) FROM t1; -- すべてのビットマップの積集合
SELECT RB_XOR_AGG(bitmap) FROM t1; -- すべてのビットマップの対称差7. セットされたビットのカウント (カーディナリティ)
SELECT RB_CARDINALITY(bitmap) FROM t1;ビットマップ計算関数
| 関数 | 入力 | 出力 | 説明 | 例 | 結果 |
|---|---|---|---|---|---|
| rb_build | integer[] | roaringbitmap | 整数配列から roaring bitmap を作成します。 | rb_build('{1,2,3,4,5}') | {1,2,3,4,5} |
| rb_and | roaringbitmap, roaringbitmap | roaringbitmap | AND 演算を実行します。 | rb_and(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {3} |
| rb_or | roaringbitmap, roaringbitmap | roaringbitmap | OR 演算を実行します。 | rb_or(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2,3,4,5} |
| rb_xor | roaringbitmap, roaringbitmap | roaringbitmap | XOR 演算を実行します。 | rb_xor(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2,4,5} |
| rb_andnot | roaringbitmap, roaringbitmap | roaringbitmap | ANDNOT 演算を実行します。 | rb_andnot(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2} |
| rb_cardinality | roaringbitmap | integer | セットされたビットの数を返します。 | rb_cardinality(rb_build('{1,2,3,4,5}')) | 5 |
| rb_and_cardinality | roaringbitmap, roaringbitmap | integer | AND 演算結果のカーディナリティを返します。 | rb_and_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 1 |
| rb_or_cardinality | roaringbitmap, roaringbitmap | integer | OR 演算結果のカーディナリティを返します。 | rb_or_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 5 |
| rb_xor_cardinality | roaringbitmap, roaringbitmap | integer | XOR 演算結果のカーディナリティを返します。 | rb_xor_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 4 |
| rb_andnot_cardinality | roaringbitmap, roaringbitmap | integer | ANDNOT 演算結果のカーディナリティを返します。 | rb_andnot_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 2 |
| rb_is_empty | roaringbitmap | boolean | roaring bitmap が空かどうかをチェックします。 | rb_is_empty(rb_build('{1,2,3,4,5}')) | false |
| rb_equals | roaringbitmap, roaringbitmap | boolean | 2 つの roaring bitmap が等しいかどうかをチェックします。 | rb_equals(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | false |
| rb_intersect | roaringbitmap, roaringbitmap | boolean | 2 つの roaring bitmap が交差するかどうかをチェックします。 | rb_intersect(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | true |
| rb_remove | roaringbitmap, integer | roaringbitmap | 特定のオフセットを削除します。 | rb_remove(rb_build('{1,2,3}'), 3) | {1,2} |
| rb_remove | roaringbitmap, integer, integer | roaringbitmap | 特定のオフセット範囲を削除します。 | rb_remove(rb_build('{1,2,3,4,6,7,8}'), 6, 8) | {1,2,3,4} |
| rb_flip | roaringbitmap, integer | roaringbitmap | 特定のオフセットのビットを反転させます。 | rb_flip(rb_build('{1,2,3}'), 3) | {1,2} |
| rb_flip | roaringbitmap, integer, integer | roaringbitmap | 特定のオフセット範囲のすべてのビットを反転させます。 | rb_flip(rb_build('{1,2,3}'), 2, 3) | |
| rb_minimum | roaringbitmap | integer | セットされた最小のオフセットを返します。ビットマップが空の場合は -1 を返します。 | rb_minimum(rb_build('{1,2,3}')) | 1 |
| rb_maximum | roaringbitmap | integer | セットされた最大のオフセットを返します。ビットマップが空の場合は 0 を返します。 | rb_maximum(rb_build('{1,2,3}')) | 3 |
| rb_rank | roaringbitmap, integer | integer | 指定された値以下のセットされたオフセットの数を返します。 | rb_rank(rb_build('{1,2,3}'), 3) | 3 |
| rb_iterate | roaringbitmap | setof integer | セットされた各オフセットを行として返します。 | rb_iterate(rb_build('{1,2,3}')) | 1、2、3 (1 行に 1 つ) |
| rb_iterate_decrement | roaringbitmap | integer[] | セットされたすべてのオフセットを降順の配列として返します。 | rb_iterate_decrement(rb_build('{1,2,3,4}')) | {4,3,2,1} |
| rb_contains | roaringbitmap, integer | boolean | ビットマップが特定のオフセットを含むかどうかをチェックします。 | rb_contains(rb_build('{1,2,3}'), 1) | true |
| rb_contains | roaringbitmap, integer, integer | boolean | ビットマップが特定のオフセット範囲を含むかどうかをチェックします。 | rb_contains(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | |
| rb_contains | roaringbitmap, roaringbitmap | boolean | あるビットマップが別のビットマップを含むかどうかをチェックします。 | rb_contains(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | false |
| rb_becontained | integer, roaringbitmap | boolean | 特定のオフセットがビットマップに含まれるかどうかをチェックします。 | rb_becontained(1, rb_build('{1,2,3}')) | true |
| rb_becontained | roaringbitmap, roaringbitmap | boolean | あるビットマップが別のビットマップに含まれるかどうかをチェックします。 | rb_becontained(rb_build('{1}'), rb_build('{1,2,3}')) | true |
| rb_add | roaringbitmap, integer | roaringbitmap | 特定のオフセットを追加します。 | rb_add(rb_build('{1,2,3,4}'), 5) | {1,2,3,4,5} |
| rb_add | roaringbitmap, integer, integer | roaringbitmap | 特定のオフセット範囲を追加します。 | rb_add(rb_build('{1,2,3,4}'), 6, 8) | {1,2,3,4,6,7,8} |
| rb_add_2 | integer, roaringbitmap | roaringbitmap | ビットマップに特定のオフセットを追加します (引数の順序が逆)。 | rb_add_2(5, rb_build('{1,2,3,4}')) | {1,2,3,4,5} |
| rb_jaccard_index | roaringbitmap, roaringbitmap | float8 | 2 つのビットマップ間のジャカード類似係数を計算します。 | rb_jaccard_index(rb_build('{1,2,3,4}'), rb_build('{1,2}')) | 0.5 |
| rb_to_array | roaringbitmap | integer[] | roaring bitmap を整数配列に変換します。 | rb_to_array(rb_build('{1,2,3,4}')) | {1,2,3,4} |
ビットマップ集計関数
| 関数 | 入力 | 出力 | 説明 | 例 | 結果 |
|---|---|---|---|---|---|
| rb_build_agg | integer | roaringbitmap | 一連のオフセットを集計して roaring bitmap にします。 | rb_build_agg(1) | {1} |
| rb_or_agg | roaringbitmap | roaringbitmap | 行をまたいで OR 集計操作を実行します。 | rb_or_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_and_agg | roaringbitmap | roaringbitmap | 行をまたいで AND 集計操作を実行します。 | rb_and_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_xor_agg | roaringbitmap | roaringbitmap | 行をまたいで XOR 集計操作を実行します。 | rb_xor_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_or_cardinality_agg | roaringbitmap | integer | OR 集計結果のカーディナリティを返します。 | rb_or_cardinality_agg(rb_build('{1,2,3}')) | 3 |
| rb_and_cardinality_agg | roaringbitmap | integer | AND 集計結果のカーディナリティを返します。 | rb_and_cardinality_agg(rb_build('{1,2,3}')) | 3 |
| rb_xor_cardinality_agg | roaringbitmap | integer | XOR 集計結果のカーディナリティを返します。 | rb_xor_cardinality_agg(rb_build('{1,2,3}')) | 3 |
演算子
すべての演算子には、前のセクションに記載されている同等の関数形式があります。演算子構文は、インライン SQL 式でより簡潔です。
| オペレーター | 左 | 右 | 出力 | 説明 | 例 |
|---|---|---|---|---|---|
& | roaringbitmap | roaringbitmap | roaringbitmap | AND 演算。 | rb_build('{1,2,3}') & rb_build('{1,2,4}') |
| | roaringbitmap | roaringbitmap | roaringbitmap | OR 演算。 | rb_build('{1,2}') | rb_build('{1,3}') |
# | roaringbitmap | roaringbitmap | roaringbitmap | XOR 演算。 | rb_build('{1,2}') # rb_build('{1,3}') |
~ | roaringbitmap | roaringbitmap | roaringbitmap | ANDNOT 演算。 | rb_build('{2,3}') ~ rb_build('{2,4}') |
+ | roaringbitmap | integer | roaringbitmap | 特定のオフセットを追加します。 | rb_build('{2,3}') + 1 |
- | roaringbitmap | integer | roaringbitmap | 特定のオフセットを削除します。 | rb_build('{1,2,3}') - 1 |
= | roaringbitmap | roaringbitmap | boolean | 2 つのビットマップが等しいかどうかをチェックします。 | rb_build('{2,3}') = rb_build('{2,3}') |
<> | roaringbitmap | roaringbitmap | boolean | 2 つのビットマップが異なるかどうかをチェックします。 | rb_build('{2,3}') <> rb_build('{1,2,3}') |
&& | roaringbitmap | roaringbitmap | boolean | 2 つのビットマップが交差するかどうかをチェックします。 | rb_build('{2,3}') && rb_build('{3,4}') |
@> | roaringbitmap | roaringbitmap | boolean | 左のビットマップが右のビットマップを含むかどうかをチェックします。 | rb_build('{2,3}') @> rb_build('{2}') |
@> | roaringbitmap | integer | boolean | ビットマップが特定のオフセットを含むかどうかをチェックします。 | rb_build('{2,3}') @> 2 |
<@ | roaringbitmap | roaringbitmap | boolean | 左のビットマップが右のビットマップに含まれるかどうかをチェックします。 | rb_build('{2,3}') <@ rb_build('{1,2,3}') |
<@ | integer | roaringbitmap | boolean | オフセットがビットマップに含まれるかどうかをチェックします。 | 2 <@ rb_build('{2,3}') |