Skip to content

About

RoaringBitmap extension for PostgreSQL

Topics

Resources

Stars

288 stars

Watchers

16 watching

Forks

Latest commit

 

History

209 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pg_roaringbitmap

RoaringBitmap extension for PostgreSQL.

This is originally based on https://github.com/zeromax007/gpdb-roaringbitmap.

Introduction

Roaring bitmaps are compressed bitmaps which tend to outperform conventional compressed bitmaps such as WAH, EWAH or Concise. In some instances, roaring bitmaps can be hundreds of times faster and they often offer significantly better compression. They can even be faster than uncompressed bitmaps. More information at https://github.com/RoaringBitmap/CRoaring.

Build

Requirements

Note: The regression testing before the version release only covers PostgreSQL 13 and above.

Build

su - postgres
make
sudo make install
psql -c "create extension roaringbitmap"

Note: You can use make -f Makefile_native instead of make to let the compiler use SIMD instructions if your CPU supports them. In some scenarios, it may double the performance. But if you use the pg_roaringbitmap binary built with SIMD support on a machine without SIMD support, you could get a SIGILL crash.

Test

make installcheck

Usage

roaringbitmap

about roaringbitmap data type

Logically, you could think of the roaringbitmap data type as bit(4294967296), and it should be noted that the integers added to bitmaps are considered to be unsigned. Within bitmaps, numbers are ordered according to uint32. We order the numbers like 0, 1, ..., 2147483647, -2147483648, -2147483647,..., -1. But we use bigint to reference the range of these integers, that is [0 4294967296).

The comparison operators <, <=, =, >=, > compare bitmaps as ascending element sequences in exactly that uint32 order (lexicographically: the first differing element decides, and a shorter sequence is smaller). ORDER BY, DISTINCT, GROUP BY and rb_min() / rb_max() use the same order, so roaringbitmap('{0,-2147483648}') > roaringbitmap('{0,2}') is true while roaringbitmap('{0,-2147483648}') > roaringbitmap('{0,-1}') is false.

input and ouput

Two kinds of input/output syntax are supported: 'array' and 'bytea'. The default output format is 'bytea'.

postgres=# select roaringbitmap('{1,100,10}');
                 roaringbitmap
------------------------------------------------
 \x3a30000001000000000002001000000001000a006400
(1 row)

or

postgres=# select '\x3a30000001000000000002001000000001000a006400'::roaringbitmap;
                 roaringbitmap
------------------------------------------------
 \x3a30000001000000000002001000000001000a006400
(1 row)

The output format can changed with roaringbitmap.output_format

postgres=# set roaringbitmap.output_format='bytea';
SET
postgres=# select '{1}'::roaringbitmap;
             roaringbitmap
----------------------------------------
 \x3a3000000100000000000000100000000100
(1 row)

postgres=# set roaringbitmap.output_format='array';
SET
postgres=# select '{1}'::roaringbitmap;
 roaringbitmap
---------------
 {1}
(1 row)

sample of usage

Use bitmap as type of column

CREATE TABLE t1 (id integer, bitmap roaringbitmap);

Build bitmap from integers

INSERT INTO t1 SELECT 1,rb_build(ARRAY[1,2,3,4,5,6,7,8,9,200]);

INSERT INTO t1 SELECT 2,rb_build_agg(e) FROM generate_series(1,100) e;

Bitmap Calculation (OR, AND, XOR, ANDNOT)

SELECT roaringbitmap('{1,2,3}') | roaringbitmap('{3,4,5}');
SELECT roaringbitmap('{1,2,3}') & roaringbitmap('{3,4,5}');
SELECT roaringbitmap('{1,2,3}') # roaringbitmap('{3,4,5}');
SELECT roaringbitmap('{1,2,3}') - roaringbitmap('{3,4,5}');

Bitmap Aggregate (OR, AND, XOR, BUILD)

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;

Calculate cardinality

SELECT rb_cardinality('{1,2,3}');

Convert bitmap to integer array

SELECT rb_to_array(bitmap) FROM t1 WHERE id = 1;

Convert bitmap to SET of integers

SELECT unnest(rb_to_array('{1,2,3}'::roaringbitmap));

or

SELECT rb_iterate('{1,2,3}'::roaringbitmap);

Operator List

Operator Input Output Desc 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 element to roaringbitmap roaringbitmap('{1,2,3}') | 6 {1,2,3,6}
| integer,roaringbitmap roaringbitmap add element to roaringbitmap 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 shift left roaringbitmap('{1,2,3}') << 2 {0,1}
>> roaringbitmap,bigint roaringbitmap bitwise shift right roaringbitmap('{1,2,3}') >> 3 {4,5,6}
- roaringbitmap,roaringbitmap roaringbitmap difference(bitwise ANDNOT) roaringbitmap('{1,2,3}') - roaringbitmap('{3,4,5}') {1,2}
- roaringbitmap,integer roaringbitmap remove element from roaringbitmap roaringbitmap('{1,2,3}') - 3 {1,2}
@> roaringbitmap,roaringbitmap bool contains roaringbitmap('{1,2,3}') @> roaringbitmap('{3,4,5}') f
@> roaringbitmap,integer bool contains 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 contained by 3 <@ roaringbitmap('{3,4,5}') t
&& roaringbitmap,roaringbitmap bool overlap (have elements in common) 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 less than (uint32 element order) roaringbitmap('{1,2}') < roaringbitmap('{2}') t
<= roaringbitmap,roaringbitmap bool less than or equal to (uint32 element order) roaringbitmap('{1,2}') <= roaringbitmap('{1,3}') t
>= roaringbitmap,roaringbitmap bool greater than or equal to (uint32 element order) roaringbitmap('{-2147483648}') >= roaringbitmap('{2147483647}') t
> roaringbitmap,roaringbitmap bool greater than (uint32 element order) roaringbitmap('{0,-2147483648}') > roaringbitmap('{0,2}') t
<> roaringbitmap,roaringbitmap bool not equal roaringbitmap('{1,2,3}') <> roaringbitmap('{3,4,5}') t

Function List

Function Input Output Desc Example Result
rb_build integer[] roaringbitmap Create roaringbitmap from 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 in this roaringbitmap, or -1 if not present rb_index('{1,2,3}',3) 2
rb_cardinality roaringbitmap bigint Return cardinality of the roaringbitmap rb_cardinality('{1,2,3,4,5}') 5
rb_and_cardinality roaringbitmap,roaringbitmap bigint Return cardinality of the AND of two roaringbitmaps rb_and_cardinality('{1,2,3}','{3,4,5}') 1
rb_or_cardinality roaringbitmap,roaringbitmap bigint Return cardinality of the OR of two roaringbitmaps rb_or_cardinality('{1,2,3}','{3,4,5}') 5
rb_xor_cardinality roaringbitmap,roaringbitmap bigint Return cardinality of the XOR of two roaringbitmaps rb_xor_cardinality('{1,2,3}','{3,4,5}') 4
rb_andnot_cardinality roaringbitmap,roaringbitmap bigint Return cardinality of the ANDNOT of two roaringbitmaps rb_andnot_cardinality('{1,2,3}','{3,4,5}') 2
rb_is_empty roaringbitmap boolean Check if roaringbitmap is empty. rb_is_empty('{1,2,3,4,5}') f
rb_fill roaringbitmap,range_start bigint,range_end bigint roaringbitmap Fill the specified range (not include the range_end) rb_fill('{1,2,3}',5,7) {1,2,3,5,6}
rb_clear roaringbitmap,range_start bigint,range_end bigint roaringbitmap Clear the specified range (not include the range_end) rb_clear('{1,2,3}',2,3) {1,3}
rb_flip roaringbitmap,range_start bigint,range_end bigint roaringbitmap Negative the specified range (not include the 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 new set with specified range (not include the range_end) rb_range('{1,2,3}',2,3) {2}
rb_range_cardinality roaringbitmap,range_start bigint,range_end bigint bigint Return the cardinality of specified range (not include the range_end) rb_range_cardinality('{1,2,3}',2,3) 1
rb_min roaringbitmap integer Return the smallest offset in roaringbitmap. Return NULL if the bitmap is empty rb_min('{1,2,3}') 1
rb_max roaringbitmap integer Return the greatest offset in roaringbitmap. Return NULL if the bitmap is empty rb_max('{1,2,3}') 3
rb_rank roaringbitmap,integer bigint Return the number of elements that are smaller or equal to the specified offset rb_rank('{1,2,3}',3) 3
rb_jaccard_dist(Deprecated) roaringbitmap,roaringbitmap double precision Deprecated, use rb_jaccard_index instead. The name is misleading: this function returns the Jaccard similarity coefficient, not the distance, and the name may be removed in a future release rb_jaccard_dist('{1,2,3}','{3,4}') 0.25
rb_jaccard_index roaringbitmap,roaringbitmap double precision Return the Jaccard similarity coefficient of two bitmaps, |A ∩ B| / |A ∪ B|. Return 1 if both bitmaps are empty rb_jaccard_index('{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 subset [bitset_offset,bitset_offset+bitset_limit) of bitmap between range [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 roaringbitmap to integer array rb_to_array(roaringbitmap('{1,2,3}')) {1,2,3}
rb_iterate roaringbitmap SET of integer Return set of integer from a roaringbitmap data. rb_iterate(roaringbitmap('{1,2,3}'))
1
2
3
rb_runoptimize roaringbitmap roaringbitmap Return space-optimized bitmap rb_runoptimize(roaringbitmap('{1,2,3,4,5}')) {1,2,3,4,5} (but the underlying bitmap is smaller)
rb_group_elements_by_source roaringbitmap[] TABLE(sources integer[], members roaringbitmap) Group the elements found across an array of bitmaps by the combination of source bitmaps (1-based indices into the input array) that contain them
select sources, rb_to_array(members)
    from rb_group_elements_by_source(ARRAY[
        rb_build('{1,2,3,4,5}'),
        rb_build('{1,2,3,6,7}')
    ])
sources | rb_to_array
--------+------------
{1,2}   | {1,2,3}
{1}     | {4,5}
{2}     | {6,7}

Aggregation List

Function Input Output Desc Example Result
rb_build_agg integer roaringbitmap Build a roaringbitmap from a integer set
select rb_build_agg(id)
    from (values (1),(2),(3)) t(id)
{1,2,3}
rb_or_agg roaringbitmap roaringbitmap AND Aggregate calculations from a roaringbitmap set
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 calculations from a roaringbitmap set
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 calculations from a roaringbitmap set
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 calculations from a roaringbitmap set, 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 calculations from a roaringbitmap set, 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 calculations from a roaringbitmap set, return cardinality
select rb_xor_cardinality_agg(bitmap)
    from (values (roaringbitmap('{1,2,3}')),
                 (roaringbitmap('{2,3,4}'))
          ) t(bitmap)
2

Index Support

roaringbitmap supports btree, hash and GIN indexes, and the operators they support are listed below.

Index Type Operators Use Case
btree <, <=, =, >=, > equality, range and ORDER BY on low-cardinality bitmaps; supports UNIQUE
hash = equality only (no range or ORDER BY), but works on bitmaps of any size
gin &&, @>, <@, =, @> (int4) set containment and overlap; the only option for high-cardinality bitmaps

Sample:

CREATE INDEX ... USING btree(col);
CREATE INDEX ... USING hash(col);
CREATE INDEX ... USING gin(col);

Notes

  1. btree limits the size of an index key. Bitmap values are stored in the index as is and are never TOASTed, so CREATE INDEX ... USING btree (col) fails once a bitmap exceeds roughly 2.7 KB: ERROR: index row size 2832 exceeds btree version 4 maximum 2704.

  2. GIN index size depends on the total number of elements, not on the number of rows. GIN keys are element-level int4 values, so dense bitmaps bloat the index, which can grow far larger than the table it indexes.

  3. High-cardinality bitmaps overflow to TOAST, which hides the real cost of a sequential scan. The planner computes the Seq Scan cost from the heap's own page count and ignores the TOAST pages that must be read to detoast every value, so the estimate is far too low and a much faster GIN index may never be chosen. This is addressed by declaring the comparison functions behind &&, @>, <@ and = with COST 100 (instead of the default 1), which raises the Seq Scan estimate while leaving the Bitmap Index Scan cost unchanged, allowing the planner to pick the GIN index within the limits described above (and if a plan still looks wrong, compare it against SET enable_seqscan = off).

  4. No MCV list or histogram is collected for roaringbitmap columns. The type brings its own ANALYZE function, so ANALYZE stores only the null fraction, the average width and an "unknown" distinct count — The full statistics are expensive to maintain and rarely useful for typical bitmap workloads.

roaringbitmap64

about roaringbitmap64 data type

​​roaringbitmap64​​ is a 64-bit Roaring bitmap implementation, and its format definition can be found in https://github.com/RoaringBitmap/RoaringFormatSpec. Logically, you could think of the roaringbitmap64 data type as bit(18446744073709551615) just like roaringbitmap, and it should be noted that the bigint data added to bitmaps are considered to be unsigned. Within 64 bit bitmaps, numbers are ordered according to uint64. We order the numbers like 0, 1, ..., 9223372036854775807, -9223372036854775808, -9223372036854775807,..., -1.

The comparison operators <, <=, =, >=, > compare bitmaps as ascending element sequences in exactly that uint64 order (lexicographically: the first differing element decides, and a shorter sequence is smaller). ORDER BY, DISTINCT, GROUP BY and rb64_min() / rb64_max() use the same order, so roaringbitmap64('{0,-9223372036854775808}') > roaringbitmap64('{0,2}') is true while roaringbitmap64('{0,-9223372036854775808}') > roaringbitmap64('{0,-1}') is false.

input and ouput

Two kinds of input/output syntax are supported: 'array' and 'bytea'. The default output format is 'bytea'.

postgres=# select roaringbitmap64('{1,100,10}');
                            roaringbitmap64
------------------------------------------------------------------------
 \x0100000000000000000000003a30000001000000000002001000000001000a006400
(1 row)

or

postgres=# select '\x0100000000000000000000003a30000001000000000002001000000001000a006400'::roaringbitmap64;
                            roaringbitmap64
------------------------------------------------------------------------
 \x0100000000000000000000003a30000001000000000002001000000001000a006400
(1 row)

The output format can changed with roaringbitmap.output_format

postgres=# set roaringbitmap.output_format='bytea';
SET
postgres=# select '{1}'::roaringbitmap64;
                        roaringbitmap64
----------------------------------------------------------------
 \x0100000000000000000000003a3000000100000000000000100000000100
(1 row)

postgres=# set roaringbitmap.output_format='array';
SET
postgres=# select '{1}'::roaringbitmap64;
 roaringbitmap64
-----------------
 {1}
(1 row)

sample of usage

Use bitmap as type of column

CREATE TABLE t1 (id integer, bitmap roaringbitmap64);

Build bitmap from set of bigint

INSERT INTO t1 SELECT 1,rb64_build(ARRAY[1,2,3,4,5,6,7,8,9,200]);

INSERT INTO t1 SELECT 2,rb64_build_agg(e) FROM generate_series(1,100) e;

Bitmap Calculation (OR, AND, XOR, ANDNOT)

SELECT roaringbitmap64('{1,2,3}') | roaringbitmap64('{3,4,5}');
SELECT roaringbitmap64('{1,2,3}') & roaringbitmap64('{3,4,5}');
SELECT roaringbitmap64('{1,2,3}') # roaringbitmap64('{3,4,5}');
SELECT roaringbitmap64('{1,2,3}') - roaringbitmap64('{3,4,5}');

Bitmap Aggregate (OR, AND, XOR, BUILD)

SELECT rb64_or_agg(bitmap) FROM t1;
SELECT rb64_and_agg(bitmap) FROM t1;
SELECT rb64_xor_agg(bitmap) FROM t1;
SELECT rb64_build_agg(e) FROM generate_series(1,100) e;

Calculate cardinality

SELECT rb64_cardinality('{1,2,3}');

Convert bitmap to bigint array

SELECT rb64_to_array(bitmap) FROM t1 WHERE id = 1;

Convert bitmap to SET of bigint

SELECT unnest(rb64_to_array('{1,2,3}'::roaringbitmap64));

or

SELECT rb64_iterate('{1,2,3}'::roaringbitmap64);

Operator List

Operator Input Output Desc Example Result
& roaringbitmap64,roaringbitmap64 roaringbitmap64 bitwise AND roaringbitmap64('{1,2,3}') & roaringbitmap64('{3,4,5}') {3}
| roaringbitmap64,roaringbitmap64 roaringbitmap64 bitwise OR roaringbitmap64('{1,2,3}') | roaringbitmap64('{3,4,5}') {1,2,3,4,5}
| roaringbitmap64,bigint roaringbitmap64 add element to roaringbitmap64 roaringbitmap64('{1,2,3}') | 6 {1,2,3,6}
| bigint,roaringbitmap64 roaringbitmap64 add element to roaringbitmap64 6 | roaringbitmap64('{1,2,3}') {1,2,3,6}
# roaringbitmap64,roaringbitmap64 roaringbitmap64 bitwise XOR roaringbitmap64('{1,2,3}') # roaringbitmap64('{3,4,5}') {1,2,4,5}
<< roaringbitmap64,bigint roaringbitmap64 bitwise shift left roaringbitmap64('{1,2,3}') << 2 {0,1}
>> roaringbitmap64,bigint roaringbitmap64 bitwise shift right roaringbitmap64('{1,2,3}') >> 3 {4,5,6}
- roaringbitmap64,roaringbitmap64 roaringbitmap64 difference(bitwise ANDNOT) roaringbitmap64('{1,2,3}') - roaringbitmap64('{3,4,5}') {1,2}
- roaringbitmap64,bigint roaringbitmap64 remove element from roaringbitmap64 roaringbitmap64('{1,2,3}') - 3 {1,2}
@> roaringbitmap64,roaringbitmap64 bool contains roaringbitmap64('{1,2,3}') @> roaringbitmap64('{3,4,5}') f
@> roaringbitmap64,bigint bool contains roaringbitmap64('{1,2,3,4,5}') @> 3 t
<@ roaringbitmap64,roaringbitmap64 bool is contained by roaringbitmap64('{1,2,3}') <@ roaringbitmap64('{3,4,5}') f
<@ bigint,roaringbitmap64 bool is contained by 3 <@ roaringbitmap64('{3,4,5}') t
&& roaringbitmap64,roaringbitmap64 bool overlap (have elements in common) roaringbitmap64('{1,2,3}') && roaringbitmap64('{3,4,5}') t
= roaringbitmap64,roaringbitmap64 bool equal roaringbitmap64('{1,2,3}') = roaringbitmap64('{3,4,5}') f
< roaringbitmap64,roaringbitmap64 bool less than (uint64 element order) roaringbitmap64('{1,2}') < roaringbitmap64('{2}') t
<= roaringbitmap64,roaringbitmap64 bool less than or equal to (uint64 element order) roaringbitmap64('{1,2}') <= roaringbitmap64('{1,3}') t
>= roaringbitmap64,roaringbitmap64 bool greater than or equal to (uint64 element order) roaringbitmap64('{-9223372036854775808}') >= roaringbitmap64('{9223372036854775807}') t
> roaringbitmap64,roaringbitmap64 bool greater than (uint64 element order) roaringbitmap64('{0,-9223372036854775808}') > roaringbitmap64('{0,2}') t
<> roaringbitmap64,roaringbitmap64 bool not equal roaringbitmap64('{1,2,3}') <> roaringbitmap64('{3,4,5}') t

Function List

Function Input Output Desc Example Result
rb64_build bigint[] roaringbitmap64 Create roaringbitmap64 from bigint array rb64_build('{1,2,3,4,5}') {1,2,3,4,5}
rb64_index roaringbitmap64,bigint bigint Return the 0-based index of the element in this roaringbitmap64, or -1 if not present rb64_index('{1,2,3}',3) 2
rb64_cardinality roaringbitmap64 bigint Return cardinality of the roaringbitmap64 rb64_cardinality('{1,2,3,4,5}') 5
rb64_and_cardinality roaringbitmap64,roaringbitmap64 bigint Return cardinality of the AND of two roaringbitmaps rb64_and_cardinality('{1,2,3}','{3,4,5}') 1
rb64_or_cardinality roaringbitmap64,roaringbitmap64 bigint Return cardinality of the OR of two roaringbitmaps rb64_or_cardinality('{1,2,3}','{3,4,5}') 5
rb64_xor_cardinality roaringbitmap64,roaringbitmap64 bigint Return cardinality of the XOR of two roaringbitmaps rb64_xor_cardinality('{1,2,3}','{3,4,5}') 4
rb64_andnot_cardinality roaringbitmap64,roaringbitmap64 bigint Return cardinality of the ANDNOT of two roaringbitmaps rb64_andnot_cardinality('{1,2,3}','{3,4,5}') 2
rb64_is_empty roaringbitmap64 boolean Check if roaringbitmap64 is empty. rb64_is_empty('{1,2,3,4,5}') f
rb64_fill roaringbitmap64,range_start bigint,range_end bigint roaringbitmap64 Fill the specified range (not include the range_end),negative range value will be internally converted to unsigned int64; the range may not contain more than 4294967296 values. rb64_fill('{1,2,3}',5,7) {1,2,3,5,6}
rb64_clear roaringbitmap64,range_start bigint,range_end bigint roaringbitmap64 Clear the specified range (not include the range_end),negative range value will be internally converted to unsigned int64, and range_end = 0 means unlimited rb64_clear('{1,2,3}',2,3) {1,3}
rb64_flip roaringbitmap64,range_start bigint,range_end bigint roaringbitmap64 Negative the specified range (not include the range_end),negative range value will be internally converted to unsigned int64; the range may not contain more than 4294967296 values. rb64_flip('{1,2,3}',2,10) {1,4,5,6,7,8,9}
rb64_range roaringbitmap64,range_start bigint,range_end bigint roaringbitmap64 Return new set with specified range (not include the range_end),negative range value will be internally converted to unsigned int64, and range_end = 0 means unlimited rb64_range('{1,2,3}',2,3) {2}
rb64_range_cardinality roaringbitmap64,range_start bigint,range_end bigint bigint Return the cardinality of specified range (not include the range_end),negative range value will be internally converted to unsigned int64, and range_end = 0 means unlimited rb64_range_cardinality('{1,2,3}',2,3) 1
rb64_min roaringbitmap64 bigint Return the smallest offset in roaringbitmap64. Return NULL if the bitmap is empty rb64_min('{1,2,3}') 1
rb64_max roaringbitmap64 bigint Return the greatest offset in roaringbitmap64. Return NULL if the bitmap is empty rb64_max('{1,2,3}') 3
rb64_rank roaringbitmap64,bigint bigint Return the number of elements that are smaller or equal to the specified offset rb64_rank('{1,2,3}',3) 3
rb64_jaccard_dist(Deprecated) roaringbitmap64,roaringbitmap64 double precision Deprecated, use rb64_jaccard_index instead. The name is misleading: this function returns the Jaccard similarity coefficient, not the distance, and the name may be removed in a future release rb64_jaccard_dist('{1,2,3}','{3,4}') 0.25
rb64_jaccard_index roaringbitmap64,roaringbitmap64 double precision Return the Jaccard similarity coefficient of two bitmaps, |A ∩ B| / |A ∪ B|. Return 1 if both bitmaps are empty rb64_jaccard_index('{1,2,3}','{3,4}') 0.25
rb64_select roaringbitmap64,bitset_limit bigint,bitset_offset bigint=0,reverse boolean=false,range_start bigint=0,range_end bigint=-1 roaringbitmap64 Return subset [bitset_offset,bitset_offset+bitset_limit) of bitmap between range [range_start,range_end),negative range value will be internally converted to unsigned int64, and range_end = 0 means unlimited rb64_select('{1,2,3,4,5,6,7,8,9}',5,2) {3,4,5,6,7}
rb64_to_array roaringbitmap64 bigint[] Convert roaringbitmap64 to bigint array rb64_to_array(roaringbitmap64('{1,2,3}')) {1,2,3}
rb64_iterate roaringbitmap64 SET of bigint Return set of bigint from a roaringbitmap64 data. rb64_iterate(roaringbitmap64('{1,2,3}'))
1
2
3
rb64_runoptimize roaringbitmap64 roaringbitmap64 Return space-optimized bitmap rb64_runoptimize(roaringbitmap64('{1,2,3,4,5}')) {1,2,3,4,5} (but the underlying bitmap is smaller)
rb64_group_elements_by_source roaringbitmap64[] TABLE(sources integer[], members roaringbitmap64) Group the elements found across an array of bitmaps by the combination of source bitmaps (1-based indices into the input array) that contain them
select sources, rb64_to_array(members)
    from rb64_group_elements_by_source(ARRAY[
        rb64_build('{1,2,3,4,5}'),
        rb64_build('{1,2,3,6,7}')
    ])
sources | rb64_to_array
--------+--------------
{1,2}   | {1,2,3}
{1}     | {4,5}
{2}     | {6,7}

Aggregation List

Function Input Output Desc Example Result
rb64_build_agg bigint roaringbitmap64 Build a roaringbitmap64 from a bigint set
select rb64_build_agg(id)
    from (values (1),(2),(3)) t(id)
{1,2,3}
rb64_or_agg roaringbitmap64 roaringbitmap64 AND Aggregate calculations from a roaringbitmap64 set
select rb64_or_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
{1,2,3,4}
rb64_and_agg roaringbitmap64 roaringbitmap64 AND Aggregate calculations from a roaringbitmap64 set
select rb64_and_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
{2,3}
rb64_xor_agg roaringbitmap64 roaringbitmap64 XOR Aggregate calculations from a roaringbitmap64 set
select rb64_xor_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
{1,4}
rb64_or_cardinality_agg roaringbitmap64 bigint OR Aggregate calculations from a roaringbitmap64 set, return cardinality.
select rb64_or_cardinality_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
4
rb64_and_cardinality_agg roaringbitmap64 bigint AND Aggregate calculations from a roaringbitmap64 set, return cardinality
select rb64_and_cardinality_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
2
rb64_xor_cardinality_agg roaringbitmap64 bigint XOR Aggregate calculations from a roaringbitmap64 set, return cardinality
select rb64_xor_cardinality_agg(bitmap)
    from (values (roaringbitmap64('{1,2,3}')),
                 (roaringbitmap64('{2,3,4}'))
          ) t(bitmap)
2

Index Support

roaringbitmap64 supports btree, hash and GIN indexes, and the operators they support are listed below.

Index Type Operators Use Case
btree <, <=, =, >=, > equality, range and ORDER BY on low-cardinality bitmaps; supports UNIQUE
hash = equality only (no range or ORDER BY), but works on bitmaps of any size
gin &&, @>, <@, =, @> (int8) set containment and overlap; the only option for high-cardinality bitmaps

Sample:

CREATE INDEX ... USING btree(col);
CREATE INDEX ... USING hash(col);
CREATE INDEX ... USING gin(col);

Notes

  1. btree limits the size of an index key. Bitmap values are stored in the index as is and are never TOASTed, so CREATE INDEX ... USING btree (col) fails once a bitmap exceeds roughly 2.7 KB: ERROR: index row size 2832 exceeds btree version 4 maximum 2704.

  2. GIN index size depends on the total number of elements, not on the number of rows. GIN keys are element-level int8 values, so dense bitmaps bloat the index, which can grow far larger than the table it indexes.

  3. High-cardinality bitmaps overflow to TOAST, which hides the real cost of a sequential scan. The planner computes the Seq Scan cost from the heap's own page count and ignores the TOAST pages that must be read to detoast every value, so the estimate is far too low and a much faster GIN index may never be chosen. This is addressed by declaring the comparison functions behind &&, @>, <@ and = with COST 100 (instead of the default 1), which raises the Seq Scan estimate while leaving the Bitmap Index Scan cost unchanged, allowing the planner to pick the GIN index within the limits described above (and if a plan still looks wrong, compare it against SET enable_seqscan = off).

  4. No MCV list or histogram is collected for roaringbitmap64 columns. The type brings its own ANALYZE function, so ANALYZE stores only the null fraction, the average width and an "unknown" distinct count — The full statistics are expensive to maintain and rarely useful for typical bitmap workloads.

Cloud Vendor Support

pg_roaringbitmap is supported by the following cloud vendors

To request support for pg_roaringbitmap from other cloud vendors, please see the following:

  • DigitalOcean Managed Databases: comment on this idea
  • Azure Database for PostgreSQL: comment on this post

About

RoaringBitmap extension for PostgreSQL

Topics

Resources

Stars

288 stars

Watchers

16 watching

Forks

Releases

Packages

Used by

Contributors

Languages