1. 程式人生 > >MongoDB數據模型和索引學習總結

MongoDB數據模型和索引學習總結

-c 指定 explain creat 生效 上下 通信協議 必須 數據類型

MongoDB數據模型和索引學習總結

1. MongoDB數據模型:

  • MongoDB數據存儲結構:
    MongoDB針對文檔(大文件採用GridFS協議)採用BSON(binary json,採用二進制編碼)數據格式來存儲和交換數據。Bson吸收了JSON schema-less的特點,存儲結構松散,不須要像RDB(關系數據)那樣事先定義數據存儲的元數據結構。另外添加了多種數據類型的支持和優化,使讀寫更加高效。


    (1) BSON 支持的數據類型:

    Double、String、Object、Array、Binary Data、Undefined、Object id、Boolean、Date、Null、Regular Expression、JavaScript、Symbol、JavaScript(with scope)、32-bit integer、Timestamp、64-bitInteger、Min key、Max key
    

    (2) BSON 在表現形式例如以下:

    { "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1),"name":"steven"}
    

    (3) BSON 是MongoDB中的通信協議和數據存儲格式: 在MongoDB中client和服務端通信採用的是BSON的文檔格式。比如查詢一段數據。須要這樣寫:

    db.steven.find({"name":"steven"})
    

    更新一段數據須要這樣寫:

    db.steven.update({"name":"steven"},{$set:{"name":"jianying"}})
    

    刪除一段數據須要這樣寫:

    db.steven.remove({"name":"steven"})
    

    總之MongoDB中針對文檔的CRUD的RPC通信格式均支持採用了BSON的數據格式。而且其存儲格式也採用了BSON的格式類似:

    { "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1),"name":"steven"}
    

    (4) BSON數據格式的編碼:
    BSON的String類型均採用UTF-8編碼。當中KV結構中 K值 和 字符串類型的V值,均採用UTF-8格式編碼。假設使用的是其它格式則須要轉碼。而且針對K 值能夠採用除下面要求外的隨意UTF-8字符:

    a.鍵不能含有\o(空字符)
    b.$和.有特殊的含義,僅僅有在特定環境下採用使用
    c.下面劃線"_"開頭的鍵是保留的(不是嚴格要求的)
    

    而其他值類型的編碼則依照詳細數據類型的內置協議編碼。

    MongoDB在數據模型的組織方式上,支持文檔的引用和嵌套。詳細介紹例如以下。

  • 數據模型設計模式 - 引用 和 嵌套:
    以引用的方式存儲數據是一種MongoDB組織數據存儲結構的模式,即一個文檔中存儲了檢索還有一個文檔須要的必要信息,舉比例如以下:

    {
       _id: "joe",
       name: "Joe Bookreader"
    }
    
    {
       patron_id: "joe",
       street: "123 Fake Street",
       city: "Faketon",
       state: "MA",
       zip: "12345"
    }
    

    上面的文檔是用戶joe的信息。而以下那個文檔則記錄了他的地址信息。要依據joe的name檢索地址信息。則須要先檢索第一個文檔,然後再檢索第二個文檔。而設計成 嵌套模式則表現為:

    {
       _id: "joe",
       name: "Joe Bookreader",
       addresses: [
                    {
                      street: "123 Fake Street",
                      city: "Faketon",
                      state: "MA",
                      zip: "12345"
                    }
                  ]
     }
    

    這兩種設計模式的均有各自的優缺點,引用模式被覺得是規範化的模式。減小了數據存儲的冗余,結構設計清爽簡單。

    符合我們一般設計原則,可是要獲取完整數據的通信開銷比較大,並且多個文檔操作的原子性在MongoDB層面無法保證。 而被覺得非規範化的嵌套設計模式。則具備相反的特性。其有點是降低了通訊的成本,並且原子性在單條文檔得以保證,缺點就是數據存在冗余。選擇哪種數據組織方式事實上是一種權衡(trade-off)。

  • 註意點:
    (1) MongoDB 文檔的大小必須小於16M,超過這個大小的話,要考慮使用GirdFs。


    (2) 增加的文檔大小超出原先分配給它的空間,MongoDB會把這個文檔移動到磁盤的另外一個位置。

    遷移文檔比原位更新更要耗時,也會因此導致磁盤碎片問題。
    (3) 在MongoDB裏面,操作的原子性級別保證到 document級別。


    (4) Bson 字符串採用UTF-8編碼。

2. MongoDB索引結構:

  • MongoDB支持索引的類型:
    MongoDB採用B樹的結構來組織索引(有效的支持等值查詢和範圍查詢)。支持針對文檔中隨意字段構建索引,不論是單值、數組、文本、嵌套結構的字段,均可構建索引。

    MongoDB 針對BSON存儲格式是一種全索引的支持策略。

    面對多而強大的Mongo索引,索引的設計對性能的提升有比較大的影響。眼下最新MongoV3.0版本號支持的索引類型有例如以下幾種:

    索引類型           簡述   
    Default _id       默認ID索引:Mongo默認構建唯一性索引的id字段,每一個文檔都有一個_id字段。
    Single Field      單值索引:針對文檔的某一字段或或嵌套文檔的某一字段構建索引。

    Compound Index 組合索引:將多個字段放在一起構建索引。字段索引間組成上下層的樹形結構。

    Multikey Index 多值索引:針對數組類型的索引結構,為數組的每一個值建立一個索引。

    Geospatial Index 地理位置索引: 針對地理坐標結構,構建索引。能高效定位坐標範圍,屬額外福利。 Text indexes 文本索引:類似搜索引擎的文本檢索,涉及到分詞操作,可惜不支持中文,並且查詢語法的支持相對單一。 Hashed Indexes 哈希索引:為了支持 基於Hash的Sharding(一種部署方式)而生。僅僅支持等值檢索,不支持範圍檢索。

    以上介紹了索引的類型,而不同類型的索引又能夠帶有下面屬性,間接例如以下:

  • 索引的屬性:

(1) 唯一索引: 和RDB(關系型數據庫)的唯一性索引的概念一致。為了避免出現反復的值而設計。


構建方式如:

    db.members.createIndex( { "user_id": 1 }, { unique: true } )

(2) 稀疏索引: 稀疏索引的稀疏性體如今,其僅僅為那些包括索引字段的文檔構建索引Entry。

忽略那些不包括索引字段的文檔。
構建方式如:

    db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )

(3) TTL索引: TTL顧名思義是生命周期的意思。即存儲的document存儲帶有過期時間屬性,超過生命周期自己主動刪除。像日誌數據、系統自己主動產生的暫時數據、會話數據等均符合這一場景。


構建方式如:

    db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
  • 索引結構和特性:

(1) B樹結構,順序存儲:MongoDB的索引均採用B樹的結構組織,支持高效的等值查詢和範圍查詢。

且內部索引項(entry)是默認有序的,能夠天然保證返回結果有序。


(2) 索引的排序:構建索引是能夠指定索引項是依照升序或降序構建。升序或降序的選擇對於單值索引來說是等效的,可是對於組合索引則不等學效,組合索引被組織成上下級的樹形結構,升序或降序選擇錯誤。會對性能產生較大影響。
(3) 索引的交集:2.6版本號以後,索引的查詢優化策略支持索引的交集,能夠將多條索引組合來使用,最高效的檢索數據。

比如能夠構建兩條單獨的索引。當查詢條件關聯到這兩條索引的時候。索引優化計劃會自己主動組合這兩條索引來檢索。
比如構建了例如以下2條索引:

{ qty: 1 }
{ item: 1 }

則下面查詢語句會命中以上兩條索引:

db.orders.find( { item: "abc123", qty: { $gt: 15 } } )

另外索引的交集和包含:

索引的前綴交集:主要針對組合索引,查詢計劃會優化組合索引的前綴來查詢。

  • 索引分析方法:

(1) 評估RAM容量,盡量保證索引在內存中:
查詢索引大小的命令(單位是字節):

db.collection.totalIndexSize() 
db.collection.stats()

(2) 分析查看索引的計劃:

MongoDB中使用explain和hint能夠查看索引的策略:

db.collection.find().explain()

能夠看出那條索引策略生效,以及索引交集的使用情況。

db.collection.find().hint({"name":1})

hint的命令則能夠指定強制使用某條索引。

(3) 索引的管理信息: 每一個DB以下都會有一個system.indexes集合,這個集合記錄著DB下,索引構建的元數據信息。

db.system.indexes.find()
  • 註意點:
    (1) 每一個索引須要至少8K的空間。
    (2) MongoDB 會對 _id字段自己主動創建唯一索引。
    (3) 一個特別的索引類型支撐了TTL集合的實現,TTL依賴一個在Mongod中的後臺線程。該線程讀取索引中日期類型的值並從集合中刪除過期的documents。

MongoDB數據模型和索引學習總結