2012-10-18 15 views
3

架構這個模式的一個好的mongodb分片密鑰是什麼?

{ 
     "_id" : ObjectId("5069d68700a2934015000000"), 
     "port_name" : "CL1-A", 
     "metric" : 340, 
     "port_number" : "0", 
     "datetime" : ISODate("2012-09-30T13:44:00Z"), 
     "array_serial" : "12345" 
} 

每個陣列具有128個端口,而每個文件是該度量數據的一分鐘。似乎array_serial對於分片鍵來說不是一個好的選擇,因爲基數很低,也就是說,串行12345的所有數據都必須保留在同一個分片上,而不是分成多個塊,對嗎?

這似乎是port_number將允許適度的基數,但它會失敗查詢隔離,爲多個端口同一陣列上的一個單一的查詢將跨越多個碎片。我預計用戶不需要一次查詢超過4-8個端口。

答案是一個組合嗎?我應該使用一段日期時間,比如月份還是星期?

回答

7

關於數組序列,是的,這是正確的。

如果您使用「port_number」,它將具有足夠高的基數,並且意味着具有相同「port_number」的所有文檔將駐留在同一個塊中,但是如果查詢到達某個範圍的端口,會打多個碎片。

正如你所猜測的,選擇正確的分片鍵是非常重要和困難的。 「完美」片鍵滿足三個相互排斥的目標:

  • 寫操作應在碎片均勻分佈
  • 單個文檔的
  • 查詢應在碎片均勻分佈
  • 範圍查詢和排序應該是有效的,這意味着序列中的元素應該全部位於相同的分片上。

的原因之一,以避免連續碎片關鍵是,它會創建插入熱點:在任何特定時間的單個碎片將採取所有的插入負載(這是很好的查詢隔離而不是性能,最終 - 因此_id和「datetime」不是很好的選擇)。我可能會去找一個複合分片鍵。有關於這一主題在谷歌集團的一些良好的討論:

如果你選擇像{array_serial:1,日期時間:1}然後「array_serial」中的數據將被打破根據需要分成許多塊(基於日期時間),並分佈在各個服務器上。使用完整的「數據時間」值。

「array_serial」是如何決定的?什麼是價值的範圍?我假設port_name更改爲port_number更改?根據你所說的,我可能會爲{port_number:1,datetime:1}去,這並不完美,但並不壞。

這是您的最佳選擇嗎?這實際上取決於使用信息。

  • 什麼是您最常見的查詢?

如果你主要是在特定的端口號範圍內查詢特定的名字,那麼這可能是你最好的鑰匙。

另一方面,如果您將主要根據日期時間執行所有「名稱」的查詢,而不管端口號如何,那麼您將每次都進行分散/收集查詢,這會降低整體性能的羣集。

此外,問問自己

  • 一個碎片能處理所有的插件?

  • 範圍查詢性能對你來說真的很重要嗎?

根據你的問題,我猜你已經閱讀choosing a shard key :)

鏈接下面是選擇一個好的片鍵,可以幫助你一些進一步的討論:

相關問題