Dictionary is a classic compression technique that can greatly reduce the size of data. Kylin apply dictionary to all dimension values stored in cube.
Kylin's requirement to dictionary:
Dictionary is implemented as a trie data structure. Dictionary ID (or “seq. no” below) is chosen in a way to preserve value order. Then at query time, predicate filters can be pushed down to storage and be evaluated on the IDs.
An example of a trie dictionary.
Once built, the dictionary is serialized into a chunk of bytes. This is how it stays in memory and also in file.
We compared dictionary‘s size and performance with HashMap and ID Based Array. It’s memory footprint is an order less and the throughput is very stable accross scales.
| HashMap (value=>id) | Dictionary (value=>id) | IdArray (id=>value) | Dictionary (id=>value) | ||
|---|---|---|---|---|---|
| 150K eng words footprint (bytes) | 18.8M | 1.7M | 11.1M | 1.7M | 1.4M raw size |
| 150K eng words throughput (acc/s) | 13M | 1.9M | 150M | 1.96M | 31 max value len |
| 6.6K categories footprint (bytes) | 0.94M | 0.13M | 0.58M | 0.12M | 0.1M raw size |
| 6.6K categories throughput (acc/s) | 26M | 2.0M | 98M | 2.0M | 30 max value len |
| 6 words footprint (bytes) | 792B | 168B | 416B | 168B | 33B raw size |
| 6 works throughput (acc/s) | 68.5M | 14.7M | 714M | 11.1M | 9 max value len |
To achieve maximum lookup throughput, a cache layer (HashMap or IdArray) sits on top of dictionary using weak reference. The cache could be gone when memory runs short, then dictionary will be hit directly.