redis散列与字符串的内存成本



我做了一些实验,redis哈希似乎总是比字符串更节省空间,即使哈希包含单个字段!

import redis
rc = redis.Redis(host='127.0.0.1',port=1234)
rc.flushdb()
pipe = rc.pipeline()
for i in range(1000000):
pipe.set('stream:'+str(i)+':target',True)
f = pipe.execute()    
# uses 236 MB
rc.flushdb()
pipe = rc.pipeline()
for i in range(1000000):
pipe.hset('stream:'+str(i),'target',True)
f = pipe.execute()
# uses 170 MB
rc.flushdb()
pipe = rc.pipeline()
for i in range(500000):
pipe.set('stream:'+str(i)+':target',True)
pipe.set('stream:'+str(i)+':ws',True)
f = pipe.execute()
# uses 238 MB
rc.flushdb()
pipe = rc.pipeline()
for i in range(500000):
pipe.hset('stream:'+str(i),':target',True)
pipe.hset('stream:'+str(i),':ws',True)
f = pipe.execute()
# uses 113 MB

散列和字符串都有O(1)摊销的写/读成本。如果我不需要使用APPEND、GETBIT、SETBIT、RANGE等最花哨的操作,并且只使用纯粹的SET/GET语义,那么散列不是更可取吗?我是不是错过了什么疯狂的东西?此外,我很想知道为什么散列更节省空间。

这篇内存优化文章讨论了您提出的一些问题。

redis的建议是,如果可以将数据表示为散列,则使用散列。"小散列是在一个非常小的空间中编码的,所以你应该尽可能地使用散列来表示你的数据"。

如果redis可以将哈希打包到一个数组中,并且仍然以O(1)进行查询,则redis认为哈希很小。将数据放在连续的内存区域中也有助于提高性能,尤其是当阵列的相邻元素是在盒子上缓存行的帧内读取时。

在redis配置中,您可以找到以下设置,

# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives.
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

您需要在上述阈值的两侧重复测试。总的来说,最好让你的测试尽可能接近你的真实数据和访问模式。你的问题的前提是应该始终使用哈希,但请记住,你指望的是优化启发式,而这些启发式对你作为用户来说并不是完全透明的。

最新更新