我们介绍一种基于Cuckoo Hashing Cuckoo Hashing 的新SST文件格式,它可以有很高的点查效率。如果应用不使用range scan但是需要非常高的点查率,可以使用这种新的format。Cuckoo Hashing Table Format | RocksDB 对这种算法做了进一步介绍。
好处:
- 面向大量查找,每次查找只有一次内存访问;
- 由于我们不在key中存储seqence和值类型(put 、delete等),因此压缩后数据库每个键小 8 个字节。
限制
- 因为文件格式基于hash,range scan非常慢;
- key和value长度是固定的;
- 不支持merge操作;
- 不支持snapshots;
- 在最坏的情况下,数据库中最后一个SST文件的利用率可能只有50%。
可以通过table.h的NewCuckooTableFactory()来创建 table factory;具体参数可见
include/rocksdb/table.h or blogpost 。
例如
options.table_factory.reset(NewCuckooTableFactory());
或者
options.table_factory.reset(NewCuckooTableFactory(
0.9 /* hash_table_ratio */,
100 /* max_search_depth */,
5 /* cuckoo_block_size */);
文件格式
Cuckoo SST file包含:
- 包含键值对的哈希表,并且使用表中键范围之外的特殊键填充空桶。
- 包含表属性的Property块
- 元数据和footer
<beginning_of_file>
<beginning_of_hash_table>
[key1 value1]
[key2 value2]
[key3 value3]
...
[More key-values including empty buckets]
...
[keyN valueN]
<end_of_hash_table>
[Property Block]
[Footer] (fixed size; starts at file_size - sizeof(Footer))
<end_of_file>
必须要注释的是优化的hash计算,我们将哈希表中的桶数固定为二的幂。因此,文件大小只能是一组固定的值,因此文件大小可能比options.target_file_size_base
和 options.target_file_size_multiplier乘积
的值小得多。
性能结果
我们写入100M 条记录到8个文件,key length=8B value length=4B;我们选择默认的Cuckoo hash参数:hash_table_ratio=0.9, max_search_depth=100, cuckoo_block_size=5
.
测试命令
./db_bench --disable_seek_compaction=1 --statistics=1 --histogram=1 --cache_size=1048576 --bloom_bits=10 --cache_numshardbits=4 --open_files=500000 --verify_checksum=1 --write_buffer_size=1073741824 --max_write_buffer_number=2 --level0_slowdown_writes_trigger=16 --level0_stop_writes_trigger=24 --delete_obsolete_files_period_micros=300000000 --max_grandparent_overlap_factor=10 --stats_per_interval=1 --stats_interval=10000000 --compression_type=none --compression_ratio=1 --memtablerep=vector --sync=0 --disable_data_sync=1 --key_size=8 --value_size=4 --num_levels=7 --threads=1 --mmap_read=1 --mmap_write=0 --max_bytes_for_level_base=4294967296 --target_file_size_base=201327616 --level0_file_num_compaction_trigger=10 --max_background_compactions=20 --use_existing_db=0 --disable_wal=1 --db=/mnt/tmp/cuckoo/2M100 --use_cuckoo_table=1 --use_uint64_comparator --benchmarks=filluniquerandom,compact --cuckoo_hash_ratio=0.9 --num=100000000
随机读:
readrandom : 0.371 micros/op 2698931 ops/sec; (809679999 of 809679999 found)
./db_bench --stats_interval=10000000 --open_files=-1 --key_size=8 --value_size=4 --num_levels=7 --threads=1 --mmap_read=1 --mmap_write=0 --use_existing_db=1 --disable_wal=1 --db=/mnt/tmp/cuckoo/2M100 --use_cuckoo_table=1 --benchmarks=readrandom --num=100000000 --readonly --use_uint64_comparator --duration=300
Multi Random Read:
multireadrandom : 0.278 micros/op 3601345 ops/sec; (1080449950 of 1080449950 found)
./db_bench --stats_interval=10000000 --open_files=-1 --key_size=8 --value_size=4 --num_levels=7 --threads=1 --mmap_read=1 --mmap_write=0 --use_existing_db=1 --disable_wal=1 --db=/mnt/tmp/cuckoo/2M100 --use_cuckoo_table=1 --benchmarks=multireadrandom --num=10000000 --duration=300 --readonly --batch_size=50 --use_uint64_comparator
源码分析
CuckooHash——根据计算hash值
Cuckoo Filter:设计与实现 | 酷 壳 - CoolShellhttps://coolshell.cn/articles/17225.html