2013-08-06 21 views
3

我正在開發一個小應用程序,它將存儲有關用戶,帳戶和交易的信息。用戶將擁有多個賬戶(可能少於10個),賬戶將有很多交易(可能是1000)。閱讀它似乎表明,嵌入如下是要走的路的文檔...嵌入或引用Mongodb

{ 
"username": "joe", 
"accounts": [ 
    { 
     "name": "account1", 
     "transactions": [ 
      { 
       "date": "2013-08-06", 
       "desc": "transaction1", 
       "amount": "123.45" 
      }, 
      { 
       "date": "2013-08-07", 
       "desc": "transaction2", 
       "amount": "123.45" 
      }, 
      { 
       "date": "2013-08-08", 
       "desc": "transaction3", 
       "amount": "123.45" 
      } 
     ] 
    }, 
    { 
     "name": "account2", 
     "transactions": [ 
      { 
       "date": "2013-08-06", 
       "desc": "transaction1", 
       "amount": "123.45" 
      }, 
      { 
       "date": "2013-08-07", 
       "desc": "transaction2", 
       "amount": "123.45" 
      }, 
      { 
       "date": "2013-08-08", 
       "desc": "transaction3", 
       "amount": "123.45" 
      } 
     ] 
    } 
] 
} 

我的問題是......由於交易的名單將增長到將數據變成碎片的文件中或許1000的並減慢性能。我會更好地擁有一個文檔來存儲用戶和賬戶不會增長得那麼大,然後是一個單獨的集合來存儲參考賬戶的交易。或者,還有更好的方法?

回答

5

這不是要走的路。你有很多交易,你不知道你會得到多少。相反的,你應該保存他們喜歡的:

{ 
    "username": "joe", 
    "name": "account1", 
    "date": "2013-08-06", 
    "desc": "transaction1", 
    "amount": "123.45" 
}, 
{ 
    "username": "joe", 
    "name": "account1", 
    "date": "2013-08-07", 
    "desc": "transaction2", 
    "amount": "123.45" 
}, 
{ 
    "username": "joe", 
    "name": "account1", 
    "date": "2013-08-08", 
    "desc": "transaction3", 
    "amount": "123.45" 
}, 
{ 
    "username": "joe", 
    "name": "account2", 
    "date": "2013-08-06", 
    "desc": "transaction1", 
    "amount": "123.45" 
}, 
{ 
    "username": "joe", 
    "name": "account2", 
    "date": "2013-08-07", 
    "desc": "transaction2", 
    "amount": "123.45" 
}, 
{ 
    "username": "joe", 
    "name": "account2", 
    "date": "2013-08-08", 
    "desc": "transaction3", 
    "amount": "123.45" 
} 

在NoSQL的數據庫MongoDB的一樣你不應該害怕denormalise。正如你注意到的,我甚至沒有爲用戶分別收集一個集合。如果您的用戶有更多信息需要在每次交易時顯示,您可能還需要考慮包含這些信息。

如果你需要搜索,或者通過選擇,任意字段,然後不要忘記創建索引,例如:

// look up all transactions for an account 
db.transactions.ensureIndex({ username: 1, name: 1 }); 

和:

// look up all transactions for "2013-08-06" 
db.transactions.ensureIndex({ date: 1 }); 

等。

複製數據有很多優點。通過上面的模式,您可以擁有儘可能多的事務,並且您永遠不會因爲文檔永遠不會改變而導致任何碎片 - 只能添加到它們中。這也提高了寫入性能,並且使其他查詢更容易。

替代

另一種可能是存儲的用戶名/名稱的集合中,只使用它的ID與交易:

帳戶:

{ 
    "username": "joe", 
    "name": "account1", 
    "account_id": 42, 
} 

交易:

{ 
    "account_id": 42, 
    "date": "2013-08-06", 
    "desc": "transaction1", 
    "amount": "123.45" 
}, 

這會創建較小的事務處理文檔,但這意味着您必須執行兩個查詢以獲取用戶信息。

0

您應該考慮使用ensureIndex()函數創建索引,它應該降低性能問題的風險。 您越早添加這些,您就越能理解收藏應該如何構建。 使用蒙戈太長的數據是我沒去過,但是我還沒有遇到任何問題(反正目前還沒有)來零散

編輯如果你打算用這個多目標承諾,蒙戈沒有按」支持回滾。您需要使用64位版本來支持日記功能,並使交易持久。

1

由於交易清單在文檔內可能增長到1000個字節,數據會變得分散並且性能下降。

幾乎可以肯定的是,事實上,如果在一段時間內交易只達到千次而不是單個賬戶的10萬次,我會感到驚訝。

隨着時間的推移,您將從不斷增長的文檔中看到的碎片級別增加,如果沒有用完根文檔空間(即16meg),最終會出現嚴重問題。事實上,考慮到您將一個人的所有帳戶存儲在一個文檔下,我會說您在大約2年的時間內填寫文檔的風險很高。

我會引用這種關係。

1

我會將交易分成不同的集合。似乎用戶和事務之間的數據和更新模式有很大不同。如果交易不斷添加到用戶,並導致它一直增長,它將在mongo文件中移動很多。所以是的,它會帶來性能影響(碎片化,更多IO,更多mongo工作)。 此外,數組操作性能有時會在文檔中的大數組上解聚,因此在數組中保存1000個對象可能不是一個好主意(取決於您使用它做什麼)。