2012-01-30 71 views
4

我目前使用的是mongodb,而且我發現查詢性能很差(可能需要幾秒鐘)。 該方案是如下:mongodb性能不佳

我有結構的文件:

{_id:"xxx", userId:"yyy", a:1 ,b:2, counter:1}  

在測試中:

"userId" value could be {1..200,000} 
"a" values could be {1..30} 
"b" values could be {1} 

因此我maximun大小的採集將是600萬 目前有爲此集合定義的兩個索引:default _id and useId

業務邏輯查詢所有你ser條目,然後通過遞增計數器更新一個特定值(查詢更新由「_id」寫入)。另外,如果這是一個新的實體,則存在插入查詢。

我與蒙戈1.8.2運行在Ubuntu上配備8G的RAM

我有一個主次級複製(所有蒙戈與本地磁盤存儲,並與Tomcat服務器一個子網中運行)。當然,所有的讀取都是次要的並寫入主文件。 我沒有測試分片,因爲我認爲600萬不是一個巨大的集合,不是嗎?

另外我運行jmetter測試,每次用不同的userIds生成500個線程請求。

當我運行mongostat時,我發現在大約5-10分鐘的加載後,鎖定的百分比非常高(約70%) 我看到qw(寫入隊列)是500(作爲我的開放連接數) 當我停止服務器需要mongo約10-20分鐘來完成所有排隊的任務

我也跑了db.serverStatus()並解釋和結果看起來不錯。 當我運行db.currentOp()我看到正在等待'寫'鎖定的查詢 我不能有currentOp的輸出文件來完全分析它,因爲我從命令行執行查詢,只有窗口緩衝區大小。但是從那裏我看到很多正在等待寫鎖的更新(通過_id)。

我會感激任何想法。

還有一兩件事:因爲每個查詢pottentially將帶來30個文件,我認爲有可能是不同moddeling如下:

{_id:"xxx", userId:"123", bs: [{b:1, cs[{c:1, cnt:1}, {c:2, cnt:1}}, {{b:2 cs: [{c:1, cnt:1}]}}] 

但是當我tryed這個造型,我不能增加櫃檯,我根本沒找不到這樣做的正確方法。我能做的插入和推芽不能更新 以下查詢:

db.coll.update({userId:"123", "bs.b":1, "bs.cs.c":1}, {"bs.cs.cnt" : {$inc : 1}) 

我對在查詢

我敢現在堆疊非法「點」的錯誤。等待一些好的想法

非常感謝
朱莉婭

回答

5

MongoDB有一個global write lock。這意味着您的更新只能一次進行。

db.serverStatus()命令可以幫助您診斷全局寫入鎖的問題。

這裏有一些事情你可以嘗試:

1)請確保您使用的MongoDB 2.0。它比舊版本具有更好的併發性。 2.2將具有更好的併發性。

2)排隊你的寫入,使它們是異步的,並使用單個線程執行它們。這可能有助於併發性,因爲通常只有一個線程會一次嘗試使用全局寫入鎖定。 3)如果你使用最新版本,並且你不能讓你的單線程寫入,那麼考慮分片。分片不僅僅是規模;對於寫入併發至少同樣重要。如果分片,那麼每個片段將在其自己的進程中運行,並擁有自己的全局寫入鎖定。這將允許整個系統處理更多的寫入。

+0

非常感謝,我想如果我使用通過_id更新它們可以針對不同的ID同時發生。我使用1.8我會嘗試2.你知道它是否已經成熟了嗎? – Julias 2012-01-30 13:36:54

+1

2.0已經在一段時間之前發佈(2011年下半年,如果我沒有記錯的話)。目前的產品版本是2.0.2。在我看來,它是安全的生產使用。 – 2012-01-30 14:34:16

1

對於更新檢查出positional operator

db.coll.update({userId:"123", "bs.b":1, "bs.cs.c":1}, {"bs.$.cs.$.cnt" : {$inc : 1}) 

理解查詢使用explain的成本,並確保查詢是有效的。

+0

謝謝,我會嘗試更新。我用解釋,它表明我很好的結果。因爲我在userId上有一個索引,而且b的數目最多爲30.它顯示我爲nscaned 30.我只是不明白爲什麼我有這麼多的排隊更新導致非常延遲的高查詢 – Julias 2012-01-30 13:04:06