The pg_roaringbitmap plug-in adds a roaringbitmap data type and a full set of bitmap operators and functions to PolarDB. Roaring bitmaps outperform traditional compressed bitmap formats such as WAH, EWAH, and Concise. In certain workloads, they provide indexing speeds almost hundreds of times faster than traditional compressed bitmaps — faster even than uncompressed bitmaps.
Common use cases include user segmentation, ad targeting, funnel analysis, and tag-based filtering at scale.
Install the plug-in
CREATE EXTENSION IF NOT EXISTS roaringbitmap;Verify the installation:
\dxExpected output:
List of installed extensions
Name | Version | Schema | Description
---------------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
roaringbitmap | 0.5 | public | support for Roaring Bitmaps
(2 rows)Quick start
The following walkthrough covers the core usage pattern: create a table, insert bitmap data, run bitmap operations, run aggregate queries, and iterate over results.
1. Create a table with a roaringbitmap column.
CREATE TABLE t1 (id integer, bitmap roaringbitmap);2. Insert bitmap data.
Build a bitmap from an explicit integer array:
INSERT INTO t1 SELECT 1, rb_build(ARRAY[1,2,3,4,5,6,7,8,9,200]);Build a bitmap by aggregating a generated series:
INSERT INTO t1 SELECT 2, rb_build_agg(e) FROM generate_series(1,100) e;3. Run bitmap operations.
All four binary operations are supported: OR, AND, XOR, and ANDNOT.
SELECT roaringbitmap('{1,2,3}') | roaringbitmap('{3,4,5}'); -- OR: {1,2,3,4,5}
SELECT roaringbitmap('{1,2,3}') & roaringbitmap('{3,4,5}'); -- AND: {3}
SELECT roaringbitmap('{1,2,3}') # roaringbitmap('{3,4,5}'); -- XOR: {1,2,4,5}
SELECT roaringbitmap('{1,2,3}') - roaringbitmap('{3,4,5}'); -- ANDNOT:{1,2}4. Run aggregate queries.
SELECT rb_or_agg(bitmap) FROM t1;
SELECT rb_and_agg(bitmap) FROM t1;
SELECT rb_xor_agg(bitmap) FROM t1;
SELECT rb_build_agg(e) FROM generate_series(1,100) e;5. Count elements (cardinality).
SELECT rb_cardinality('{1,2,3}');6. Iterate over elements.
Convert to an integer array:
SELECT rb_to_array(bitmap) FROM t1 WHERE id = 1;Return elements as a set:
SELECT rb_iterate('{1,2,3}'::roaringbitmap);Input and output formats
PolarDB supports only array and bytea input and output formats.
Input formats
array:SELECT roaringbitmap('{1,100,10}'); -- \x3a30000001000000000002001000000001000a006400bytea:SELECT '\x3a30000001000000000002001000000001000a006400'::roaringbitmap; -- \x3a30000001000000000002001000000001000a006400
Output format
The default output format is bytea. Change it with roaringbitmap.output_format:
SET roaringbitmap.output_format = 'bytea';
SELECT '{1}'::roaringbitmap;
-- \x3a3000000100000000000000100000000100
SET roaringbitmap.output_format = 'array';
SELECT '{1}'::roaringbitmap;
-- {1}Operators
| Operator | Input | Output | Description | Example | Result |
|---|---|---|---|---|---|
& | roaringbitmap, roaringbitmap | roaringbitmap | Bitwise AND | roaringbitmap('{1,2,3}') & roaringbitmap('{3,4,5}') | {3} |
| | roaringbitmap, roaringbitmap | roaringbitmap | Bitwise OR | roaringbitmap('{1,2,3}') | roaringbitmap('{3,4,5}') | {1,2,3,4,5} |
| | roaringbitmap, integer | roaringbitmap | Add an element | roaringbitmap('{1,2,3}') | 6 | {1,2,3,6} |
| | integer, roaringbitmap | roaringbitmap | Add an element | 6 | roaringbitmap('{1,2,3}') | {1,2,3,6} |
# | roaringbitmap, roaringbitmap | roaringbitmap | Bitwise XOR | roaringbitmap('{1,2,3}') # roaringbitmap('{3,4,5}') | {1,2,4,5} |
<< | roaringbitmap, bigint | roaringbitmap | Bitwise left shift | roaringbitmap('{1,2,3}') << 2 | {0,1} |
>> | roaringbitmap, bigint | roaringbitmap | Bitwise right shift | roaringbitmap('{1,2,3}') >> 3 | {4,5,6} |
- | roaringbitmap, roaringbitmap | roaringbitmap | ANDNOT (difference) | roaringbitmap('{1,2,3}') - roaringbitmap('{3,4,5}') | {1,2} |
- | roaringbitmap, integer | roaringbitmap | Remove an element | roaringbitmap('{1,2,3}') - 3 | {1,2} |
@> | roaringbitmap, roaringbitmap | bool | Contains | roaringbitmap('{1,2,3}') @> roaringbitmap('{3,4,5}') | f |
@> | roaringbitmap, integer | bool | Contains element | roaringbitmap('{1,2,3,4,5}') @> 3 | t |
<@ | roaringbitmap, roaringbitmap | bool | Is contained by | roaringbitmap('{1,2,3}') <@ roaringbitmap('{3,4,5}') | f |
<@ | integer, roaringbitmap | bool | Is member of | 3 <@ roaringbitmap('{3,4,5}') | t |
&& | roaringbitmap, roaringbitmap | bool | Intersects | roaringbitmap('{1,2,3}') && roaringbitmap('{3,4,5}') | t |
= | roaringbitmap, roaringbitmap | bool | Equal | roaringbitmap('{1,2,3}') = roaringbitmap('{3,4,5}') | f |
<> | roaringbitmap, roaringbitmap | bool | Not equal | roaringbitmap('{1,2,3}') <> roaringbitmap('{3,4,5}') | t |
Functions
Scalar functions
| Function | Input | Output | Description | Example | Result |
|---|---|---|---|---|---|
rb_build | integer[] | roaringbitmap | Build a bitmap from an integer array | rb_build('{1,2,3,4,5}') | {1,2,3,4,5} |
rb_index | roaringbitmap, integer | bigint | Return the 0-based index of the element, or -1 if not found | rb_index('{1,2,3}', 3) | 2 |
rb_cardinality | roaringbitmap | bigint | Return the number of elements | rb_cardinality('{1,2,3,4,5}') | 5 |
rb_and_cardinality | roaringbitmap, roaringbitmap | bigint | Return the cardinality of the AND result | rb_and_cardinality('{1,2,3}', rb_build('{3,4,5}')) | 1 |
rb_or_cardinality | roaringbitmap, roaringbitmap | bigint | Return the cardinality of the OR result | rb_or_cardinality('{1,2,3}', '{3,4,5}') | 5 |
rb_xor_cardinality | roaringbitmap, roaringbitmap | bigint | Return the cardinality of the XOR result | rb_xor_cardinality('{1,2,3}', '{3,4,5}') | 4 |
rb_andnot_cardinality | roaringbitmap, roaringbitmap | bigint | Return the cardinality of the ANDNOT result | rb_andnot_cardinality('{1,2,3}', '{3,4,5}') | 2 |
rb_is_empty | roaringbitmap | boolean | Return true if the bitmap has no elements | rb_is_empty('{1,2,3,4,5}') | f |
rb_fill | roaringbitmap, range_start bigint, range_end bigint | roaringbitmap | Add all integers in [range_start, range_end) | rb_fill('{1,2,3}', 5, 7) | {1,2,3,5,6} |
rb_clear | roaringbitmap, range_start bigint, range_end bigint | roaringbitmap | Remove all integers in [range_start, range_end) | rb_clear('{1,2,3}', 2, 3) | {1,3} |
rb_flip | roaringbitmap, range_start bigint, range_end bigint | roaringbitmap | Negate all bits in [range_start, range_end) | rb_flip('{1,2,3}', 2, 10) | {1,4,5,6,7,8,9} |
rb_range | roaringbitmap, range_start bigint, range_end bigint | roaringbitmap | Return elements in [range_start, range_end) | rb_range('{1,2,3}', 2, 3) | {2} |
rb_range_cardinality | roaringbitmap, range_start bigint, range_end bigint | bigint | Return the count of elements in [range_start, range_end) | rb_range_cardinality('{1,2,3}', 2, 3) | 1 |
rb_min | roaringbitmap | integer | Return the smallest element, or NULL if empty | rb_min('{1,2,3}') | 1 |
rb_max | roaringbitmap | integer | Return the largest element, or NULL if empty | rb_max('{1,2,3}') | 3 |
rb_rank | roaringbitmap, integer | bigint | Return the count of elements less than or equal to the given value | rb_rank('{1,2,3}', 3) | 3 |
rb_jaccard_dist | roaringbitmap, roaringbitmap | double precision | Return the Jaccard distance (Jaccard similarity coefficient) | rb_jaccard_dist('{1,2,3}', '{3,4}') | 0.25 |
rb_select | roaringbitmap, bitset_limit bigint, bitset_offset bigint=0, reverse boolean=false, range_start bigint=0, range_end bigint=4294967296 | roaringbitmap | Return the subset at positions [bitset_offset, bitset_offset+bitset_limit) within [range_start, range_end) | rb_select('{1,2,3,4,5,6,7,8,9}', 5, 2) | {3,4,5,6,7} |
rb_to_array | roaringbitmap | integer[] | Convert to an integer array | rb_to_array(roaringbitmap('{1,2,3}')) | {1,2,3} |
rb_iterate | roaringbitmap | SET of integer | Return each element as a row | SELECT rb_iterate(rb_build('{1,2,3}')) | 1, 2, 3 |
Aggregate functions
| Function | Input | Output | Description | Example | Result |
|---|---|---|---|---|---|
rb_build_agg | integer | roaringbitmap | Build a bitmap from a set of integers | SELECT rb_build_agg(id) FROM (VALUES (1),(2),(3)) t(id) | {1,2,3} |
rb_or_agg | roaringbitmap | roaringbitmap | OR aggregate | SELECT rb_or_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | {1,2,3,4} |
rb_and_agg | roaringbitmap | roaringbitmap | AND aggregate | SELECT rb_and_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | {2,3} |
rb_xor_agg | roaringbitmap | roaringbitmap | XOR aggregate | SELECT rb_xor_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | {1,4} |
rb_or_cardinality_agg | roaringbitmap | bigint | OR aggregate, return cardinality | SELECT rb_or_cardinality_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | 4 |
rb_and_cardinality_agg | roaringbitmap | bigint | AND aggregate, return cardinality | SELECT rb_and_cardinality_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | 2 |
rb_xor_cardinality_agg | roaringbitmap | bigint | XOR aggregate, return cardinality | SELECT rb_xor_cardinality_agg(bitmap) FROM (VALUES (roaringbitmap('{1,2,3}')), (roaringbitmap('{2,3,4}'))) t(bitmap) | 2 |