根据 Riak 的文档(使用 Python 绑定),get_keys()非常昂贵且不适合生产。我的问题是一个非常简单的地图查询是否合适。例如,仅使用具有以下功能的地图阶段:
function(v) { return [v.key]; }
这会比 get_keys() 表现更好吗?为什么 Riak 不提供这个实现而不是当前版本的 get_keys()?有没有更好的方法列出存储桶的键?
该函数在后端get_keys()
调用,并且被认为是一项昂贵的操作,因为它会执行密钥空间的完整扫描。list_keys
根据您的 Riak 后端,这还可能涉及对存储在磁盘上的数据进行全面扫描(想到 InnoStore)。默认存储后端 (Bitcask) 将所有密钥存储在内存中,因此性能应该不是什么大问题。
另一个原因list_keys
被认为是昂贵的,因为它以前是一个阻塞操作,因为它涉及 Basho 开发人员所说的对所有键的“折叠”。list_keys
现在使用存储桶的快照(而不是读取实时密钥空间),这也使其成为更轻量级的操作。
升级到 Riak 1.0 使这变得更容易。如果您使用 LevelDB 后端,您可以在存储桶上启用二级索引并使用$key
索引(由 Riak 自动提供)来获取存储桶中所有键的列表。
至于为什么 Riak 没有提供这样的更好实现:询问功能的用途。在 RDBMS 中,获取表的所有主键涉及全表扫描。在 Riak 中,从存储桶中获取所有密钥需要扫描每个节点中的所有数据,然后将密钥名称发送回原始节点,组合该数据,然后将其发送到调用客户端。由于 Riak 的分布式、无序状态,无论您如何切片,此操作都是昂贵的。正如我上面所概述的,有一些方法可以让它变得更好。
如果您使用的是 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。这就是为什么您需要控制您需要列出密钥的存储桶的密钥。