前言
在MongoDB中,索引通常能夠極大的提高查詢的效率。如果沒有索引,MongoDB在讀取數據時必須掃描集合中的每個文檔并選取那些符合查詢條件的記錄。如果有一個合適的索引來進行查詢,則可以限制掃描文檔的數量。
索引是特殊的數據結構,存儲在一個易于遍歷讀取的數據集合中,它是對數據庫表中一列或多列的值進行排序的一種結構。索引條目的排序支持高效的匹配和基于范圍的查詢操作,同時,MongoDB可以通過使用索引返回排序后的結果。
下面的示意圖表明如何通過索引篩選和整理匹配的文檔。($lt
條件操作符表示小于,{score:-1或者1}
表示逆向排序或者正向排序)
從本質上來說,MongoDB中的索引與其他數據庫系統中的索引相類似,對于集合中的任何域或者子域都支持索引。
默認索引 _id
MongoDB在創建集合時,會在_id
域創建一個唯一性的索引,即禁止插入兩個具有相同_id
值的文檔,同時該索引無法被刪除。
查詢、創建、刪除索引
//查詢索引
db.集合名.getIndexes()
//創建索引
db. 集合名.createIndex( <key and index type specification>, <options> )
//刪除索引
db.集合名.dropIndex(<key and index type specification>)
常見索引
- 單鍵索引
MongoDB支持用戶對文檔的一個域創建單鍵索引,進行操作時,排列順序并不重要因為無論升序還是降序,MongoDB均能做遍歷。
假設有名為records
的集合,其中有一個記錄如下:
{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"userid": 1,
"score": 1034,
"location": { state: "NY", city: "New York" }
}
創建單鍵索引舉例:
//這里的1不是值,而是代表排序方向,即升序
db.records.createIndex( { score: 1 } )
- 復合索引
當查詢條件不止一個時,即要查詢的字段不止一個時,就需要創建復合索引,最大字段數為31。
創建復合索引舉例(排列原則為,先對userid進行排序,在userid相同的基礎上,再對score進行排序):
db.collection.createIndex( {userid:1, score:-1} )
// 查詢時,支持對多個字段查詢,也支持對單個字段查詢
db.collection.find( { userid: "aa1" } )
db.collection.find( { userid: "ca2", score: { $gt: 60} } )
1)排序順序:
假設一個集合
events
的文檔有兩個字段username
與date
,使用下面兩條不同的語句查詢:
db.events.find().sort( { username: 1, date: -1 } )
db.events.find().sort( { username: -1, date: 1 } )
可支持上面兩條查詢語句的索引為:
db.events.createIndex( { "username" : 1, "date" : -1 } )
但是,該索引卻不支持下面的查詢:
db.events.find().sort( { username: 1, date: 1 } )
更多詳情可參考 Use Indexes to Sort Query Results(需翻墻)
2)前綴:
索引前綴是復合索引字段的子集。例如,考慮下面的復合:
{ "item": 1, "location": 1, "stock": 1 }
它的索引前綴為:
{ item: 1 }
{ item: 1, location: 1 }
該復合索引可查詢的方法有如下幾種:
the item field,
the item field and the location field,
the item field and the location field and the stock field.
當然還有the item field and the stock field
,因為item field
是一個索引前綴,當然這樣的效率不及直接用item field and the stock field
作為一個復合索引。
但是,下面的查詢方法是不支持的,因為缺少了item
字段而不符合索引前綴。
the location field,
the stock field,
the location and stock fields.
如果建立了復合索引,同時有一個單鍵索引與它的復合索引重復,當它們沒有稀疏或者唯一的屬性時,可把單鍵索引刪去。因為MongoDB會在能使用復合索引前綴的任何情況下優先用之。
- 多鍵索引
多鍵索引和單鍵索引創建形式相同,區別在于字段的值。對于單鍵索引,字段的值為一個單一的值,如字符串,數字,日期。對于多鍵索引,值具有多個記錄,如數組。為了給一個數組字段創建索引,MongoDB為數組中的每一個元素均創建一個索引鍵。多鍵索引支持高效查詢數組字段,它可以被構建在包含字符串、數字類型或者嵌套文檔的數組。
創建多鍵索引舉例:
db.collection.createIndex( { addr.zip: 1 } )
1)限制
多鍵索引不支持以下幾種情況:分片鍵、哈希索引、覆蓋查詢。
對于復合多鍵索引,多個字段不能同時為數組,但允許其中一個字段為數組。
MongoDB無法直接使用整個數組作為查詢條件,而是將數組的第一個元素作為查詢條件,得到符合第一個元素的文檔,返回給MongoDB,再使用第二個元素作為查詢條件,直到得到最終結果。
- 過期索引
顧名思義,即在一段時間后便會過期的索引,在索引過期后,相應的數據會被刪除。適合存儲在一段時間之后會失效的數據比如用戶的登錄信息、存儲的日志。
創建過期索引舉例(expireAfterSeconds
后的值表示多少秒后刪除):
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
參考英文文檔,由于英文水平不足,有些部分翻譯會比較生硬。
如有建議,歡迎指出。