Roaring bitmap adalah struktur data bitmap terkompresi yang dioptimalkan untuk operasi himpunan seperti irisan (intersection), gabungan (union), selisih (difference), dan deduplikasi. Roaring bitmap menggunakan memori jauh lebih sedikit dibandingkan bitmap konvensional sekaligus memberikan performa lebih cepat, sehingga sangat cocok untuk beban kerja profil pengguna (user profiling), rekomendasi personalisasi, dan pemasaran presisi.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Instans AnalyticDB for PostgreSQL yang menjalankan versi V6.3.8.9 atau lebih baru. Untuk memeriksa versi minor instans Anda, lihat Lihat versi mesin minor.
Ekstensi
roaringbitmapyang telah diinstal pada instans tersebut. Lihat Instal, perbarui, dan uninstal ekstensi.
Cara kerja
Roaring bitmap mengkodekan setiap bilangan bulat 32-bit dengan membaginya menjadi 16 bit paling signifikan (disimpan sebagai kunci chunk) dan 16 bit paling tidak signifikan (disimpan dalam container). Setiap chunk menampung hingga 2^16 bilangan bulat, dan chunk-chunk tersebut diurutkan dalam array yang dapat diperluas secara dinamis sehingga pencarian biner dapat menemukan nilai apa pun dengan cepat.
Jenis container dipilih secara otomatis berdasarkan karakteristik data:
| Container type | When used | Capacity |
|---|---|---|
| Array container | Nilai sparse dan tidak berurutan | Kurang dari 4.096 bilangan bulat |
| Bitmap container | Bilangan bulat padat dan berurutan | 4.096 bilangan bulat atau lebih |
| Run container | Rentang panjang nilai berurutan yang meningkat | Lebih kecil daripada container array maupun bitmap |
Tata letak penyimpanan adaptif ini menjaga rasio kompresi tetap tinggi dan memungkinkan operasi AND, OR, dan XOR dilakukan langsung antar jenis container. Untuk informasi lebih lanjut mengenai struktur data dasarnya, lihat repositori CRoaring.
Memulai
Langkah-langkah berikut menjelaskan alur kerja lengkap: instal ekstensi, buat tabel, masukkan data, dan jalankan kueri bitmap.
1. Instal ekstensi.
Pada halaman Extensions instans Anda, instal ekstensi roaringbitmap.
2. Buat tabel dengan kolom `roaringbitmap`.
CREATE TABLE t1 (id integer, bitmap roaringbitmap);3. Masukkan data roaring bitmap.
Gunakan RB_BUILD untuk membuat bitmap dari array bilangan bulat eksplisit, atau RB_BUILD_AGG untuk mengagregasi rangkaian bilangan bulat menjadi bitmap.
-- Membuat bitmap dari array eksplisit (mengatur bit pada posisi 1-9 dan 200)
INSERT INTO t1 SELECT 1, RB_BUILD(ARRAY[1,2,3,4,5,6,7,8,9,200]);
-- Membuat bitmap dengan mengagregasi rangkaian bilangan bulat 1-100
INSERT INTO t1 SELECT 2, RB_BUILD_AGG(e) FROM GENERATE_SERIES(1,100) e;4. Kueri posisi bit.
RB_ITERATE mengembalikan setiap posisi bilangan bulat tempat bit diatur ke 1.
SELECT RB_ITERATE(bitmap) FROM t1 WHERE id = 1;5. Lakukan operasi himpunan bitmap.
Gunakan sintaks fungsi atau sintaks operator yang setara—keduanya menghasilkan hasil yang sama.
-- OR: gabungan dua bitmap (sintaks fungsi)
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: gabungan dua bitmap (sintaks operator)
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. Agregasi bitmap lintas baris.
SELECT RB_OR_AGG(bitmap) FROM t1; -- Gabungan semua bitmap
SELECT RB_AND_AGG(bitmap) FROM t1; -- Irisan semua bitmap
SELECT RB_XOR_AGG(bitmap) FROM t1; -- Selisih simetris semua bitmap7. Hitung jumlah bit yang diatur (cardinality).
SELECT RB_CARDINALITY(bitmap) FROM t1;Fungsi perhitungan bitmap
| Function | Input | Output | Description | Example | Result |
|---|---|---|---|---|---|
| rb_build | integer[] | roaringbitmap | Membuat roaring bitmap dari array bilangan bulat. | rb_build('{1,2,3,4,5}') | {1,2,3,4,5} |
| rb_and | roaringbitmap, roaringbitmap | roaringbitmap | Melakukan operasi AND. | rb_and(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {3} |
| rb_or | roaringbitmap, roaringbitmap | roaringbitmap | Melakukan operasi OR. | rb_or(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2,3,4,5} |
| rb_xor | roaringbitmap, roaringbitmap | roaringbitmap | Melakukan operasi XOR. | rb_xor(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2,4,5} |
| rb_andnot | roaringbitmap, roaringbitmap | roaringbitmap | Melakukan operasi ANDNOT. | rb_andnot(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | {1,2} |
| rb_cardinality | roaringbitmap | integer | Mengembalikan jumlah bit yang diatur. | rb_cardinality(rb_build('{1,2,3,4,5}')) | 5 |
| rb_and_cardinality | roaringbitmap, roaringbitmap | integer | Mengembalikan cardinality dari hasil operasi AND. | rb_and_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 1 |
| rb_or_cardinality | roaringbitmap, roaringbitmap | integer | Mengembalikan cardinality dari hasil operasi OR. | rb_or_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 5 |
| rb_xor_cardinality | roaringbitmap, roaringbitmap | integer | Mengembalikan cardinality dari hasil operasi XOR. | rb_xor_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 4 |
| rb_andnot_cardinality | roaringbitmap, roaringbitmap | integer | Mengembalikan cardinality dari hasil operasi ANDNOT. | rb_andnot_cardinality(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | 2 |
| rb_is_empty | roaringbitmap | boolean | Memeriksa apakah roaring bitmap kosong. | rb_is_empty(rb_build('{1,2,3,4,5}')) | false |
| rb_equals | roaringbitmap, roaringbitmap | boolean | Memeriksa apakah dua roaring bitmap sama. | rb_equals(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | false |
| rb_intersect | roaringbitmap, roaringbitmap | boolean | Memeriksa apakah dua roaring bitmap saling beririsan. | rb_intersect(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | true |
| rb_remove | roaringbitmap, integer | roaringbitmap | Menghapus offset tertentu. | rb_remove(rb_build('{1,2,3}'), 3) | {1,2} |
| rb_remove | roaringbitmap, integer, integer | roaringbitmap | Menghapus rentang offset tertentu. | rb_remove(rb_build('{1,2,3,4,6,7,8}'), 6, 8) | {1,2,3,4} |
| rb_flip | roaringbitmap, integer | roaringbitmap | Membalik bit pada offset tertentu. | rb_flip(rb_build('{1,2,3}'), 3) | {1,2} |
| rb_flip | roaringbitmap, integer, integer | roaringbitmap | Membalik semua bit dalam rentang offset tertentu. | rb_flip(rb_build('{1,2,3}'), 2, 3) | |
| rb_minimum | roaringbitmap | integer | Mengembalikan offset terkecil yang diatur. Mengembalikan -1 jika bitmap kosong. | rb_minimum(rb_build('{1,2,3}')) | 1 |
| rb_maximum | roaringbitmap | integer | Mengembalikan offset terbesar yang diatur. Mengembalikan 0 jika bitmap kosong. | rb_maximum(rb_build('{1,2,3}')) | 3 |
| rb_rank | roaringbitmap, integer | integer | Mengembalikan jumlah offset yang diatur kurang dari atau sama dengan nilai yang ditentukan. | rb_rank(rb_build('{1,2,3}'), 3) | 3 |
| rb_iterate | roaringbitmap | setof integer | Mengembalikan setiap offset yang diatur sebagai satu baris. | rb_iterate(rb_build('{1,2,3}')) | 1, 2, 3 (satu per baris) |
| rb_iterate_decrement | roaringbitmap | integer[] | Mengembalikan semua offset yang diatur dalam urutan menurun sebagai array. | rb_iterate_decrement(rb_build('{1,2,3,4}')) | {4,3,2,1} |
| rb_contains | roaringbitmap, integer | boolean | Memeriksa apakah bitmap berisi offset tertentu. | rb_contains(rb_build('{1,2,3}'), 1) | true |
| rb_contains | roaringbitmap, integer, integer | boolean | Memeriksa apakah bitmap berisi rentang offset tertentu. | rb_contains(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | |
| rb_contains | roaringbitmap, roaringbitmap | boolean | Memeriksa apakah sebuah bitmap berisi bitmap lainnya. | rb_contains(rb_build('{1,2,3}'), rb_build('{3,4,5}')) | false |
| rb_becontained | integer, roaringbitmap | boolean | Memeriksa apakah offset tertentu terdapat dalam bitmap. | rb_becontained(1, rb_build('{1,2,3}')) | true |
| rb_becontained | roaringbitmap, roaringbitmap | boolean | Memeriksa apakah sebuah bitmap terdapat dalam bitmap lainnya. | rb_becontained(rb_build('{1}'), rb_build('{1,2,3}')) | true |
| rb_add | roaringbitmap, integer | roaringbitmap | Menambahkan offset tertentu. | rb_add(rb_build('{1,2,3,4}'), 5) | {1,2,3,4,5} |
| rb_add | roaringbitmap, integer, integer | roaringbitmap | Menambahkan rentang offset tertentu. | rb_add(rb_build('{1,2,3,4}'), 6, 8) | {1,2,3,4,6,7,8} |
| rb_add_2 | integer, roaringbitmap | roaringbitmap | Menambahkan offset tertentu ke bitmap (urutan argumen dibalik). | rb_add_2(5, rb_build('{1,2,3,4}')) | {1,2,3,4,5} |
| rb_jaccard_index | roaringbitmap, roaringbitmap | float8 | Menghitung koefisien kemiripan Jaccard antara dua bitmap. | rb_jaccard_index(rb_build('{1,2,3,4}'), rb_build('{1,2}')) | 0,5 |
| rb_to_array | roaringbitmap | integer[] | Mengonversi roaring bitmap menjadi array bilangan bulat. | rb_to_array(rb_build('{1,2,3,4}')) | {1,2,3,4} |
Fungsi agregat bitmap
| Function | Input | Output | Description | Example | Result |
|---|---|---|---|---|---|
| rb_build_agg | integer | roaringbitmap | Mengagregasi kumpulan offset menjadi roaring bitmap. | rb_build_agg(1) | {1} |
| rb_or_agg | roaringbitmap | roaringbitmap | Melakukan operasi agregat OR lintas baris. | rb_or_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_and_agg | roaringbitmap | roaringbitmap | Melakukan operasi agregat AND lintas baris. | rb_and_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_xor_agg | roaringbitmap | roaringbitmap | Melakukan operasi agregat XOR lintas baris. | rb_xor_agg(rb_build('{1,2,3}')) | {1,2,3} |
| rb_or_cardinality_agg | roaringbitmap | integer | Mengembalikan cardinality dari hasil agregat OR. | rb_or_cardinality_agg(rb_build('{1,2,3}')) | 3 |
| rb_and_cardinality_agg | roaringbitmap | integer | Mengembalikan cardinality dari hasil agregat AND. | rb_and_cardinality_agg(rb_build('{1,2,3}')) | 3 |
| rb_xor_cardinality_agg | roaringbitmap | integer | Mengembalikan cardinality dari hasil agregat XOR. | rb_xor_cardinality_agg(rb_build('{1,2,3}')) | 3 |
Operator
Semua operator memiliki bentuk fungsi setara yang tercantum pada bagian sebelumnya. Sintaks operator lebih ringkas untuk ekspresi SQL inline.
| Operator | Left | Right | Output | Description | Example |
|---|---|---|---|---|---|
& | roaringbitmap | roaringbitmap | roaringbitmap | Operasi AND. | rb_build('{1,2,3}') & rb_build('{1,2,4}') |
| | roaringbitmap | roaringbitmap | roaringbitmap | Operasi OR. | rb_build('{1,2}') | rb_build('{1,3}') |
# | roaringbitmap | roaringbitmap | roaringbitmap | Operasi XOR. | rb_build('{1,2}') # rb_build('{1,3}') |
~ | roaringbitmap | roaringbitmap | roaringbitmap | Operasi ANDNOT. | rb_build('{2,3}') ~ rb_build('{2,4}') |
+ | roaringbitmap | integer | roaringbitmap | Menambahkan offset tertentu. | rb_build('{2,3}') + 1 |
- | roaringbitmap | integer | roaringbitmap | Menghapus offset tertentu. | rb_build('{1,2,3}') - 1 |
= | roaringbitmap | roaringbitmap | boolean | Memeriksa apakah dua bitmap sama. | rb_build('{2,3}') = rb_build('{2,3}') |
<> | roaringbitmap | roaringbitmap | boolean | Memeriksa apakah dua bitmap berbeda. | rb_build('{2,3}') <> rb_build('{1,2,3}') |
&& | roaringbitmap | roaringbitmap | boolean | Memeriksa apakah dua bitmap saling beririsan. | rb_build('{2,3}') && rb_build('{3,4}') |
@> | roaringbitmap | roaringbitmap | boolean | Memeriksa apakah bitmap kiri berisi bitmap kanan. | rb_build('{2,3}') @> rb_build('{2}') |
@> | roaringbitmap | integer | boolean | Memeriksa apakah bitmap berisi offset tertentu. | rb_build('{2,3}') @> 2 |
<@ | roaringbitmap | roaringbitmap | boolean | Memeriksa apakah bitmap kiri terdapat dalam bitmap kanan. | rb_build('{2,3}') <@ rb_build('{1,2,3}') |
<@ | integer | roaringbitmap | boolean | Memeriksa apakah offset terdapat dalam bitmap. | 2 <@ rb_build('{2,3}') |