2014-12-02 136 views
4

我試圖從集合中獲取毫秒(<秒)的響應時間。但是,即使對於小數據量(〜200MB),它現在也需要3-5秒。我收集的這個系列產品的預期數據大約是每個碎片100GB。 我已經檢查了以下內容
- 當我在每個分片上單獨嘗試查詢時,響應時間相同。 - 檢查了性能分析輸出,我只能看到高時間鎖定的微秒和numYield。 - 在MMS圖表中找不到任何不尋常的東西。 我覺得這裏過分愚蠢的東西。任何幫助進一步分析這一點高度讚賞。下面提供分析MongoDb聚合性能

羣集我的羣集和收集細節 - 34 GB,4個芯機(AWS m2.2xlarge) 數據大小 1285 MB(每分片213 MB) 沒有記錄的6個節點= 5500000(〜每碎片1 M)

記錄樣品

{ 
    "_id" : { 
     "ItemID" : 105182, 
     "DeviceType" : 16, 
     "ItemVersionID" : 117971, 
     "Timestamp" : ISODate("2014-11-14T00:00:00Z"), 
     "RecordType" : 1 
    }, 
    "Dim1ID" : 102260, 
    "Dim2ID" : 313, 
    "Dim3ID" : 1, 
    "actionType" : { 
     "1" : 66, 
     "47" : 66, 
     "42" : 72, 
     "46" : 130 
    } 
} 

查詢

db.AggregateCollection.aggregate({ "$group" : { "_id" : { } , "type1" : { "$sum" : "$actionType.1"} , "type2" : { "$sum" : "$actionType.2"}}}) 

資料統計(從一個碎片)

"keyUpdates" : 0, 
    "numYield" : 79, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(2981456), 
      "w" : NumberLong(0) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(3756), 
      "w" : NumberLong(4) 
     } 
    }, 
    "responseLength" : 157, 
    "millis" : 3268, 
    "execStats" : { 

    }, 

UPDATE 感謝您將爲迅速作出反應。 Apreciate它。我喜歡你的新數據模型和索引。不過,恐怕不適合我目前的數據,因爲, - 記錄的99%,將有actionType.1 SOEM價值和 - 我們的查詢的99%將選擇actionType.1 上actiionType.K止跌所以指數我猜想沒什麼幫助。

正如您在#2 &#3中所建議的那樣,我們已經在使用Spark羣集進行預聚集,該羣集會上傳MongoDb。

多一點點關於我的查詢 我剛纔共享查詢只是一個樣本之一,只是用來基準性能。我的實際查詢將在Timestamp上有$匹配,在一個或多個fileds上有$ group。 典型的生產查詢將用於30天的數據。目前我的收藏只有15天的數據。我的目標是獲得亞秒級的響應時間爲30天的數據

順便說一句,我今天 做了一些更多的分析我toook碎片的轉儲和安裝在我的MacBook本地蒙戈恢復。相同的查詢僅需2秒(在AWS isntance中花了4秒鐘) 沒有意義,因爲AWS實例至少比MacBook強4倍(均爲CPU &內存) MacBook Air - http://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i5-4250U+%40+1.30GHz AWS m2.2xlarge實例 - http://www.cpubenchmark.net/cpu.php?cpu=Intel+Xeon+E5-2665+%40+2.40GHz

我懷疑碎片監守在AWS數據蒙戈實例是通過一個應用程序人口在過去15天。所以我重新將AWS mongo上的轉儲作爲單獨的集合導入。查詢這個新的收藏需要2秒,這是相當於MAcBook的速度。所以碎片化是確定的一個原因。我計劃在以後對碎片做更多的研究。 儘管對改進的perfromace進行了碎片整理,但它與我的MacBook花費相同的時間並沒有什麼意義,因爲AWS isntance功能強大4倍。 然後我們查看了CPU利用率,發現mongod實例只使用一個CPU(4箇中的一個)來執行查詢。我們現在計劃在每臺機器上安裝4個碎片來解決這個問題。如果你看到更好的方法,請告訴我。

還有一件事,我知道我的查詢必須掃描整個集合,但2秒鐘掃描~200MB的數據對我來說似乎非常高。這是預計還是我錯過了什麼?

+0

您的聚合管道正在處理集合中的每個文檔。如果它必須擊中每個文檔,它不會很快。你只是總結了幾個字段值,所以更容易做的是在插入/更新時跟蹤運行總數。 – wdberkeley 2014-12-02 08:31:48

+0

正確,但這是故意的。我只有15天的數據(〜200MB),我正在嘗試進行基準測試。 – 2014-12-03 00:54:02

回答

2

事情我想嘗試:

1)你在這使得分組很困難的方式組織數據。如果你像這樣組織文檔,你可能會得到更好的結果:

{ 
    ... 
    "actionType" : [{k:1, v:66}, {k:47, v:66}, {k:42, v:72}, {k:46, v:130}] 
} 

這將允許您創建'actionType.k'索引。然後,你可以做一個匹配該索引你的整體數據集減少到你想要的確切actionTypes此聚集,在您的查詢是:

db.action.aggregate([{$unwind: '$actionType'}, 
     {$group:{_id:'$actionType.k', t:{$sum:'$actionType.v'} } }]); 
//output 
{ "_id" : 46, "t" : 130 } 
{ "_id" : 42, "t" : 72 } 
{ "_id" : 47, "t" : 66 } 
{ "_id" : 1, "t" : 66 } 

然後ensureIndex上「actionType.k」。如果您不打算過濾所有不同的鍵值,索引將會有所幫助,具體取決於文檔中鍵的密度。如果您計劃彙總每個密鑰,那麼索引在這裏將無濟於事。

2)在cron-job/setTimeout時間表上映射和/或添加它們。此外,根據您的更新週期,以及如何準確,你需要在任何一個時間的數據,建立類似:

  • 每隔一小時過程中的所有「髒」的結果
  • 添加當前值運行總計
  • 標記爲'乾淨'

如果您只對此數據庫執行插入操作,則可以使用該功能。 3)如果關鍵值定期更新(更新而不是插入),那麼在更新日誌插入時可能會更好,因爲更新日誌插入與主集合更新同時發生。

db.changes.insert({key:44, change:2}); 
db.changes.insert({key:34, change:-2}); 

然後常規地清空'changes'集合,將這些值相加到不同的集合中。

+0

感謝Will,請查看問題的更新 – 2014-12-03 00:51:49