前言
在MongoDB中,索引通常能夠極大的提高查詢的效率。如果沒(méi)有索引,MongoDB在讀取數(shù)據(jù)時(shí)必須掃描集合中的每個(gè)文檔并選取那些符合查詢條件的記錄。如果有一個(gè)合適的索引來(lái)進(jìn)行查詢,則可以限制掃描文檔的數(shù)量。
索引是特殊的數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)在一個(gè)易于遍歷讀取的數(shù)據(jù)集合中,它是對(duì)數(shù)據(jù)庫(kù)表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu)。索引條目的排序支持高效的匹配和基于范圍的查詢操作,同時(shí),MongoDB可以通過(guò)使用索引返回排序后的結(jié)果。
下面的示意圖表明如何通過(guò)索引篩選和整理匹配的文檔。($lt條件操作符表示小于,{score:-1或者1}表示逆向排序或者正向排序)

從本質(zhì)上來(lái)說(shuō),MongoDB中的索引與其他數(shù)據(jù)庫(kù)系統(tǒng)中的索引相類似,對(duì)于集合中的任何域或者子域都支持索引。
默認(rèn)索引 _id
MongoDB在創(chuàng)建集合時(shí),會(huì)在_id域創(chuàng)建一個(gè)唯一性的索引,即禁止插入兩個(gè)具有相同_id值的文檔,同時(shí)該索引無(wú)法被刪除。
查詢、創(chuàng)建、刪除索引
//查詢索引
db.集合名.getIndexes()
//創(chuàng)建索引
db. 集合名.createIndex( <key and index type specification>, <options> )
//刪除索引
db.集合名.dropIndex(<key and index type specification>)
常見(jiàn)索引
- 單鍵索引
MongoDB支持用戶對(duì)文檔的一個(gè)域創(chuàng)建單鍵索引,進(jìn)行操作時(shí),排列順序并不重要因?yàn)闊o(wú)論升序還是降序,MongoDB均能做遍歷。
假設(shè)有名為records的集合,其中有一個(gè)記錄如下:
{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"userid": 1,
"score": 1034,
"location": { state: "NY", city: "New York" }
}
創(chuàng)建單鍵索引舉例:
//這里的1不是值,而是代表排序方向,即升序
db.records.createIndex( { score: 1 } )

- 復(fù)合索引
當(dāng)查詢條件不止一個(gè)時(shí),即要查詢的字段不止一個(gè)時(shí),就需要?jiǎng)?chuàng)建復(fù)合索引,最大字段數(shù)為31。
創(chuàng)建復(fù)合索引舉例(排列原則為,先對(duì)userid進(jìn)行排序,在userid相同的基礎(chǔ)上,再對(duì)score進(jìn)行排序):
db.collection.createIndex( {userid:1, score:-1} )
// 查詢時(shí),支持對(duì)多個(gè)字段查詢,也支持對(duì)單個(gè)字段查詢
db.collection.find( { userid: "aa1" } )
db.collection.find( { userid: "ca2", score: { $gt: 60} } )

1)排序順序:
假設(shè)一個(gè)集合
events的文檔有兩個(gè)字段username與date,使用下面兩條不同的語(yǔ)句查詢:
db.events.find().sort( { username: 1, date: -1 } )
db.events.find().sort( { username: -1, date: 1 } )
可支持上面兩條查詢語(yǔ)句的索引為:
db.events.createIndex( { "username" : 1, "date" : -1 } )
但是,該索引卻不支持下面的查詢:
db.events.find().sort( { username: 1, date: 1 } )
更多詳情可參考 Use Indexes to Sort Query Results(需翻墻)
2)前綴:
索引前綴是復(fù)合索引字段的子集。例如,考慮下面的復(fù)合:
{ "item": 1, "location": 1, "stock": 1 }
它的索引前綴為:
{ item: 1 }
{ item: 1, location: 1 }
該復(fù)合索引可查詢的方法有如下幾種:
the item field,
the item field and the location field,
the item field and the location field and the stock field.
當(dāng)然還有the item field and the stock field,因?yàn)?code>item field是一個(gè)索引前綴,當(dāng)然這樣的效率不及直接用item field and the stock field作為一個(gè)復(fù)合索引。
但是,下面的查詢方法是不支持的,因?yàn)槿鄙倭?code>item字段而不符合索引前綴。
the location field,
the stock field,
the location and stock fields.
如果建立了復(fù)合索引,同時(shí)有一個(gè)單鍵索引與它的復(fù)合索引重復(fù),當(dāng)它們沒(méi)有稀疏或者唯一的屬性時(shí),可把單鍵索引刪去。因?yàn)镸ongoDB會(huì)在能使用復(fù)合索引前綴的任何情況下優(yōu)先用之。
- 多鍵索引
多鍵索引和單鍵索引創(chuàng)建形式相同,區(qū)別在于字段的值。對(duì)于單鍵索引,字段的值為一個(gè)單一的值,如字符串,數(shù)字,日期。對(duì)于多鍵索引,值具有多個(gè)記錄,如數(shù)組。為了給一個(gè)數(shù)組字段創(chuàng)建索引,MongoDB為數(shù)組中的每一個(gè)元素均創(chuàng)建一個(gè)索引鍵。多鍵索引支持高效查詢數(shù)組字段,它可以被構(gòu)建在包含字符串、數(shù)字類型或者嵌套文檔的數(shù)組。
創(chuàng)建多鍵索引舉例:
db.collection.createIndex( { addr.zip: 1 } )

1)限制
多鍵索引不支持以下幾種情況:分片鍵、哈希索引、覆蓋查詢。
對(duì)于復(fù)合多鍵索引,多個(gè)字段不能同時(shí)為數(shù)組,但允許其中一個(gè)字段為數(shù)組。
MongoDB無(wú)法直接使用整個(gè)數(shù)組作為查詢條件,而是將數(shù)組的第一個(gè)元素作為查詢條件,得到符合第一個(gè)元素的文檔,返回給MongoDB,再使用第二個(gè)元素作為查詢條件,直到得到最終結(jié)果。
- 過(guò)期索引
顧名思義,即在一段時(shí)間后便會(huì)過(guò)期的索引,在索引過(guò)期后,相應(yīng)的數(shù)據(jù)會(huì)被刪除。適合存儲(chǔ)在一段時(shí)間之后會(huì)失效的數(shù)據(jù)比如用戶的登錄信息、存儲(chǔ)的日志。
創(chuàng)建過(guò)期索引舉例(expireAfterSeconds后的值表示多少秒后刪除):
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
參考英文文檔,由于英文水平不足,有些部分翻譯會(huì)比較生硬。
如有建議,歡迎指出。