Kasus penggunaan Anda sangat menarik dan cukup kompleks dari segi efisiensi penyimpanan dan kebutuhan akses dua arah (label → nilai dan nilai → label). Anda sudah berada di jalur yang sangat baik dengan pertimbangan penggunaan RocksDB dan transformasi representasi label. Saya akan menjawab pertanyaan Anda satu per satu secara terperinci:
Ya, RocksDB mendukung kompresi awalan kunci (prefix compression) secara eksplisit melalui konfigurasi block-based table format. Mekanisme ini sangat berguna jika kunci-kunci Anda memiliki awalan yang panjang dan berulang seperti dalam kasus label hierarkis.
Prefix Compression: Secara default, RocksDB menggunakan prefix compression di dalam setiap blok data (biasanya 4KB secara default), yang menyimpan hanya delta dari awalan kunci sebelumnya.
Key Delta Encoding: Jika Anda menyimpan kunci dalam urutan leksikografis (yang disarankan), RocksDB akan menyimpan hanya perbedaan antara kunci saat ini dengan sebelumnya, yang sangat efisien untuk struktur jalur seperti ferroelectric/optical/drew
.
Anda dapat mengatur ini melalui BlockBasedTableOptions
:
cpp
SalinEdit
options.table_factory.reset(NewBlockBasedTableFactory( BlockBasedTableOptions().SetDataBlockIndexType(kDataBlockBinaryAndHash) ));
Anda juga bisa menambahkan prefix_extractor
(misalnya, rocksdb::NewFixedPrefixTransform(prefix_length)
) untuk membantu filter indexing jika ingin mempercepat pencarian berdasarkan awalan.
➡️ Rekomendasi: Simpan kunci label dalam bentuk string UTF-8 yang diurutkan leksikografis, dan manfaatkan prefix compression bawaan RocksDB.
RocksDB tidak mendukung secara langsung relasi antar kolom dalam satu database layaknya RDBMS (tidak ada foreign key atau join). Tapi:
Anda dapat menggunakan Column Families untuk menyimpan data yang saling terkait:
Misalnya, satu column family menyimpan mapping label → nilai, dan column family lain menyimpan mapping nilai → label (terbalik).
Dengan WriteBatch dan transaksi, Anda bisa menjaga keduanya tetap sinkron.
Namun, RocksDB tidak memiliki kompresi bersama antar column family – setiap column family memiliki kompresinya sendiri, jadi mengulang string panjang di dua tempat bisa memakan ruang lebih.
➡️ Rekomendasi: Jika efisiensi penyimpanan jadi perhatian besar, maka duplikasi label panjang di column family berbeda tidak efisien. Gunakan teknik de-referencing seperti yang Anda jelaskan di poin 3.
Ya, secara signifikan. Pendekatan menggantikan segmen jalur string dengan ID numerik kecil memiliki potensi manfaat besar dalam efisiensi ruang, terutama karena:
String panjang diulang berkali-kali dalam struktur jalur.
Penggunaan ID (misalnya, 32-bit) per segmen memungkinkan representasi kunci menjadi array kecil dari angka tetap (misalnya, 3–5 * 4 byte per label).
RocksDB sangat efisien dalam menyimpan kunci biner pendek.
Anda juga bisa menggabungkan segmen ID menjadi satu key binary blob untuk memaksimalkan kompresi dan urutan leksikografis.
Untuk implementasinya:
Buat satu column family untuk mapping segmen → ID.
Gunakan transactional batch untuk memastikan bahwa setiap insert ke "main store" menggunakan ID yang konsisten.
Pertimbangkan penggunaan encoding seperti varint atau delta encoding jika jumlah segmen besar tapi sebagian besar ID-nya kecil.
➡️ Estimasi efisiensi:
Misalnya, path turbofan/metaphase-insignia-clinch/scenography
sepanjang 45 byte dalam UTF-8.
Dengan 3 segmen dan masing-masing ID 32-bit: hanya 12 byte!
Jika RocksDB menggunakan prefix compression atas ID ini (karena representasi biner urut), maka efisiensi bisa meningkat drastis.
Gunakan prefix compression RocksDB – sangat sesuai dengan karakteristik label Anda.
Untuk kebutuhan dua arah (label ↔ nilai), duplikasi string tidak efisien. Sebaiknya gunakan representasi indirected (ordinal/ID).
Pendekatan segment ID sangat layak dan bisa membawa efisiensi besar dalam penyimpanan dan pencarian – dengan overhead yang bisa dikelola melalui transactional batch.
Pertimbangkan untuk membuat tool internal seperti dictionary segment store + encoder/decoder jalur sebagai lapisan abstraksi di atas RocksDB.
Apakah Anda juga ingin contoh kode bagaimana menyimpan dan meng-encode label menjadi segmen ID di RocksDB dengan transaksi?