5

シャード クラスター上のインスタンスに対して大規模なコレクションで重複検出 mapreduce 操作を実行していmongosますが、操作に 10 分以上かかると予想されます。

m = function () {
    emit(this.fieldForDupCheck, 1);
}
r = function (k, vals) {
    return Array.sum(vals);
}
res = db.Collection.mapReduce(m, r, { out : "dups" });

これを実行すると、約 10 分の処理後に次のエラーが表示されます。

uncaught exception: map reduce failed:{
"ok" : 0,
"errmsg" : "MR post processing failed: { result: "dups", errmsg: "exception: getMore: cursor didn't exist on server, possible restart or timeout?", code: 13127, ok: 0.0 }"
}

mapReduce 呼び出しで使用してnoTimeout オプションを追加しようとし.addOption(DBQuery.Option.noTimeout)ましたが、これによりシェルで JS エラーが発生しますObject [object Object] has no method 'addOption'

実行時間の長い mapreduce 操作でカーソルのタイムアウトを回避するにはどうすればよいですか?

4

1 に答える 1

7

使用している MongoDB のリリースについて言及していませんが、解決策はここで提示されているものと似ています。Ubuntu 13.04 に付属する 2.2.4 の上でデモンストレーションを行います。

これを行う際の問題は、実際にオプションをカーソルに挿入することです。それがaddOption命の場所です:

> var cursor = db.test.find()
> cursor.addOption
function (option) {
    this._options |= option;
    return this;
}

mapReduceがどのように定義されているか見てみましょう。

> db.test.mapReduce
function (map, reduce, optionsOrOutString) {
    var c = {mapreduce:this._shortName, map:map, reduce:reduce};
    ...
    var raw = this._db.runCommand(c);
    ...
    return new MapReduceResult(this._db, raw);
}

そのため、 を介してコマンドを実行するドキュメントを作成しますrunCommand。さらに詳しく見てみましょう。

> db.runCommand
function (obj) {
    if (typeof obj == "string") {
        var n = {};
        n[obj] = 1;
        obj = n;
    }
    return this.getCollection("$cmd").findOne(obj);
}

したがって、コマンドは経由で実行されfindOneます。それを見てみましょう:

> db.test.findOne
function (query, fields, options) {
    var cursor = this._mongo.find(this._fullName, this._massageObject(query) || {}, fields, -1, 0, 0, options || this.getQueryOptions());
    if (!cursor.hasNext()) {
        return null;
    }
    var ret = cursor.next();
    ...
    return ret;
}

ああ、ここに面白いものがあります。カーソルは、パラメーターからのフラグで初期化されていますがoptions、残念ながら設定されていないため、あなたのケースには役立ちませんが、コレクションからのrunCommandで OR します。getQueryOptions()それを見てみましょう:

> db.collection.getQueryOptions
function () {
    var options = 0;
    if (this.getSlaveOk()) {
        options |= 4;
    }
    return options;
}

おっと..それはダメです。そのため、カーソルにアクセスすることも、実行されたコマンドに非ハッキング手段でクエリ オプションを挿入する方法もありません。

まあ、しかし、map reduce コマンドが実際にそのプロセスを通じてどのようにサーバーに配信されるかについて、多くのことを学びました。これは、データベース内の特定のコレクションに対してクエリが実行される単なるドキュメントです。つまり、同じクエリを作成して自分で実行できますが、必要なフラグを提供できます。

MongoDB コマンド全体を作成して結果をセットアップするという問題については説明しませんが、isMasterコマンドを使用して実際に機能することを示すだけにとどめます。

これは、フラグなしで実行されるコマンドです。

> db.getCollection("$cmd").findOne({isMaster: 1}).ismaster
true

効果の違いを確認するために、データベースとの通信を tcpdump します。ワイヤ プロトコルのドキュメントで、関連するフラグがコレクション名の直前に 32 ビット整数で存在することがわかります。そのため、ダンプの関連部分を簡単に見つけることができます。

    .                  vvvvvvvvv
    0x0040:  d407 0000 0000 0000 7465 7374 2e24 636d  ........test.$cm
    0x0050:  6400 0000 0000 ffff ffff 1700 0000 0169  d..............i

良い。コレクション名の直前にある 4 バイトがゼロになっていることがわかります。

さて、いくつかのフラグを提供しながら同じことをしましょう。上記のデバッグ セクションから、クエリ フラグを の 3 番目のオプションとして提供できることがわかったfindOneので、そうしましょう。

> db.getCollection("$cmd").findOne({isMaster: 1}, undefined, 0xBEEF).ismaster
true

そしてダンプを見てください:

    .                  vvvvvvvvv
    0x0040:  d407 0000 efbe 0000 7465 7374 2e24 636d  ........test.$cm
    0x0050:  6400 0000 0000 ffff ffff 1700 0000 0169  d..............i

ねえ、私たちのフラグは必要な場所に配信されました。また、逆になっていることもわかります。つまり、バイトはリトルエンディアンとしてエンコードされ、 docsと一致します。

つまり、フラグDBQuery.Option.noTimeoutを の 3 番目のオプションとして提供し、ドキュメントで説明されているように、 で行ったのと同様の方法でfindOnemap-reduce コマンドをハンドコーディングすると、必要なものが得られます。isMaster

于 2013-08-30T21:30:13.007 に答える