2

C#でMongoDB Aggregation Frameworkを使用すると、パフォーマンスの問題が発生します。Mongoシェルを介して高速に動作する集計は、C#で実行すると永遠にかかります。

C#を介してフレームワークを呼び出そうとする前に、Mongoシェルを介して次の集計を実行し、すべてが機能することを確認しました。

db.runCommand(
    {
        aggregate: "actions", 
        pipeline : 
        [
            { $match : { CustomerAppId : "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName : "install"}}, 
            { $group : { _id : { CustomerAppId:"$CustomerAppId",ActionDate:"$ActionDate" }, count : { $sum : 1 } }}
        ]
    });

スクリプトは500ミリ秒未満で実行され、予想される約200の結果を返します(CustomerAppIdはデータベース内の文字列として定義されています。集約フレームワークでGUIDを使用することはできません)。

次に、同じスクリプトをC#に移植しました。

var pipeline = new BsonArray
        {
            new BsonDocument
                {
                    {
                        "$match", 
                        new BsonDocument
                            {
                                {"CustomerAppId", "f5357224-b1a8-4f1a-8ea2-a06a00ca597a"},
                                {"ActionName", "install"}
                            }
                    },
                    { "$group", 
                        new BsonDocument
                            {
                                { "_id", new BsonDocument
                                             {
                                                 {
                                                     "CustomerAppId","$CustomerAppId"
                                                 },
                                                 {
                                                     "ActionName","$ActionName"
                                                 }
                                             } 

                                },
                                {
                                    "Count", new BsonDocument
                                                 {
                                                     {
                                                         "$sum", 1
                                                     }
                                                 }
                                }
                            } 
                  }
            }
        };


var command = new CommandDocument
{
    { "aggregate", "actions" },
    { "pipeline", pipeline }
};

(C#で集計を記述する簡単な方法があるかどうか教えてください:))

私はこのように実行しています:

var result = db.RunCommand(command);

問題は、サーバーを強制終了することです。CPUとメモリの使用量が大幅に増加します。db.currentOp()を確認すると、集約操作を確認できますが、最終的にはdb.killOp(1281546)を使用してそれを強制終了する必要があります。

"opid" : 1281546,
"active" : true,
"secs_running" : 294,
"op" : "query",
"ns" : "database.actions",
"query" : {
        "aggregate" : "actions",
        "pipeline" : [
                {
                        "$match" : {
                                "CustomerAppId" : "f5357224-b1a8-4f1a-8ea2-a06a00ca597a",
                                "ActionName" : "install"
                        },
                        "$group" : {
                                "_id" : {
                                        "CustomerAppId" : "$CustomerAppId",
                                        "ActionName" : "$ActionName"
                                },
                                "Count" : {
                                        "$sum" : 1
                                }
                        }
                }
        ]
},

私には、操作は完全に正常に見え、mongoシェルから直接実行するスクリプトに似ています。C#を介して集計を実行すると、MongoDBがインデックスを見逃し、コレクション内の約600万のドキュメントすべてに対してテーブルスキャンを実行しているように感じます。

何か案は?

更新:ログ

cirrusの提案のおかげで、詳細ログを有効にしてから、tailを使用してクエリを取得しました。そして、それらは異なります!だから私は私のC#ポートに何か問題があると思います。クエリを正しくフォーマットする方法について何かアイデアはありますか?

シェルを介して実行されたときのクエリ:

Mon Oct  8 15:00:13 [conn1] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] }
Mon Oct  8 15:00:13 [conn1] command database.$cmd command: { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] } ntoreturn:1 keyUpdates:0 locks(micros) r:27944 reslen:12705 29ms

そして、C#を介して実行されたときのクエリ:

Mon Oct  8 15:00:16 [conn8] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" }, $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, Count: { $sum: 1 } } } ] }

2行目が欠落しているのは、クエリが終了していないためだと思います。

比較しやすいように、ここでもログを示します。スクリプトはアップ、C#はダウン:

Mon Oct  8 15:00:13 [conn1] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] }
Mon Oct  8 15:00:16 [conn8] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" }, $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, Count: { $sum: 1 } } } ] }
4

1 に答える 1

4

パイプラインオブジェクトを正しくフォーマットしていなかったことがわかりました。$matchと$groupの両方が独自のBsonDocument-instancesにある必要があります。次のコードは正しい出力を生成するようです。

var pipeline = new BsonArray
        {
            new BsonDocument
                {
                    {
                        "$match", 
                        new BsonDocument
                            {
                                {"CustomerAppId", "f5357224-b1a8-4f1a-8ea2-a06a00ca597a"},
                                {"ActionName", "install"}
                            }
                    }
            },
            new BsonDocument
                {
                    { "$group", 
                        new BsonDocument
                            {
                                { "_id", new BsonDocument
                                             {
                                                 {
                                                     "CustomerAppId","$CustomerAppId"
                                                 },
                                                 {
                                                     "ActionDate","$ActionDate"
                                                 }
                                             } 

                                },
                                {
                                    "Count", new BsonDocument
                                                 {
                                                     {
                                                         "$sum", 1
                                                     }
                                                 }
                                }
                            } 
                  }
                }
        };

パイプラインにMongoDBAggregationFramework用のC#Linqプロバイダーがあることを本当に望んでいます:)

于 2012-10-08T15:16:23.733 に答える