返回目錄

使用索引可以大大提高文檔的查詢效率。如果沒有索引,會遍歷集合中所有文檔,才能找到匹配查詢語句的文檔。這樣遍歷集合中整個文檔的方式是非常耗時的,特別是處理大數(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ù)

ParameterTypeDescription
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