1

我有一个包含大约 900,000 条记录的存储桶。这些记录中的大多数在二级索引中的状态为 PERSISTED。我想检索所有标记为 PERSISTED 的文档的所有 base_url 以及属于每个 base_url 的文档数。

这是查询:

curl -X POST -H "content-type: application/json" \
    http://localhost:8098/mapred?chunked=true --data @-<<\EOF
{
    "timeout":600000,
    "inputs":{
       "bucket":"test-bucket",
       "index":"status_bin",
       "key":"PERSISTED"
    },
    "query":[{
        "map":{
            "language":"javascript",
            "source":"
                function(value, keyData, arg) {
                    var data = Riak.mapValuesJson(value)[0];
                    var obj = {};
                    obj[data.base_url] = 1;
                    return [obj];
                }
            "
        }
    },
    {
        "reduce":{
            "language":"javascript",
            "source":"
                function(values, arg){ 
                    return [values.reduce(
                        function(acc, item){ 
                            for(var base_url in item){
                                if(acc[base_url]) {
                                    acc[base_url] = acc[base_url] + 1
                                } else {
                                    acc[base_url] = item[base_url];
                                }
                            }
                            return acc;
                        })
                    ];
                }
            "
        }
    }]

EOF

这是 10 分钟后超时。

我在具有 20Gb 内存的 16 核 3Ghz AWS 节点上。

有什么我可能做错了,无论是我的配置还是上面的查询?

可能需要这么长时间吗?

为了给出观点,MySQL中的等效查询看起来像这样

SELECT COUNT(*), catalog FROM urls GROUP BY catalog;

我还没有尝试过,但我怀疑在 MySQL 中,来自上述查询的超过 900,000 条记录的结果集需要几秒钟。我不想将 Riak 与 MySQL 进行比较,因为我意识到它们非常不同,但我想知道我至少如何在 10 分钟内执行上述查询。

谢谢!

4

1 回答 1

1

Riak 中的 JavaScript MapReduce 作业使用 SpiderMonkey JavaScript VM 池,重要的是根据您的使用模式调整此池的大小,以避免或至少减少争用。池的大小通过 app.config 文件中的“map_js_vm_count”和“reduce_js_vm_count”参数指定。

由于您在单个节点上运行并且只有一个映射阶段,我建议您将“map_js_vm_count”参数设置为环的大小,默认情况下为 64。可以在此处找到更深入的描述。

虽然 map 阶段处理很容易扩展并且是并行完成的,但中央 reduce 阶段很容易成为瓶颈,因为它在单个节点上递归运行。这可以通过将参数传递给 map 阶段来解决,以启用 pre-reduce 并增加 reduce 阶段的批量大小,如此处所述。启用 pre-reduce 将允许 reduce 阶段的第一次迭代并行运行,这很可能会提高您的工作效率。但是,您需要通过大幅增加“reduce_js_vm_count”参数来增加可用于减少阶段函数的 VM 数量。

如果同时运行大型 MapReduce 作业,则支持此操作所需的 JavaScript VM 数量可能会变得非常大。通常鼓励将 map 和 reduce 阶段函数转换为 Erlang,因为它确实消除了 JS VM 争用,并且由于与 VM 相关的开销更少,性能也更好。对于您打算定期运行的 MapReduce 作业,始终建议这样做。

于 2013-04-11T02:39:23.110 回答