MongoDB索引問題

索引類型:mysql

MongoDB有多種索引類型,每種索引類型有其適合的場景。sql

  1. 單字段索引
  2. 複合索引
  3. 多key索引
  4. 文本索引
  5. 其餘

對於單字段索引而言,升序和降序效果是同樣的。mongodb

複合索引針對多個字段聯合建立索引,先按第一個字段排序,第一個字段相同的文檔按第二個字段排序,以此類推。複合索引也能知足單個字段的索引,但僅限複合索引首個字段。數據庫

當索引的字段爲數組時,建立出的索引爲多key索引,多key索引會爲數組的每一個元素創建一條索引,好比下圖所示BillInterceptLifeInfo表中加入一個NeedSyncSiteCodes字段,須要查詢NeedSyncSiteCodes中是否包含了某個sitecode就能夠利用該字段的多key索引。json

 

實際場景:api

攔截件監控代碼中,主要的數據在一個攔截件生命期表, 該表記錄了攔截件的生命期狀態,一個應下發設備表和一個實際下發設備表。數組

表結構以下:性能

其中更新應下發設備表是要查詢出1.站點信息相符的全部單號,且該單號的2.結束時間大於當前時間,且該3.應下發List中不含即將插入的deviceID纔會插入一條記錄。優化

由於須要下發的站點列表和須要下發的設備列表是兩個list,沒法一塊兒建索引,所以決定建EndTime和NeedSyncSiteCodes的複合索引,NeedSyncSiteCodes也是一個多key索引。url

一開始建索引以下:

 

 db.BillInterceptLifeInfo.createIndex({  "EndTime" : 1, "NeedSyncSiteCodes" : 1 }) 
代碼上線後,一開始平穩,但數據量上千後開始不穩定
後根據系統優化提示將索引改成:
 db.BillInterceptLifeInfo.createIndex({ "NeedSyncSiteCodes" : 1 , "EndTime" : 1,}) 
監控如圖:
根據某兩條查詢對比來看:
前:  後:
能夠看出,組合索引的前後順序不一樣,EndTime在前的索引Key match到的記錄有5K多條,而實際須要修改的只有3條,
NeedSyncSiteCodes在前的索引Key match到的記錄有107條,而這107條都是須要修改的,NeedSyncSiteCodes在前的這條索引能縮小二次匹配的範圍程度更大。
在複合索引中,多個字段應把最有區分度的字段放前面,好比一個person表中有一個[name + age]的複合索引,age字段的取值頗有限,即擁有相同age字段的文檔會有不少;而name字段的取值則豐富不少,擁有相同name字段的文檔不多;顯然先按name字段查找,再在相同name的文檔裏查找age字段更爲高效。
同理,在此例子中的EndTime和NeedSyncSiteCodes兩個字段建複合索引,EndTime的區分度確定不如NeedSyncSiteCodes的多key索引。所以將NeedSyncSiteCodes做爲複合索引的第一項更高效。
 
複合多key索引中:
  • 對於一個複合多key索引,每個索引最多能夠包含一個數組。
  • 在多於一個數組的情形下來建立複合多key索引不被支持。

 

另外談下B樹(即B-樹)和B+樹的區別,以及爲何mongodb用B-樹而不用B+樹。

首先B樹結構(細節請自行查閱)以下圖:

每一個節點存有key對應的data, 每一個節點上的n個key有n+1個子節點。

一個m階的B樹每一個節點至少有m個孩子。

一棵含有N個總關鍵字數的m階的B樹的最大高度是log_ceil(m/2)(N+1)/2 + 1。

所以B數的高度相對會降低,而高度降低,定位數據會更快。因爲B數節點中存數據,最快查詢可爲O(1)。

 

而B+樹,以下圖:

 

B+樹的特色是,key的副本存儲在內部節點,真正的key-data存儲在葉子節點上。

n個key的節點指針域是n而不是n+1(mongodb 是n+1)

爲了增長區間訪問性,B+樹的葉子節點兩兩相連,對於範圍查詢大大增長了友好度。

 

B樹和B+樹在磁盤訪問這一點上

  1. B樹由於key對應的data直接在節點上,所以查詢到能夠直接取出,最好的狀況下查詢很是快,且磁盤訪問會降低。可是正由於如此,單個節點存儲太大,若是沒有訪問到key,再要往下查詢時,須要讀入內存的數據量就很大。
  2. B+樹由於內部節點只存key的副本,所以查詢效率相對很穩定。但也是由於存儲了key的副本,致使整個索引相對會比較大。

 

B樹和B+樹各有優缺點,對於mongodb來講,mongdb是一種文檔型數據庫,使用json格式保存數據,歸屬於聚合型數據庫。適用於數據模型簡單,性能要求高的場合。

而mysql之類的關係型數據庫,區間訪問是很常見的現象,B+樹支持區間訪問,所以mysql更適合用B+樹。

相關文章
相關標籤/搜索