我正在构建一个地图图块存储,并且需要存储15亿~3KB的blob。其中95%以上是重复的。是否有NoSQL存储引擎可以避免存储相同的值?
我当然可以实现双重参考,例如键 - >散列>值。如果hash是MD5,16字节的哈希值仅使用24GB forhashess,加上每项开销,这可能更多。还有什么更有效的吗?
谢谢!
答案 0 :(得分:2)
双重引用是可行的方法 - 您可以通过不存储重复数据来节省4-5TB之间的数据,因此存储24GB的哈希值是值得的。此外,您只需要在插入和更新时计算哈希函数,而不是在查找或删除时计算哈希函数。
为了降低查找中双重引用的成本,您可以使用内存缓存(例如,内存缓存)来补充磁盘上的键值数据库。 Redis - 您可以缓存经常访问的key->hash
对以避免在主数据库上进行两次查找,或者您可以直接将整个key->hash->blob
结构存储在缓存中(前者更简单)实现是因为你不需要从主数据库中复制双重引用,而后者只有一小部分blob活动时更有意义。
您可以使用更简单/更小的哈希 - probability of a hash collision为1 - e^(-k^2 / 2N)
,其中k
是哈希值的数量,N
是大小哈希,所以一个好的64位哈希有大约12%的机会发生冲突,一个好的128位哈希有一个无限小的碰撞机会。 MurmurHash具有64位和128位版本,因此您可以在两者之间进行实验,并且它比MD5更快,主要是因为MD5是加密哈希函数,而Murmur没有增加的费用/加密安全的复杂性(我假设您并不关心任何试图故意产生哈希冲突的人或类似的东西)。一些键值存储也使得设计容易碰撞变得相对容易,例如,您可以将哈希存储在Riak Map中,并带有一个标志,指示该哈希值是否存在任何冲突 - 如果为false然后简单地返回blob,否则返回选项2(例如,索引blob变为两个blob,其中哈希冲突被压缩/焦油化,以及CSV对应于哪个blob;即使使用64位哈希此代码路径不会经常运用,因此实现简单性可能胜过性能);问题是减少的内存/散列开销是否弥补了碰撞容限的复杂性。