1

約 900,000 レコードのバケットがあります。これらのレコードの大部分は、セカンダリ インデックスで PERSISTED のステータスを持っています。すべての base_url と、PERSISTED とマークされたすべてのドキュメントの各 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(*), カタログ FROM urls GROUP BY カタログ;

試したことはありませんが、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」パラメーターで指定されます。

単一のノードで実行しており、マップ フェーズが 1 つしかないため、「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 に答える