前言
在MongoDB中,索引通常能夠極大的提高查詢的效率酿愧。如果沒有索引沥潭,MongoDB在讀取數據時必須掃描集合中的每個文檔并選取那些符合查詢條件的記錄。如果有一個合適的索引來進行查詢嬉挡,則可以限制掃描文檔的數量钝鸽。
索引是特殊的數據結構汇恤,存儲在一個易于遍歷讀取的數據集合中,它是對數據庫表中一列或多列的值進行排序的一種結構拔恰。索引條目的排序支持高效的匹配和基于范圍的查詢操作因谎,同時,MongoDB可以通過使用索引返回排序后的結果颜懊。
下面的示意圖表明如何通過索引篩選和整理匹配的文檔财岔。($lt
條件操作符表示小于,{score:-1或者1}
表示逆向排序或者正向排序)
從本質上來說河爹,MongoDB中的索引與其他數據庫系統(tǒng)中的索引相類似匠璧,對于集合中的任何域或者子域都支持索引。
默認索引 _id
MongoDB在創(chuàng)建集合時咸这,會在_id
域創(chuàng)建一個唯一性的索引夷恍,即禁止插入兩個具有相同_id
值的文檔,同時該索引無法被刪除媳维。
查詢裁厅、創(chuàng)建、刪除索引
//查詢索引
db.集合名.getIndexes()
//創(chuàng)建索引
db. 集合名.createIndex( <key and index type specification>, <options> )
//刪除索引
db.集合名.dropIndex(<key and index type specification>)
常見索引
- 單鍵索引
MongoDB支持用戶對文檔的一個域創(chuàng)建單鍵索引侨艾,進行操作時,排列順序并不重要因為無論升序還是降序拓挥,MongoDB均能做遍歷唠梨。
假設有名為records
的集合,其中有一個記錄如下:
{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"userid": 1,
"score": 1034,
"location": { state: "NY", city: "New York" }
}
創(chuàng)建單鍵索引舉例:
//這里的1不是值侥啤,而是代表排序方向当叭,即升序
db.records.createIndex( { score: 1 } )
- 復合索引
當查詢條件不止一個時,即要查詢的字段不止一個時盖灸,就需要創(chuàng)建復合索引蚁鳖,最大字段數為31。
創(chuàng)建復合索引舉例(排列原則為赁炎,先對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會在能使用復合索引前綴的任何情況下優(yōu)先用之同波。
- 多鍵索引
多鍵索引和單鍵索引創(chuàng)建形式相同鳄梅,區(qū)別在于字段的值。對于單鍵索引未檩,字段的值為一個單一的值戴尸,如字符串,數字冤狡,日期孙蒙。對于多鍵索引,值具有多個記錄悲雳,如數組挎峦。為了給一個數組字段創(chuàng)建索引,MongoDB為數組中的每一個元素均創(chuàng)建一個索引鍵合瓢。多鍵索引支持高效查詢數組字段坦胶,它可以被構建在包含字符串、數字類型或者嵌套文檔的數組晴楔。
創(chuàng)建多鍵索引舉例:
db.collection.createIndex( { addr.zip: 1 } )
1)限制
多鍵索引不支持以下幾種情況:分片鍵顿苇、哈希索引、覆蓋查詢税弃。
對于復合多鍵索引纪岁,多個字段不能同時為數組,但允許其中一個字段為數組则果。
MongoDB無法直接使用整個數組作為查詢條件幔翰,而是將數組的第一個元素作為查詢條件,得到符合第一個元素的文檔西壮,返回給MongoDB导匣,再使用第二個元素作為查詢條件,直到得到最終結果茸时。
- 過期索引
顧名思義贡定,即在一段時間后便會過期的索引,在索引過期后可都,相應的數據會被刪除缓待。適合存儲在一段時間之后會失效的數據比如用戶的登錄信息蚓耽、存儲的日志。
創(chuàng)建過期索引舉例(expireAfterSeconds
后的值表示多少秒后刪除):
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
參考英文文檔旋炒,由于英文水平不足步悠,有些部分翻譯會比較生硬。
如有建議瘫镇,歡迎指出鼎兽。