MongoDB基礎教程系列--第六篇 MongoDB 索引


 返回目錄

使用索引可以大大提高文檔的查詢效率。如果沒有索引,會遍歷集合中所有文檔,才能找到匹配查詢語句的文檔。這樣遍歷集合中整個文檔的方式是非常耗時的,特別是處理大數據時,耗時幾十秒甚至幾分鍾都是有可能的。

創建索引

MongoDB 中,使用 ensureIndex() 方法創建索引。

格式

db.COLLECTION_NAME.ensureIndex({KEY:1})

其中,KEY表示要創建索引的字段名稱,1 表示按升序排列字段值。-1 表示按降序排列。

范例

1、給 user 集合中 name 字段添加索引

>db.user.ensureIndex({"name":1})
>

MongoDB 中用 db.collection.getIndexes() 方法查詢集合中所有的索引,我們查詢一下 user 中所有的索引。

>db.user.getIndexes()
[
      {
             "v" : 2,
             "key" : {
                         "_id" : 1
             },
             "name" : "_id_",
             "ns" : "liruihuan.user"
      },
      {
             "v" : 2,
             "key" : {
                         "age" : 1
             },
             "name" : "name_1",
             "ns" : "liruihuan.user"
      }
]

我們發現 user 中有兩個索引,其中索引 "_id_" 是我們創建 user 集合時,MongoDB 自動生成的索引。第二個索引就是我們剛才創建的索引,其中,name 值"name_1"表示索引名稱,MongoDB 會自動生成的索引名稱。當然,我們也可以自己指定索引的名稱。

2、給 user 集合中 age 字段添加索引,並指定索引名稱為 "index_age_esc"。

>db.user.ensureIndex({"age":1},{name:"index_age_esc"})
>db.user.getIndexes()
[
      {
             "v" : 2,
             "key" : {
                         "_id" : 1
             },
             "name" : "_id_",
             "ns" : "liruihuan.user"
      },
      {
             "v" : 2,
             "key" : {
                         "age" : 1
             },
             "name" : "index_age_esc",
             "ns" : "liruihuan.user"
      }
]

指定索引名稱用到的 name 參數,只是 ensureIndex() 方法可接收可選參數的其中一個,下表列出了 ensureIndex() 方法可接收的參數

Parameter Type Description
background 布爾值 建索引過程會阻塞其它數據庫操作,background可指定以后台方式創建索引,即增加 "background" 可選參數。 "background" 默認值為false
unique 布爾值 建立的索引是否唯一。指定為true創建唯一索引。默認值為false.
name 字符串 索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。
dropDups 布爾值 在建立唯一索引時是否刪除重復記錄,指定 true 創建唯一索引。默認值為 false.
sparse 布爾值 對文檔中不存在的字段數據不啟用索引;這個參數需要特別注意,如果設置為true的話,在索引字段中不會查詢出不包含對應字段的文檔.。默認值為 false.
expireAfterSeconds 整型 指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間。
v 索引版本 索引的版本號。默認的索引版本取決於mongod創建索引時運行的版本。
weights 文檔(document) 索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引字段的得分權重。
default_language 字符串 對於文本索引,該參數決定了停用詞及詞干和詞器的規則的列表。 默認為英語
language_override 字符串 對於文本索引,該參數指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值為 language.

唯一索引

MongoDB和關系型數據庫一樣都可以建立唯一索引,重復的鍵值就不能重新插入了,MongoDB 用 unigue 來確定建立的索引是否為唯一索引,true 表示為唯一索引,下面給 user 集合的 name 字段指定唯一索引

>db.user.ensureIndex({"name":1},{unique:true})

> db.user.find()
{ "_id" : ObjectId("58e1d2f0bb1bbc3245fa754b"), "name" : "liruihuan", "age" : 18,"sex":"man" }

>db.user.insert({"name":"liruihuan","age":18})
E11000 duplicate key error collection: liruihuan.user index: name_1 dup key: { : \"liruihuan\"

可以看出,創建了唯一索引的字段,是不能再插入 "liruihuan" 的 name 值的。

復合索引

ensureIndex() 方法中你也可以設置使用多個字段創建索引

范例

>db.user.ensureIndex({"name":1,"age":1})
>db.user.getIndexes()
[
      {
             "v" : 2,
             "key" : {
                         "_id" : 1
             },
             "name" : "_id_",
             "ns" : "liruihuan.user"
      },
      {
             "v" : 2,
             "key" : {
                         "name" : 1,
                         "age" : 1
             },
             "name" : "name_1_age_1",
             "ns" : "liruihuan.user"
      }
]

刪除索引

MongoDB 用dropIndex() 方法刪除索引

格式

db.COLLECTION_NAME.dropIndex()

注:dropIndex() 方法可根據指定的索引名稱或索引文檔刪除索引(_id上的默認索引除外)

范例

我們用兩種方式刪除掉 user 中 name 字段上的索引

>db.user.dropIndex("name_1")     #根據索引名稱刪除索引
>db.user.dropIndex({"name":1})   #根據索引文檔刪除索引

還可以用 dropIndexes() 刪除集合中所有索引(_id上的默認索引除外)

>db.user.dropIndexes()

查詢分析

查詢分析是查詢語句性能分析的重要工具。

MongoDB 中查詢分析用 explain() 和 hint() 方法

范例

我們向集合 user 中插入20萬條數據,利用 explain() 查詢建立索引前后,執行時間的比較,來看看建立索引對查詢效率的提高程度。

第一步,向 user 中插入20萬條數據

>db.user.remove({})
>for(var i = 0; i <200000; i++){db.user.insert({"name":"lrh"+i,"age":18})}

第二步,刪除 user 集合中字段 name 上的索引,然后查詢 name = "lrh100000",利用explain("executionStats")查詢此時執行的時間。說明:MongoDB explain() 方法在3.0以后版本中發生了很大改變,3.0之前版本直接用explain()就可以,不用傳參數,如果想詳細了解,請訪問官網

>db.user.dropIndexes()      #刪除所有索引
db.user.find({"name":"lrh100000"}).explain("executionStats")
{
       "queryplanner" : {
                 ......
       },
       "executionStats" : {
                 "executionTimeMillis" : 109
                 ...... 
       }
}

explain.executionStats.executionTimeMillis:表示查詢所用的時間,單位是毫秒。

我們可以清楚的看出,沒用索引查詢用到的時間是 109 毫秒。

第三步,給 user 集合中 name 字段添加索引,然后再查詢同一個條件,看執行查詢所用了多久時間。

>db.user.ensureIndex({"name":1})     
>db.user.find({"name":"lrh100000"}).explain("executionStats")
{
       "queryplanner" : {
                 "winningPlan" : {
                        "inputStage" : {
                                 "indexName" : "name_1"
                                 ......
                        }
                        .......
                 }
                .......
       },
       "executionStats" : {
                 "executionTimeMillis" : 1
                 ...... 
       }
}

如果用到了索引,explain() 方法會返回 winningPlan,標識用到的索引名稱 indexName

我們可以清楚到處,用了索引,執行時間只有 1 毫秒,可以看出,查詢效率的提高可不是一星半點。

注:如果想更詳細的了解 explain() 返回的參數,可以去官網看一下

第四步,這一步我們重點看看 hint() 方法的用法。hint() 方法用來強制 MongoDB 使用一個指定的索引。

我們給 user 再添加一個 {"name":1, "age":1},利用 explain() 方法,看一下用到了哪個索引。

>db.user.ensureIndex({"name":1, "age":1})     
>db.user.find({"name":"lrh100000"}).explain("executionStats")
{
       "queryplanner" : {
                 "winningPlan" : {
                        "inputStage" : {
                                 "indexName" : "name_1_age_1"
                                 ......
                        }
                        .......
                 }
                .......
       }
       ......
}

可以看出,此時用到的索引是 "name_1_age_1",如果我們想用索引 "name_1",就可以用 hint() 方法指定。

>db.user.find({"name":"lrh100000"}).hint({"name":1}).explain("executionStats")
{
       "queryplanner" : {
                 "winningPlan" : {
                        "inputStage" : {
                                 "indexName" : "name_1"
                                 ......
                        }
                        .......
                 }
                .......
       }
       ......
}

 

業精於勤,荒於嬉;行成於思,毀於隨。

如果你覺得這篇文章不錯或者對你有所幫助,可以通過右側【打賞】功能,給予博主一點點鼓勵和支持


免責聲明!

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



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