MongoDB的數據結構很靈活,不強制要求數據結構.但是通常一個集合內部使用相同的結構.
數據建模的關鍵是平衡應用的需求和數據庫執行和數據檢索模型的性能.設計數據模型時,要考慮數據的使用情況和數據自身的結構
設計MongoDB應用的數據模型的關鍵在於文檔結構和應用程序如何表示數據之間的關系,這有兩種工具允許應用程序來表示這些關系:引用和嵌入型文檔.
類似關系型數據庫中的外鍵的引用,通常不同的集合中互相引用_id字段
某個字段的值為BSON或者某個字段值為數組,數組中的每個值為BSON
MongoDB在文檔級別的寫操作是原子性的,沒有任何單個修改多條文檔,或者多個集合的操作是原子性的.包含嵌入型數據的非標准化數據將其所表示的實體的所有的相關數據在單個文檔中保存,這使得對這個實體的操作變為對這個文檔的原子性操作.標准化數據的過程將數據跨多個集合存儲,這使得每次對實體的修改需要多次寫操作,並且多次寫操作不是原子性的.
然而,方便原子操作的結構也許會限制應用程序使用數據或者限制修改應用程序.
一些更新操作,比如向數組中追加元素或者向文檔中添加字段,都會導致文檔大小增加.
如果文檔大小超過了分配給它的空間,MongoDB將重新在硬盤上為其分配空間.這種增長將影響你選擇使用標准化數據還是非標准化數據
當設計數據模型的時候,考慮應用程序將怎樣使用你的數據庫.比如說:如果你的應用程序只是使用最近插入的文檔,考慮使用Capped Collections,或者你的應用程序主要是讀取操作,為常用的查詢添加索引來改善性能.
高效的數據模型迎合應用程序的需求.文檔結構考慮的關鍵因素是使用嵌入型文檔還是使用引用
嵌入型文檔允許一個文檔中保存多條相關信息應用程序可以執行更少的查詢和更新操作.
以下情況使用嵌入型文檔:
1.實體間有"包含"的關系
2.實體間有一對多的關系.在這種關系中,多的一方總是在一的一方作為上下文或者作為父文檔的時候出現.
嵌入型文檔讀操作性能較好,單一數據庫的時候檢索數據快.update相關數據的操作是原子性的.
缺點:嵌入型文檔導致文檔創建後大小的增長.進一步說,文檔必須小於BSON文檔的最大值限制
與嵌入型文檔進行交互,需要使用"."操作符來訪問嵌入型文檔
標准化數據使用引用來描述文檔間的關系
以下情況使用標准化數據模型:
1.嵌入型文檔模型導致數據重復的同時,查詢性能優勢不能彌補數據重復帶來的不足的時候
2.用以表示更加復雜的多對多的關系
3.用以建模多層的數據集
引用比嵌入更加靈活.然而隨之而來的是應用程序需要查詢並解析相關的引用.換句話說,標准化數據模型會導致程序和MongoDB之間更多的通信.
需要權衡考慮數據自身和數據庫.
數組的push操作,和增加新的 字段將會導致文檔大小的增長.超過文檔已分配的空間大小的時候,MongoDB將會為其重新分配空間,這將導致比原地更新花費更多的時間,同時也會導致碎片化存儲.雖然MongoDB自動會在文檔之間添加空隙以減少類似的重新分配,建立模型的時候需要盡可能的避免文檔增長
上面已有介紹,略
MongoDB使用Sharding技術來提供水平的縮放.這些集群支持大數據集的開發和高吞吐量的操作.Sharding允許用戶將一個數據庫內的一個集合,通過mongod的實例或者shards的標號,分散到多個集合文檔中
使用索引來改善查詢性能.在某些字段上建立索引,通常是在這些字段上的查詢返回排序的結果的時候.MongoDB自動在_id字段上建立索引.
建立索引時要考慮以下內容:
1.每個索引需要至少8KB的空間
2.建立索引會對寫操作有負面影響,對於寫操作很多的集合來說,索引的所花費的代價很高因為每次插入的操作都必須更新所有的索引
3.對於讀操作較多的集合來說,索引通常是有益的.索引不影響沒有建立索引的讀操作.
4.當激活的時候,每個索引都會消耗硬盤和內存空間.這些開銷對於容量計劃,特別是超過工作集的大小的考慮,是極為關鍵的,應該追蹤的.
在某些情況下,需要選擇將相關的信息存儲字多個集合中而不是一個集合中,比如不同的log內容存儲在不同的log集合中
通常大量的集合沒有性能的減弱而是性能的優化.不同的集合對於高吞吐量的批處理進程是非常重要的.
當使用有大量集合的數據模型的時候,考慮以下內容:
1.每個集合至少需要即k空間
2.每個索引,包括_id上的索引,需要至少8KB空間
3.對於數據庫來說,一個,命名空間文件存儲著該數據庫所有的元數據,每個索引和集合在這個命名空間文件中有其自己的入口.
4.MongoDB對於命名空間的數量有限制.你也許想知道當前的命名空間數,以決定數據庫還可以支持多少額外的 命名空間,查詢當前命名空間的數量,在mongo的shell中運行:db.system.namespaces.count()
數據建模的時候應該考慮數據的生命周期管理.
如果你的應用程序需要使用限定時間段內的數據,考慮使用TTL屬性.
另外,如果你的應用程序僅僅使用最近插入的文檔,考慮使用Capped Collections.它提供了對於文檔的FIFO(也就是隊列式)的管理,有效的支持哪些依賴於插入順序的插入和讀取操作.
GridFS是對於超過BSON文檔大小限制16M的文檔存儲和檢索的規范.
不是將文件存儲在單個文檔中,GridFS將文件分割為多個部分,或者數據庫,將每個數據塊作為單獨的文檔進行存儲.默認的GridFS限制數據塊大小為255k.GridFS使用兩個集合來存儲文件.一個結合存儲文件的數據塊,另一個存儲文件的元數據信息.
當你查詢GridFS存儲的文件的時候,驅動,或者客戶端將重新組裝你需要的數據塊.你可以對存儲在GridFS中的文件執行多種查詢.你也可以獲取文件的某一塊的信息,這使得你可以跳到視頻或者音頻的中間部分.
GridFS不僅僅對於存儲大小超過16M的文件有用,它可以用於存儲任何你在訪問時不想將整個文件加載到內存中的文件