使用索引可以大大提高文檔的查詢效率。如果沒有索引,會遍歷集合中所有文檔,才能找到匹配查詢語句的文檔。這樣遍歷集合中整個文檔的方式是非常耗時的,特別是處理大數(shù)據(jù)時,耗時幾十秒甚至幾分鐘都是有可能的。
創(chuàng)建索引
MongoDB 中,使用 ensureIndex() 方法創(chuàng)建索引。
格式
1 | db.COLLECTION_NAME.ensureIndex({ KEY :1}) |
其中,KEY表示要創(chuàng)建索引的字段名稱,1 表示按升序排列字段值。-1 表示按降序排列。
范例
1、給 user 集合中 name 字段添加索引
1 2 | >db. user .ensureIndex({ "name" :1}) > |
MongoDB 中用 db.collection.getIndexes() 方法查詢集合中所有的索引,我們查詢一下 user 中所有的索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | >db. user .getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" , "ns" : "liruihuan.user" }, { "v" : 2, "key" : { "age" : 1 }, "name" : "name_1" , "ns" : "liruihuan.user" } ] |
我們發(fā)現(xiàn) user 中有兩個索引,其中索引 "_id_" 是我們創(chuàng)建 user 集合時,MongoDB 自動生成的索引。第二個索引就是我們剛才創(chuàng)建的索引,其中,name 值"name_1"表示索引名稱,MongoDB 會自動生成的索引名稱。當然,我們也可以自己指定索引的名稱。
2、給 user 集合中 age 字段添加索引,并指定索引名稱為 "index_age_esc"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | >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 參數(shù),只是 ensureIndex() 方法可接收可選參數(shù)的其中一個,下表列出了 ensureIndex() 方法可接收的參數(shù)
Parameter | Type | Description |
---|---|---|
background | 布爾值 | 建索引過程會阻塞其它數(shù)據(jù)庫操作,background可指定以后臺方式創(chuàng)建索引,即增加 "background" 可選參數(shù)。 "background" 默認值為false。 |
unique | 布爾值 | 建立的索引是否唯一。指定為true創(chuàng)建唯一索引。默認值為false. |
name | 字符串 | 索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。 |
dropDups | 布爾值 | 在建立唯一索引時是否刪除重復(fù)記錄,指定 true 創(chuàng)建唯一索引。默認值為 false. |
sparse | 布爾值 | 對文檔中不存在的字段數(shù)據(jù)不啟用索引;這個參數(shù)需要特別注意,如果設(shè)置為true的話,在索引字段中不會查詢出不包含對應(yīng)字段的文檔.。默認值為 false. |
expireAfterSeconds | 整型 | 指定一個以秒為單位的數(shù)值,完成 TTL設(shè)定,設(shè)定集合的生存時間。 |
v | 索引版本 | 索引的版本號。默認的索引版本取決于mongod創(chuàng)建索引時運行的版本。 |
weights | 文檔(document) | 索引權(quán)重值,數(shù)值在 1 到 99,999 之間,表示該索引相對于其他索引字段的得分權(quán)重。 |
default_language | 字符串 | 對于文本索引,該參數(shù)決定了停用詞及詞干和詞器的規(guī)則的列表。 默認為英語 |
language_override | 字符串 | 對于文本索引,該參數(shù)指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值為 language. |
唯一索引
MongoDB和關(guān)系型數(shù)據(jù)庫一樣都可以建立唯一索引,重復(fù)的鍵值就不能重新插入了,MongoDB 用 unigue 來確定建立的索引是否為唯一索引,true 表示為唯一索引,下面給 user 集合的 name 字段指定唯一索引
1 2 3 4 5 6 7 | >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\" |
可以看出,創(chuàng)建了唯一索引的字段,是不能再插入 "liruihuan" 的 name 值的。
復(fù)合索引
ensureIndex() 方法中你也可以設(shè)置使用多個字段創(chuàng)建索引
范例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | >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() 方法刪除索引
格式
1 | db.COLLECTION_NAME.dropIndex() |
注:dropIndex() 方法可根據(jù)指定的索引名稱或索引文檔刪除索引(_id上的默認索引除外)
范例
我們用兩種方式刪除掉 user 中 name 字段上的索引
1 2 | >db. user .dropIndex( "name_1" ) #根據(jù)索引名稱刪除索引 >db. user .dropIndex({ "name" :1}) #根據(jù)索引文檔刪除索引 |
還可以用 dropIndexes() 刪除集合中所有索引(_id上的默認索引除外)
1 | >db. user .dropIndexes() |
查詢分析
查詢分析是查詢語句性能分析的重要工具。
MongoDB 中查詢分析用 explain() 和 hint() 方法
范例
我們向集合 user 中插入20萬條數(shù)據(jù),利用 explain() 查詢建立索引前后,執(zhí)行時間的比較,來看看建立索引對查詢效率的提高程度。
第一步,向 user 中插入20萬條數(shù)據(jù)
1 2 | >db. user .remove({}) > for (var i = 0; i <200000; i++){db. user . insert ({ "name" : "lrh" +i, "age" :18})} |
第二步,刪除 user 集合中字段 name 上的索引,然后查詢 name = "lrh100000",利用explain("executionStats")查詢此時執(zhí)行的時間。說明:MongoDB explain() 方法在3.0以后版本中發(fā)生了很大改變,3.0之前版本直接用explain()就可以,不用傳參數(shù),如果想詳細了解,請訪問官網(wǎng)。
1 2 3 4 5 6 7 8 9 10 11 | >db. user .dropIndexes() #刪除所有索引 db. user .find({ "name" : "lrh100000" }).explain( "executionStats" ) { "queryplanner" : { ...... }, "executionStats" : { "executionTimeMillis" : 109 ...... } } |
explain.executionStats.executionTimeMillis:表示查詢所用的時間,單位是毫秒。
我們可以清楚的看出,沒用索引查詢用到的時間是 109 毫秒。
第三步,給 user 集合中 name 字段添加索引,然后再查詢同一個條件,看執(zhí)行查詢所用了多久時間。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >db. user .ensureIndex({ "name" :1}) >db. user .find({ "name" : "lrh100000" }).explain( "executionStats" ) { "queryplanner" : { "winningPlan" : { "inputStage" : { "indexName" : "name_1" ...... } ....... } ....... }, "executionStats" : { "executionTimeMillis" : 1 ...... } } |
如果用到了索引,explain() 方法會返回 winningPlan,標識用到的索引名稱 indexName
我們可以清楚到處,用了索引,執(zhí)行時間只有 1 毫秒,可以看出,查詢效率的提高可不是一星半點。
注:如果想更詳細的了解 explain() 返回的參數(shù),可以去官網(wǎng)看一下
第四步,這一步我們重點看看 hint() 方法的用法。hint() 方法用來強制 MongoDB 使用一個指定的索引。
我們給 user 再添加一個 {"name":1, "age":1},利用 explain() 方法,看一下用到了哪個索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >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() 方法指定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >db. user .find({ "name" : "lrh100000" }).hint({ "name" :1}).explain( "executionStats" ) { "queryplanner" : { "winningPlan" : { "inputStage" : { "indexName" : "name_1" ...... } ....... } ....... } ...... } |
業(yè)精于勤,荒于嬉;行成于思,毀于隨。
如果你覺得這篇文章不錯或者對你有所幫助,可以通過右側(cè)【打賞】功能,給予博主一點點鼓勵和支持
標簽: MongoDB
http://www.cnblogs.com/liruihuan/p/6682575.html