我叫Mongo,干了「索引探索篇」提升我的效率,值得您擁有


這是mongo第四篇“索引探索”,后續會連續更新4篇

 

   mongodb的文章總結上會有一系列的文章,順序是先學會怎么用,在學會怎么用好,戒急戒躁,循序漸進,跟着我一起來探索交流。通過上三篇的介紹,我相信大家對我在使用上已經很溜啦,但是在實際使用中還需要注重效率提升,本文章探索索引,就是為提升效率為出發點,本文的介紹順序是:索引簡介->索引原理->索引類型->索引與查詢結合使用->小結,讓我們一起來一步一步的探索吧。​

01

     索引簡介

 

  Mongodb的索引和其它關系型數據庫索引很類似,索引是一個存儲結構,其存儲的內容是數據文檔持久化的位置信息。一個數據集合和一本書來對比,那么索引就是書對應的目錄,其作用就是加快查詢效率。索引在加快查詢效率的同時,在更新、刪除、新增數據時也會影響數據變更效率,因為每一次數據變更都會更新一次索引。所以在索引使用時也需要慎重。

Mongodb索引的基本命令包括:

新增索引:createIndex({字段:排序方式},{可選參數})

刪除索引:dropIndex({字段:排序方式})

查看索引:getIndexes()

先不管索引為什么能夠提高查詢效率,降低數據變更效率,先來一個實例。為了體現效果,這次我整的有點狠,直接初始化了300多萬條數據,演示步驟如下:

數據初始化:

for(var i=0;i<3000000 ;i++)

{
     db.user.insert({
        name:"我叫"+i,
        age:i%10,  
        from:i%10000
   })
}        

  

  // 上面的數據有一個特點age的值就10個,from的值有10000個。下面分別對兩個字段加上索引,並通過實際的執行語句來看效果。

給user表的age添加一個索引(age升序)

db.user.createIndex({age:1})

給user表的from添加一個索引(from升序)

db.user.createIndex({from:1})

 

 

   其實我們都知道索引能夠提高查詢效率,估計很少親自測試一把,通過測試是不是有一種爽歪歪的感覺。根據實際操作結果我們先得出幾點小小的結論:

  • 當字段的值是有限的一些值時,其實有無索引對效率無影響;
  • 當字段的值重復數據少時,索引的查詢效率明顯提高幾百倍;
  • 當查詢結果需要排序時,有索引比沒索引的效率高50倍左右;
  • 當更新時,有索引的效率低於無索引;
  • 所以在添加索引時針對字段值是有限的值時,就沒必要添加索引,當經常需要用於排序的字段可以考慮添加索引。

  以上的幾個結論,也是我通過實際數據操作得出的,如果有不准確的地方,希望指點改正,謝謝!

  先把結論得到這兒,下面我們在一步一步的剖析索引。

 

02

     索引原理

  Mongdb數據通過存儲引擎持久化以后,其實在磁盤中就是一個一個的文件,每一個文件都對應一個位置信息。索引就是這一些文件位置信息與索引字段值的對應關系的有序數據集合,索引采用btree的結構持久化存儲。在創建索引后,數據在查詢的時,直接索引數據集合查詢,然后在根據對於的位置信息操作對應的數據詳情,避免了全表掃描,同時查詢出的數據本來就是有序的數據,也避免了因為排序導致的性能損失。

  這樣我們就不難理解上面得出的幾點結論了:因為索引查詢避免了全表數據掃描,所有查詢效率高;因為索引本身就已經是有序的數據,所以根據索引字段排序效率明顯提高;因為索引會單擊存儲,一旦數據有變更,都需要同時更新索引數據,所有數據更新時有索引的效率低,同時索引也會增加額外的存儲開銷。

03

     索引類型

  MongoDB支持多種類型的索引,包括單字段索引、復合索引、多key索引、文本索引等,每種類型的索引有不同的使用場合。

  單字段索引:

  單字段索引其實很好理解,文章開始我們創建的實例就是單字段索引,簡單的所說就是針對某一個字段創建一個索引,達到提高索引字段的查詢效率。Mongdb默認_id字段創建單字段唯一索引。

 

 格式:db.collectionName.createIndex({索引字段:1升序-1降序} )

  實例:對集合user的字段age添加升序索引

  db.user.createIndex({age:1})

   

  復合索引:

  復合索引是針對單字段索引的升級版,復合索引就是聯合多個字段創建索引,也是我們常說的聯合索引。復合索引在數據存儲上,首先根據第一字段排序、然后當第一字段值相同時在以第二字段排序、依次類推第N字段。復合索引能夠滿足以下兩個場景的查詢需要:根據復合索引多個字段組合查詢;根據所有前綴字段查詢,也就是所有字段的順序的第一個至第N個的前綴字段查詢。

格式:db.collectionName.createIndex({索引字段1:排序, 索引字段2:排序} )

實例:對集合user添加字段from降序、age升序索引

db.user.createIndex({from:-1,age:1 })

以下情況可以使用到索引:

db.user.find({from:20,age:8})、db.user.find({from:20})

以下情況不能使用索引:

db.user.find({age:8,from:20})、db.user.find({age:8})

  根據復合索引的使用情況得出以下幾點小結論:

  • 索引使用順序一定要和索引創建順序保持一致;
  • 當索引字段不完全組合查詢時,需要前序字段連續;
  • 創建索引時最好取值豐富的字段在前。

  多key索引:

  多key索引是指創建的索引字段為數組,多key索引會為數組的每個元素建立一條索引,使用場景就是針對字段值是數組的查詢。有了前面的基礎,這一個就很好理解,就不在詳細描述了。

  文本索引:

  文本索引,簡單的說就是針對文本數據創建索引,比如,文章信息表,如果需要根據文章關鍵詞檢索,那么就可以對文章字段創建文本索引。格式為:db.collectionName.createIndex({索引字段1: "text" } )

04

   索引額外屬性說明 

  createIndex創建索引時,該方法有兩個參數,第一個參數就是索引字段,上面已經說了,第二個參數就是索引的額外屬性,下面我們就說說索引額外屬性信息。索引額外屬性包括:唯一索引、TTL索引、稀疏索引。

  TTL索引

  TTL索引屬性是修飾當文檔存儲自定時間,當超出指定時間后,數據被被自動刪除,使用場景為數據只存儲指定時間,如:日志數據,關鍵詞為expireAfterSecs格式為:db.collectionName.createIndex({索引字段1: "text" }, {"expireAfterSecs": 失效時間單位為秒})。

TTL索引幾點注意事項:

  • TTL只使用於時間字段
  • TTL不使用於聯合索引
  • TTL如果對於索引值是數組,那么只要其中一個值滿足要求就自動刪除

  唯一索引 (unique index)

 保證索引對應的字段不會出現相同的值,比如_id索引就是唯一索引。格式為:db.collectionName.createIndex({索引字段1: "text" }, {"unique": true})
 

  部分索引 (partial index):

  只針對符合某個特定條件的文檔建立索引,3.2版本才支持該特性。關鍵詞為partialFilterExpression

 

 格式為:db.collectionName.createIndex({索引字段1: "text" }, {"partialFilterExpression": {數據滿足條件表達式}})。

  比如:對表user只有age=9的數據創建索引

  db.user.createIndex({age:1},

  {"partialFilterExpression":{age:9}})

   

  稀疏索引(sparse index):

  只針對存在索引字段的文檔建立索引,可看做是部分索引的一種特殊情況。關鍵詞為:sparse,格式為:db.collectionName.createIndex({索引字段1: "text" }, {"sparse": true})。
 

06

     索引優化(profiling

 其實我們在建集合的時候,很多時候最開始是不知道那一些字段需要添加索引,是需要根據后續的實際使用場景來動態創建,那么這就會有一個問題,如果監控哪一些字段需要添加或是刪除索引,可通過檢測每一次操作結果的響應時間長短來動態創建索引,mongdb提供了一個profiling來動態檢測執行響應情況。

MongoDB支持對DB的請求進行profiling,目前支持3種級別的profiling。

  • 0: 不開啟profiling
  • 1: 將處理時間超過某個閾值(默認100ms)的請求都記錄到DB下的system.profile集合 (類似於mysql、redis的slowlog)
  • 2: 將所有的請求都記錄到DB下的system.profile集合(生產環境慎用)

  通常,生產環境建議使用1級別的profiling,並根據自身需求配置合理的閾值,用於監測慢請求的情況,並及時的做索引優化。

開啟profiling命令:db.setProfilingLevel(1,120 );
查詢profil記錄信息:db.system.profile.find()

    最終通過查詢出來的記錄信息,對索引進行優化。

07

小結

            Mongdb在提升查詢效率上是很有幫助,但是在實際使用中也不要濫用,否則會適得其反,下面總結幾點,供參考:

    • 索引創建時最好作用於取值豐富的字段,有限值的字段就沒必要添加索引;
    • 經常排序的字段,可以考慮添加索引;
    • 一個集合中索引的個數不是越多越好,需要根據實際情況來定;
    • 執行接口慢,有可能是缺少索引(查詢慢),也有可能是索引使用不當(編輯慢);
    • 復合索引在使用時,一定要結合索引字段的順序使用。
  • END
    原創不易,感謝掃描支持,獲取更多精彩,謝謝:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM