根据Riak的文档(使用Python绑定),get_keys()非常昂贵,不适合生产。我的问题是一个非常简单的地图查询是否合适。例如,仅使用带有函数的映射阶段:
function(v) { return [v.key]; }
这会比get_keys()更好吗?为什么Riak不会使用此实现而不是当前版本的get_keys()?我是否应该更好地列出存储桶的密钥?
答案 0 :(得分:2)
get_keys()
函数在后端调用list_keys
并被认为是一项昂贵的操作,因为它执行密钥空间的完整扫描。根据您的Riak后端,这还可能涉及存储在磁盘上的数据的完整扫描(InnoStore让人想到)。默认存储后端(Bitcask)将所有密钥存储在内存中,因此性能不应该是一个问题。
另一个原因list_keys
被认为是昂贵的,因为它以前是一个阻塞操作,因为它涉及Basho开发人员所称的所有键的“折叠”。 list_keys
现在使用了存储桶的快照(而不是读取实时密钥空间),这也使得它的权重更轻。
升级到Riak 1.0后,这变得更容易了。如果您正在使用LevelDB后端,则可以在存储桶上启用辅助索引并使用$key
索引(由Riak自动提供)来获取存储桶中所有密钥的列表。
至于为什么Riak没有更好地实现这样的东西:询问功能是什么。在RDBMS中,获取表的所有主键都涉及全表扫描。在Riak中,从存储桶获取所有密钥需要扫描每个节点中的所有数据,然后将密钥名称发送回原始节点,组合该数据,然后将其发送到调用客户端。由于Riak的分布式,无序状态,无论你如何分割它,这个操作都很昂贵。如上所述,有一些方法可以让它变得更好。
答案 1 :(得分:2)
如果您使用eleveldb后端(使用LevelDB库实现),您的密钥将按排序顺序存储,因此您可以执行以下操作:
def get_bucket_keys(riak_client, bucket_name, start='0', stop='Z'):
for record_key in riak_client.index(bucket_name, '$key', start, stop).run():
yield record_key
for key in get_bucket_keys(riak.RiakClient(), 'mybucket'):
print key
使用eleveldb riak仅扫描指定范围内的所有节点。因此,如果以可以控制键范围的方式填充存储桶,则列表存储桶键可以非常符合要求。
权衡是您无法为每个节点上处理的密钥数指定LIMIT。这就是为什么你需要控制你需要键列表的桶的密钥。