MongoDB快速上手指南:MongoDB 的索引
4.1 概述
索引支持在 MongoDB 中高效地執(zhí)行查詢.如果沒有索引, MongoDB 必須執(zhí)行全集合掃描, 即掃描集合中的每個文檔, 以選擇與查詢語句 匹配的文檔.這種掃描全集合的查詢效率是非常低的, 特別在處理大量的數(shù)據(jù)時, 查詢可以要花費幾十秒甚至幾分鐘, 這對網(wǎng)站的性能是非常致命的.
如果查詢存在適當?shù)乃饕? MongoDB 可以使用該索引限制必須檢查的文檔數(shù).
索引是特殊的數(shù)據(jù)結(jié)構(gòu), 它以易于遍歷的形式存儲集合數(shù)據(jù)集的一小部分.索引存儲特定字段或一組字段的值, 按字段值排序.索引項的排 序支持有效的相等匹配和基于范圍的查詢操作.此外, MongoDB 還可以使用索引中的排序返回排序結(jié)果.
MongoDB 和MySQL 一樣使用的都是是 B+ Tree
在之前的版本中Mongo使用的是B樹,但是現(xiàn)在都是使用B+樹了
- Mongo官方文檔
- 為什么Mongo選擇過B樹?
索引常用命令:
java copyable" lang="java">// create index
db..createIndex({ userid : 1, username : -1 })
// retrieve indexes
db..getIndexes()
// remove indexes
db..dropIndex(index)
// there are 2 ways to remove indexes:
// 1. removed based on the index name
// 2. removed based on the fields
db..dropIndex( "userid_1_username_-1" )
db..dropIndex({ userid : 1, username : -1 })
// remove all the indexes, will only remove non_id indexes
db..dropIndexes()
復(fù)制代碼
4.2 索引的類型
4.2.1 單字段索引
MongoDB 支持在文檔的單個字段上創(chuàng)建用戶定義的升序/降序索引, 稱為單字段索引(Single Field Index)
對于單個字段索引和排序操作, 索引鍵的排序順序(即升序或降序)并不重要, 因為 MongoDB 可以在任何方向上遍歷索引.
4.2.2 復(fù)合索引
MongoDB 還支持多個字段的用戶定義索引, 即復(fù)合索引 Compound Index,這個其實非常類似MySQL
中的聯(lián)合索引,因為底層都是B+樹,所有聯(lián)合索引可能也有最左原則
這種東西
復(fù)合索引中列出的字段順序具有重要意義.例如, 如果復(fù)合索引由 { userid: 1, score: -1 }
組成, 則索引首先按 userid
正序排序, 然后 在每個 userid
的值內(nèi), 再在按 score
倒序排序.
4.2.3 其他索引
- 地理空間索引 Geospatial Index
- 文本索引 Text Indexes
- 哈希索引 Hashed Indexes
地理空間索引(Geospatial Index)
為了支持對地理空間坐標數(shù)據(jù)的有效查詢, MongoDB 提供了兩種特殊的索引: 返回結(jié)果時使用平面幾何的二維索引和返回結(jié)果時使用球面幾何的二維球面索引.
文本索引(Text Indexes)
MongoDB 提供了一種文本索引類型, 支持在集合中搜索字符串內(nèi)容.這些文本索引不存儲特定于語言的停止詞(例如 “the”, “a”, “or”), 而將集合中的詞作為詞干, 只存儲根詞.
哈希索引(Hashed Indexes)
為了支持基于散列的分片, MongoDB 提供了散列索引類型, 它對字段值的散列進行索引.這些索引在其范圍內(nèi)的值分布更加隨機, 但只支持相等匹配, 不支持基于范圍的查詢.
4.3 索引的管理操作
4.3.1 索引的查看
語法
db.collection.getIndexes()
復(fù)制代碼
提示:該語法命令運行要求是MongoDB 3.0+
【示例】 查看comment集合中所有的索引情況
結(jié)果中顯示的是默認 _id 索引。
默認 _id
索引: MongoDB 在創(chuàng)建集合的過程中, 在 _id
字段上創(chuàng)建一個唯一的索引, 默認名字為 _id
, 該索引可防止客戶端插入兩個具有相同值的文 檔, 不能在 _id
字段上刪除此索引.
注意:該索引是唯一索引, 因此值不能重復(fù), 即 _id
值不能重復(fù)的.
在分片集群中, 通常使用 _id
作為片鍵.
4.3.2 索引的創(chuàng)建
語法
db.collection.createIndex(keys, options)
復(fù)制代碼
參數(shù)
options(更多選項)列表
注意在 3.0.0 版本前創(chuàng)建索引方法為 db.collection.ensureIndex()
, 之后的版本使用了 db.collection.createIndex()
方法, ensureIndex()
還能用, 但只是 createIndex()
的別名.
舉個
userid:1
表示由userid
按照升序創(chuàng)建索引,userid:1,nickname:-1}
表示先按userid升序,如果userid相等再按照nickname降序創(chuàng)建索引,這里和MySQL一摸一樣
// 先由userid按照升序創(chuàng)建索引
$ db.comment.createIndex({userid:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
// 先按userid升序,如果userid相等再按照nickname降序創(chuàng)建索引
$ db.comment.createIndex({userid:1,nickname:-1})
...
復(fù)制代碼
4.3.3 索引的刪除
語法
# 刪除某一個索引
$ db.collection.dropIndex(index)
# 刪除全部索引
$ db.collection.dropIndexes()
復(fù)制代碼
其中index
類型為:string or document,表示指定要刪除的索引??梢酝ㄟ^索引名稱或索引規(guī)范文檔指定索引。若要刪除文本索引,請指定索引名稱。
提示:
_id
的字段的索引是無法刪除的, 只能刪除非 _id
字段的索引
示例
# 刪除 comment 集合中 userid 字段上的升序索引
$ db.comment.dropIndex({userid:1})
復(fù)制代碼
4.4 索引使用
4.4.1 執(zhí)行計劃
分析查詢性能 (Analyze Query Performance) 通常使用執(zhí)行計劃 (解釋計劃 - Explain Plan) 來查看查詢的情況
$ db..find( query, options ).explain(options)
復(fù)制代碼
比如: 查看根據(jù) user_id
查詢數(shù)據(jù)的情況
未添加索引之前
"stage" : "COLLSCAN"
, 表示全集合掃描
添加索引之后
"stage" : "IXSCAN"
, 基于索引的掃描
4.4.2 覆蓋索引查詢(Covered Queries)
這里如果直接看的話其實還是滿難理解的,但是如果我們結(jié)合MySQL
來看就會發(fā)現(xiàn),這不就是MySQL里面的覆蓋索引嗎?覆蓋索引不就是減少了回表操作嗎?這樣的話其實一下就能理解下面的介紹,看來知識都是相通的,還是應(yīng)該多學底層,應(yīng)用層的東西會變,但是底層的東西大部分都不會改變,你看AVL
樹、紅黑樹
這些數(shù)據(jù)結(jié)構(gòu),都是上個世紀中期產(chǎn)生的,現(xiàn)在用的還是這一套
當查詢條件和查詢的投影僅包含索引字段時, MongoDB 直接從索引返回結(jié)果, 而不掃描任何文檔或?qū)⑽臋n帶入內(nèi)存, 這些覆蓋的查詢十分有效
docs.mongodb.com/manual/core…
例如我們查詢下面的索引執(zhí)行計劃:
作者:是小梁同學呀
鏈接:https://juejin.cn/post/7126746699527094303
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
版權(quán)聲明:
本站所有文章和圖片均來自用戶分享和網(wǎng)絡(luò)收集,文章和圖片版權(quán)歸原作者及原出處所有,僅供學習與參考,請勿用于商業(yè)用途,如果損害了您的權(quán)利,請聯(lián)系網(wǎng)站客服處理。