================ 索引 ================
索引支持在MongoDB中高效地執(zhí)行查詢从隆。如果沒有索引,MongoDB必須執(zhí)行全集合掃描狸吞,即掃描集合中的每個文檔官帘,以選擇與查詢語句
匹配的文檔。這種掃描全集合的查詢效率是非常低的悄晃,特別在處理大量的數(shù)據(jù)時,查詢可以要花費幾十秒甚至幾分鐘白粉,這對網(wǎng)站的性能是非
常致命的传泊。
如果查詢存在適當(dāng)?shù)乃饕琈ongoDB可以使用該索引限制必須檢查的文檔數(shù)鸭巴。
索引是特殊的數(shù)據(jù)結(jié)構(gòu)眷细,它以易于遍歷的形式存儲集合數(shù)據(jù)集的一小部分。索引存儲特定字段或一組字段的值鹃祖,按字段值排序溪椎。索引項的排
序支持有效的相等匹配和基于范圍的查詢操作。此外恬口,MongoDB還可以使用索引中的排序返回排序結(jié)果校读。
官網(wǎng)文檔:https://docs.mongodb.com/manual/indexes/
MongoDB索引使用B樹數(shù)據(jù)結(jié)構(gòu)(確切的說是B-Tree,MySQL是B+Tree)
1 索引的類型
1.1 單字段索引
MongoDB支持在文檔的單個字段上創(chuàng)建用戶定義的升序/降序索引祖能,稱為單字段索引(Single Field Index)歉秫。
對于單個字段索引和排序操作,索引鍵的排序順序(即升序或降序)并不重要养铸,因為MongoDB可以在任何方向上遍歷索引雁芙。
1.2 復(fù)合索引
MongoDB還支持多個字段的用戶定義索引轧膘,即復(fù)合索引(Compound Index)。
復(fù)合索引中列出的字段順序具有重要意義兔甘。例如谎碍,如果復(fù)合索引由 { userid: 1, score: -1 } 組成,則索引首先按userid正序排序洞焙,然后
在每個userid的值內(nèi)蟆淀,再在按score倒序排序
1.3 其他索引
地理空間索引(Geospatial Index)、文本索引(Text Indexes)澡匪、哈希索引(Hashed Indexes)熔任。
1.3.1 地理空間索引(Geospatial Index)
為了支持對地理空間坐標(biāo)數(shù)據(jù)的有效查詢,MongoDB提供了兩種特殊的索引:返回結(jié)果時使用平面幾何的二維索引和返回結(jié)果時使用球面 幾何的二維球面索引仙蛉。
1.3.2 文本索引(Text Indexes)
MongoDB提供了一種文本索引類型笋敞,支持在集合中搜索字符串內(nèi)容。這些文本索引不存儲特定于語言的停止詞(例如“the”荠瘪、“a”、“or”)赛惩,而將集合中的詞作為詞干哀墓,只存儲根詞。
1.3.3 哈希索引(Hashed Indexes)
為了支持基于散列的分片喷兼,MongoDB提供了散列索引類型篮绰,它對字段值的散列進行索引。這些索引在其范圍內(nèi)的值分布更加隨機季惯,但只支 持相等匹配吠各,不支持基于范圍的查詢。
2 索引管理
2.1 查詢索引
返回一個集合中的所有索引的數(shù)組
db.collection.getIndexes()
結(jié)果中顯示的是默認(rèn) _id 索引勉抓。
默認(rèn)_id索引:
MongoDB在創(chuàng)建集合的過程中贾漏,在 _id 字段上創(chuàng)建一個唯一的索引,默認(rèn)名字為 id 藕筋,該索引可防止客戶端插入兩個具有相同值的文 檔纵散,您不能在_id字段上刪除此索引。
注意:該索引是唯一索引隐圾,因此值不能重復(fù)伍掀,即 _id 值不能重復(fù)的。在分片集群中暇藏,通常使用 _id 作為片鍵
2.2 創(chuàng)建索引
在集合上創(chuàng)建索引蜜笤。
db.collection.createIndex(keys, options)
參數(shù):
options(更多選項)列表:
提示:
注意在 3.0.0 版本前創(chuàng)建索引方法為 db.collection.ensureIndex() ,之后的版本使用了 db.collection.createIndex() 方法盐碱, ensureIndex() 還能用把兔,但只是 createIndex() 的別名沪伙。
【示例】
(1)單字段索引示例:對 userid 字段建立索引:
db.comment.createIndex({userid:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
(2)復(fù)合索引:對 userid 和 nickname 同時建立復(fù)合(Compound)索引:
db.comment.createIndex({userid:1,nickname:-1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
2.3 索引的移除
可以移除指定的索引,或移除所有索引
2.3.1 指定索引的移除
db.collection.dropIndex(index)
【示例】
刪除 comment 集合中 userid 字段上的升序索引:
db.comment.dropIndex({userid:1})
查看已經(jīng)刪除了
2.3.2 所有索引的移除
db.collection.dropIndexes()
2.4 索引的使用
2.4.1 執(zhí)行計劃
分析查詢性能(Analyze Query Performance)通常使用執(zhí)行計劃(解釋計劃垛贤、Explain Plan)來查看查詢的情況焰坪,如查詢耗費的時間、是否基于索引查詢等聘惦。
那么某饰,通常,我們想知道善绎,建立的索引是否有效黔漂,效果如何,都需要通過執(zhí)行計劃查看
db.collection.find(query,options).explain(options)
【示例】
查看根據(jù)userid查詢數(shù)據(jù)的情況:
db.comment.find({userid:"1003"}).explain()
關(guān)鍵點看: "stage" : "COLLSCAN", 表示全集合掃描
下面對userid建立索引
> db.comment.createIndex({userid:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
再次查看執(zhí)行計劃,關(guān)鍵點看: "stage" : "IXSCAN" ,基于索引的掃描