Skip to content

Commit dc322af

Browse files
committed
[ydb-platform#14319] Add docs for Roaring UDF
1 parent 7fb4b65 commit dc322af

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Roaring
2+
3+
## Introduction
4+
5+
Bitsets, also called bitmaps, are commonly used as fast data structures. Unfortunately, they can use too much memory. To compensate, we often use compressed bitmaps.
6+
7+
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.
8+
9+
## Implementation
10+
11+
You can work with Roaring bitmap in YDB using a set of user-defined functions (UDFs) in the `Roaring` module. They provide the ability to work with 32-bit Roaring bitmaps. To do this, the data must be serialized in the format for 32-bit bitmaps described in the [specification](https://github.com/RoaringBitmap/RoaringFormatSpec?tab=readme-ov-file#standard-32-bit-roaring-bitmap). This can be done using a function available in the Roaring bitmap library itself. Such libraries exist for many languages, for example, for [Go](https://github.com/RoaringBitmap/roaring).
12+
13+
The application can then save the serialized bitmap in a column with the `String` type.
14+
15+
To work with Roaring bitmap, data from the string type must be deserialized into the [Resource<roaring_bitmap>](../../types/special.md) type. To save, you need to do the reverse operation. After that, the application will be able to read the updated bitmap from YDB and deserialize it on its side.
16+
17+
## Available methods
18+
19+
```yql
20+
Roaring::Deserialize(String{Flags:AutoMap})->Resource<roaring_bitmap>
21+
Roaring::FromUint32List(List<Uint32>{Flags:AutoMap})->Resource<roaring_bitmap>
22+
Roaring::Serialize(Resource<roaring_bitmap>{Flags:AutoMap})->String
23+
Roaring::Uint32List(Resource<roaring_bitmap>{Flags:AutoMap})->List<Uint32>
24+
25+
Roaring::Cardinality(Resource<roaring_bitmap>{Flags:AutoMap})->Uint32
26+
27+
Roaring::Or(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
28+
Roaring::OrWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
29+
30+
Roaring::And(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
31+
Roaring::AndWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
32+
33+
Roaring::AndNot(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
34+
Roaring::AndNotWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
35+
36+
Roaring::RunOptimize(Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
37+
```
38+
39+
## Serialization and Deserialization
40+
41+
Two functions `Deserialize` and `FromUint32List` are available for creating `Resource<roaring_bitmap>`. The second function allows creating Roaring bitmap from list of unsigned integers, i.e. without the need to use the Roaring bitmaps library code to create a binary representation.
42+
43+
YDB does not store data with the `Resource` type, so the created bitmap must be converted to a binary representation using the `Serialize` method.
44+
45+
To use the resulting bitmap, for example, in the `WHERE` condition, the `Uint32List` method is provided, which returns a list of unsigned integers from the `Resource<roaring_bitmap>`.
46+
47+
## Bitwise operations
48+
49+
Currently, three modifying binary operations with bitmaps are supported:
50+
- `Or`
51+
- `And`
52+
- `AndNot`
53+
54+
The operations are modifying, meaning that they modify the `Resource<roaring_bitmap>` passed in the first argument. Each of these operations has a version with the `WithBinary` suffix, which allows working with the binary representation without having to deserialize it into the `Resource<roaring_bitmap>` type. The implementation of these methods still has to deserialize to perform the operation, but it does not create an intermediate `Resource` to save resources.
55+
56+
## Other operations
57+
58+
The `Cardinality` function is provided to obtain the number of bits set to 1 in the `Resource<roaring_bitmap>`.
59+
60+
After the bitmap has been constructed or modified, it can be optimized using the `RunOptimize` method. Internal format of Roaring bitmap can use containers with better representation for different bit sequences.
61+
62+
## Examples
63+
64+
```yql
65+
--!syntax_v1
66+
$b = Roaring::FromUint32List(AsList(42));
67+
$b = Roaring::Or($b, Roaring::FromUint32List(AsList(56)));
68+
69+
70+
SELECT Roaring::Uint32List($b) AS `Or`; -- [42, 56]
71+
```
72+
73+
74+
```yql
75+
$b1 = Roaring::FromUint32List(AsList(10, 567, 42));
76+
$b2 = Roaring::FromUint32List(AsList(42));
77+
78+
$b2ser = Roaring::Serialize($b2); -- save this to String column
79+
80+
SELECT Roaring::Cardinality(Roaring::AndWithBinary($b1, $b2ser)) AS Cardinality; -- 1
81+
82+
SELECT Roaring::Uint32List(Roaring::And($b1, $b2)) AS `And`; -- [42]
83+
SELECT Roaring::Uint32List(Roaring::AndWithBinary($b1, $b2ser)) AS AndWithBinary; -- [42]
84+
```
85+
86+
```yql
87+
--!syntax_v1
88+
89+
$b1 = Roaring::FromUint32List(AsList(10, 567, 42));
90+
$b2 = Roaring::FromUint32List(AsList(42));
91+
92+
$b2ser = Roaring::Serialize($b2); -- save this to String column
93+
94+
SELECT Roaring::Cardinality(Roaring::AndNotWithBinary($b1, $b2ser)) AS Cardinality; -- 2
95+
96+
SELECT Roaring::Uint32List(Roaring::AndNot($b1, $b2)) AS AndNot; -- [10,567]
97+
SELECT Roaring::Uint32List(Roaring::AndNotWithBinary($b1, $b2ser)) AS AndNotWithBinary; -- [10,567]
98+
```
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Roaring
2+
3+
## Введение
4+
5+
Битовые множства, также называемые битовыми картами (bitmaps), обычно используются в качестве быстрых структур данных. К сожалению, они могут использовать слишком много памяти. Для того, чтобы уменьшить занимаемую используется сжатие.
6+
7+
Roaring bitmaps — это сжатые битовые карты, которые, как правило, превосходят обычные алгоритмы сжатия битовых карт, такие как WAH, EWAH или Concise. В некоторых случаях Roaring bitmaps могут быть в сотни раз быстрее, и они часто предлагают значительно лучшее сжатие. Они могут быть даже быстрее, чем несжатые битовые карты.
8+
9+
## Реализация
10+
11+
Работать с Roaring bitmap в YDB можно с помощью набора пользовательских функций UDF в модуле `Roaring`. Они предоставляют возможность работать с 32-битными Roaring bitmap. Для этого данные должны быть сериализованы в формате для 32-битных битовых масок, описанном в [спецификации](https://github.com/RoaringBitmap/RoaringFormatSpec?tab=readme-ov-file#standard-32-bit-roaring-bitmap). Это можно сделать с помощью функции, доступной в библиотеке Roaring bitmap. Такие библиотеки есть для многих языков, например, для [Go](https://github.com/RoaringBitmap/roaring).
12+
13+
Сериализованную битовую маску приложение может сохранить в колонке с типом `String`.
14+
15+
Для работы с Roaring bitmap данные из строкового типа необходимо десериализовать в тип [Resource<roaring_bitmap>](../../types/special.md). Для сохранения нужно проделать обратную операцию. После этого приложение сможет прочитать обновлённую битовую маску из YDB, и десериализовать её уже на своей стороне.
16+
17+
## Доступные методы
18+
19+
```yql
20+
Roaring::Deserialize(String{Flags:AutoMap})->Resource<roaring_bitmap>
21+
Roaring::FromUint32List(List<Uint32>{Flags:AutoMap})->Resource<roaring_bitmap>
22+
Roaring::Serialize(Resource<roaring_bitmap>{Flags:AutoMap})->String
23+
Roaring::Uint32List(Resource<roaring_bitmap>{Flags:AutoMap})->List<Uint32>
24+
25+
Roaring::Cardinality(Resource<roaring_bitmap>{Flags:AutoMap})->Uint32
26+
27+
Roaring::Or(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
28+
Roaring::OrWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
29+
30+
Roaring::And(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
31+
Roaring::AndWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
32+
33+
Roaring::AndNot(Resource<roaring_bitmap>{Flags:AutoMap}, Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
34+
Roaring::AndNotWithBinary(Resource<roaring_bitmap>{Flags:AutoMap}, String{Flags:AutoMap})->Resource<roaring_bitmap>
35+
36+
Roaring::RunOptimize(Resource<roaring_bitmap>{Flags:AutoMap})->Resource<roaring_bitmap>
37+
```
38+
39+
## Сериализация и десериализация
40+
41+
Для создания `Resource<roaring_bitmap>` доступны две функции `Deserialize` и `FromUint32List`. Вторая функция позволяет создавать Roaring bitmap из списков беззнаковых целых чисел, то есть без необходимости использовть библиотечный код Roaring bitmaps для создания бинарного представления.
42+
43+
YDB не сохраняет данные с типом `Resource`, поэтому созданную битовую маску необходимо превратить в бинарное представление с помощью метода `Serialize`.
44+
45+
Чтобы использовать результирующую битовую маску, например, в условии `WHERE` предусмотрен метод `Uint32List`, который возвращает список беззнаковых целых чисел из `Resource<roaring_bitmap>`.
46+
47+
48+
## Битовые операции
49+
50+
В настоящий момент поддержаны три модфицирующих бинарных операции с битовыми масками:
51+
- `Or`
52+
- `And`
53+
- `AndNot`
54+
55+
То, что операции являются модифицирующими означает, что они изменяют `Resource<roaring_bitmap>`, переданный в первом аргументе. У каждой из этих операций есть версия с суффиксом `WithBinary`, которая позволяет работать с бинарным представлением, не прибегая к его десериализации в тип `Resource<roaring_bitmap>`. Реализация этих методов всё равно вынуждена выполнить десериализацию для выполнения операции, но она не создаёт промежуточный `Resource` для экономии ресурсов.
56+
57+
## Прочие операции
58+
59+
Для получения кардинальности (количества бит, установленных в 1) предусмотрена функция `Cardinality`.
60+
61+
После построения или модификации битовой маски её можно оптимизировать с помощью метода `RunOptimize`. Это связано с тем, что внутренний формат Roaring bitmap может использовать контейнеры с лучшим представлением для разных последовательностей бит.
62+
63+
## Примеры
64+
65+
```yql
66+
--!syntax_v1
67+
$b = Roaring::FromUint32List(AsList(42));
68+
$b = Roaring::Or($b, Roaring::FromUint32List(AsList(56)));
69+
70+
71+
SELECT Roaring::Uint32List($b) AS `Or`; -- [42, 56]
72+
```
73+
74+
75+
```yql
76+
$b1 = Roaring::FromUint32List(AsList(10, 567, 42));
77+
$b2 = Roaring::FromUint32List(AsList(42));
78+
79+
$b2ser = Roaring::Serialize($b2); -- результат можно сохранить в колонку с типом String
80+
81+
SELECT Roaring::Cardinality(Roaring::AndWithBinary($b1, $b2ser)) AS Cardinality; -- 1
82+
83+
SELECT Roaring::Uint32List(Roaring::And($b1, $b2)) AS `And`; -- [42]
84+
SELECT Roaring::Uint32List(Roaring::AndWithBinary($b1, $b2ser)) AS AndWithBinary; -- [42]
85+
```
86+
87+
```yql
88+
--!syntax_v1
89+
90+
$b1 = Roaring::FromUint32List(AsList(10, 567, 42));
91+
$b2 = Roaring::FromUint32List(AsList(42));
92+
93+
$b2ser = Roaring::Serialize($b2); -- результат можно сохранить в колонку с типом String
94+
95+
SELECT Roaring::Cardinality(Roaring::AndNotWithBinary($b1, $b2ser)) AS Cardinality; -- 2
96+
97+
SELECT Roaring::Uint32List(Roaring::AndNot($b1, $b2)) AS AndNot; -- [10,567]
98+
SELECT Roaring::Uint32List(Roaring::AndNotWithBinary($b1, $b2ser)) AS AndNotWithBinary; -- [10,567]
99+
```

0 commit comments

Comments
 (0)