2012-10-08 86 views
2

我在通過C#使用MongoDB聚合框架時遇到了性能問題。在C#中執行時,通過Mongo Shell快速運行的聚合需要永久性。通過C#使用MongoDB聚合框架時的性能問題

試圖調用通過C#的框架之前,我通過蒙戈shell中執行下列聚合檢查一切正常:

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

在< 500ms的執行的腳本和返回預期的大約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 shell運行。感覺像通過C#運行聚合會導致MongoDB錯過索引,並且它正在對集合中所有大約600萬個文檔執行表掃描。

任何想法?

更新:日誌

得益於Cirrus的建議,我啓用了詳細日誌記錄,然後用尾巴來獲取查詢。和他們是不同的!所以我認爲我的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 } } } ] } 

下聯丟失,我想因爲查詢未完成。

這裏再次提供日誌以方便比較。腳本到了,C#down:

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 } } } ] } 
+2

你知道你已經使用ActionDate在C#版C#LINQ提供MongoDB的聚合框架,而不是到Action版本的shell版本吧?除此之外,在配置文件中使用「verbose = true」開啓日誌記錄,並使用tail.exe日誌文件。它會顯示它在數據庫上執行的實際查詢。 – cirrus

+0

其實不行!我發誓我三重檢查了一些事情,但我仍然設法想念它。但不幸的是執行速度仍然很慢。該索引包含ActionName,CustomerAppId和ActionDate。使用AppId&Date或AppId&ActionName從shell進行分組速度很快,但從代碼來看,它們都很慢。感謝提供詳細的建議。我得檢查一下。 –

+0

不要忘記你可以upvote有用的意見,以及答案; – cirrus

回答

4

原來我正在格式化pipeline對象,不正確。 $ match和$ group都必須位於其自己的BsonDocument實例中。下面的代碼似乎產生正確的輸出:

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 
                } 
               } 
           } 
          } 
        } 
       } 
     }; 

我真的希望有一個在管道:)

+1

我也可以。我懷疑冗長可能會有所幫助,因爲我最近一直在那裏。駕駛員缺乏總體支持是不方便的。它更脆弱,意味着醜陋的參數替換。有一張票https://jira.mongodb.org/browse/CSHARP-383用於linq的聚合支持,但由於可以使用上面使用的方法,因此它已關閉。就我個人而言,我並不認爲這是令人滿意的,你也不會聽到這種聲音。如果你閱讀評論,我不明白爲什麼它被關閉。它需要重新開放恕我直言。 – cirrus

+0

我最終編寫了一個教程,其中顯示了使用C#使用聚合框架的示例。希望人們可以複製並粘貼這些文件並使用它們來構建自己的管道。 http://mikaelkoskinen.net/post/mongodb-aggregation-framework-examples-c-csharp.aspx –

+0

@cirrus有一個開放的問題來支持linq到聚合框架在這裏看到問題https://jira.mongodb.org /瀏覽/ CSHARP-601?JQL =項目%20%3D%20CSHARP%20於是%20resolution%20%3D%20Unresolved%20ORDER%20BY%20assignee%20ASC%2C%20priority%20DESC – Dreamwalker