mongodb 索引詳解

? ? ? 索引能夠提高數據庫的查詢效率,沒有索引的話,查詢會進行全表掃描(scan every document in a collection),嚴重降低了查詢效率。默認情況下,Mongo在一個集合(collection)創建時,自動地對集合的_id創建了唯一索引。

(NOTE:In sharded clusters, if you do not use the _id field as the shard key, then your application must ensure the uniqueness of the values in the _id field to prevent errors. This is most-often done by using a standard auto-generated ObjectId.)

1.索引的分類

?? 1.1單屬性索引(Single Field)

針對單屬性索引,排序順序無關緊要,因為MongoDB能夠在任意方向來回移動。

(For a single-field index and sort operations, the sort order (i.e. ascending or descending) of the index key does not matter because MongoDB can traverse the index in either direction.)

? ? 單屬性索引示例圖:

詳細信息:https://docs.mongodb.com/manual/core/index-single/

1.2 復合索引(Compound Index)

? ? ?針對單復合索引,索引中key的排序順序決定了索引是否支持排序操作,舉例子:

假如:一個對象包含username和date兩個屬性,如果創建索引如下:

? ? db.events.createIndex( { "username" : 1, "date" : -1 } )

則查詢支持

? ? db.events.find().sort( { username: -1, date: 1 } )

? ? db.events.find().sort( { username: 1, date: -1 } ).

但是不支持如下查詢:

? ? db.events.find().sort( { username: 1, date: 1 } ).

詳細信息:https://docs.mongodb.com/manual/core/index-compound/ 。

1.3 多值索引(Multikey indexes)

? ? 針對屬性包含數組數據的情況,MongoDB支持針對數組中每一個element創建索引,Multikey indexes支持strings,numbers和nested documents。

? 詳細信息:https://docs.mongodb.com/manual/core/index-multikey/? 。

1.4地理空間索引(Geospatial Index):

? ? ? 針對地理空間坐標數據創建索引,類似于oracle geometry類型。

1.5 文本索引(Text Index)

? ? ? MongoDB提供了針對string內容的文本查詢,Text Index支持任意屬性值為string或string數組元素的索引查詢。注釋:一個集合僅支持最多一個Text Index。

詳細信息:https://docs.mongodb.com/manual/core/index-text/

1.6 Hashed Index

? ? ?針對屬性的哈希值進行索引查詢,當要使用Hashed index時,MongoDB能夠自動的計算hash值,無需程序計算hash值。注:hash index僅支持等于查詢,不支持范圍查詢

2.索引屬性

2.1 唯一索引(Unique Indexes)

? 即不允許屬性有重復的屬性值。

2.2部分索引(Partial Indexes)(3.2版本新增)

? ? 對集合中指定的篩選器表達式篩選后的部分集合進行創建索引,優點:減少了存儲空間,提高的查詢效率。

2.3 稀疏索引

? ? 索引只保存一定條目的索引屬性值,跳過沒有被指定屬性;當使用3.2之后的Mongo版本時,應優先考慮Partial Indexes。

(Changed in version 3.2: Starting in MongoDB 3.2, MongoDB provides the option to create partial indexes. Partial indexes offer a superset of the functionality of sparse indexes. If you are using MongoDB 3.2 or later, partial indexes should be preferred over sparse indexes.)

2.4 TTL索引

? ? TTL索引是特殊的索引,MongoDB能夠在指定時間之后自動的刪除集合中的數據,主要應用場景為機器產生的事件數據、日志、會話信息等。

(TTL indexes are special indexes that MongoDB can use to automatically remove documents from a collection after a certain amount of time. This is ideal for certain types of information like machine generated event data, logs, and session information that only need to persist in a database for a finite amount of time.)

詳細信息:https://docs.mongodb.com/manual/core/index-ttl/ 。

3.索引限制

? ? ?3.1 如果MongoDB的索引項超過索引限制,即1024 bytes,MongoDB將不會創建該索引,注:2.6版本之前能夠創建索引,但是不能夠對該documents進行索引;

? ? 3.2 當試圖插入一個包含索引項的屬性超過1024 bytes的documents時,MongoDB將插入documents失敗,并返回錯誤;注:2.6版本之前能夠插入成功,但是不能夠對該documents進行索引;

? ? 3.3 當試圖更新documents的屬性時時,如果索引項的屬性超過1024 bytes的,MongoDB將插入documents失敗,并返回錯誤;注:2.6版本之前能夠插入成功,但是不能夠對該documents進行索引;

? ? 3.4 如果documents存在某索引,其索引屬性超過了索引限制,則任何更新該documents將會失敗;

? ? 3.5 針對分片的collections,當數據遷移時,如果數據塊中包含索引屬性超過了索引限制,數據塊的遷移將會失敗;

3.6 一個collections最多能夠有64個索引;

3.7 針對索引的全名,包含命名空間和“.”分隔符,如:<database>.<collection name>.$<index name>,最多不超過128 characters;

3.8 針對復合索引,包含的索引屬性不能夠超過31個屬性;

3.9 查詢不能夠同時使用文本索引和地理空間索引(Queries cannot use both text and Geospatial Indexes);

3.11 包含2d sphere屬性的索引,只能夠針對地理空間屬性;

3.12 如果通過覆蓋索引查詢得到的屬性值是NaN(Not a Number),則NaN的類型總是double類型;

(If the value of a field returned from a query that is covered by an index is NaN, the type of that NaN value isalways double);

3.13 multikey index不支持covered query。

4.交叉索引

? ? MongoDB可以使用多個索引的交叉來滿足查詢,通常每個交叉索引包含兩個索引,但是MongoDB能夠使用多個或嵌套索引交叉來實現查詢。

4.1 索引前綴交叉

? ? 針對交叉索引,MongoDB能夠使用交叉索引中任意一個索引的整個索引或者索引的前綴,索引前綴是指一個復合索引中索引的子集,由第一個或者前N個索引屬性中的組成;

舉例:

索引項如下:

{ qty: 1 } ?{ status: 1, ord_date: -1 }

MongoDB能夠使用如下索引:

db.orders.find( { qty: { $gt: 10 } , status: "A" } )

4.2 索引交叉與復合索引

? ? 索引交叉并不意味著復合索引沒必要存在,因為屬性在索引中的排列順序和排序方式能夠影響到復合索引,復合索引不支持不包含索引前綴或者不同的排序方式的查詢情況(a compound index may not support a query condition that does not include theindex prefix keys or that specifies a different sort order)

舉例:

如果復合索引如下:

{ status: 1, ord_date: -1 }

復合索引支持如下查詢:

db.orders.find( { status: { $in: ["A", "P" ] } } )

db.orders.find( { ord_date: { $gt: new Date("2014-02-01") }, status: {$in:[ "P", "A" ] } })

但不支持如下查詢:

db.orders.find( { ord_date: { $gt: new Date("2014-02-01") } } )db.orders.find( { } ).sort( { ord_date: 1 } )

但是如果collections包含如下索引:

{ status: 1 } { ord_date: -1 }

這兩個索引,可以通過單獨或者交叉支持以上4中查詢。

4.3 索引交叉和排序

? ? 索引交叉不支持排序操作,即要求一個索引安全的從查詢謂語分離出來的排序;

舉例:collections包含如下索引:

{ qty: 1 }

{ status: 1, ord_date: -1 }

{ status: 1 }

{ ord_date: -1 }

MongoDB不支持如下帶有排序的交叉索引:

db.orders.find( { qty: { $gt: 10 } } ).sort( { status: 1 } )

That is, MongoDB does not use the { qty: 1 } index for the query, and the separate { status: 1 }or the { status: 1, ord_date: -1 } index for the sort.

5. 查詢計劃

?? ? MongoDB查詢優化器執行查詢,并針對現有的索引選擇最高效的查詢計劃,查詢系統在每次查詢執行時使用查詢計劃,查詢優化器僅緩存包含不止一種的可執行計劃的查詢計劃情況。針對每一次查詢,查詢計劃器從查詢計劃緩存中查詢一條滿足query shape的計劃,如果不存在滿足的計劃,查詢計劃器將通過試用一段時間來進行評價,來產生候選查詢計劃。查詢計劃器選擇勝出的計劃,在查詢計劃緩存中創建一個查詢計劃,然后使用該計劃產生查詢結果。

(For each query, the query planner searches the query plan cache for an entry that fits the query shape. If there are no matching entries, the query planner generates candidate plans for evaluation over a trial period. The query planner chooses a winning plan, creates a cache entry containing the winning plan, and uses it to generate the result documents.If a matching entry exists, the query planner generates a plan based on that entry and evaluates its performance through a replanning mechanism. This mechanism makes a pass/fail decision based on the plan performance and either keeps or evicts the cache entry. On eviction, the query planner selects a new plan using the normal planning process and caches it. The query planner executes the plan and returns the result documents for the query)

? ? ?可以使用db.collection.explain()或者 the cursor.explain() 來查看一個查詢的查詢計劃統計數據。

Query shape:即查詢謂語,排序和預測詳細計劃(A combination of query predicate, sort, and projection specifications)。

查詢計劃器的執行邏輯如下:

注釋:

? ? a. Catalog operations(比如index的刪除或collection的刪除)將刷新查詢計劃緩存;

? ? b. 當Mongod重啟或者關閉后,查詢計劃器緩存將不復存在。

6. 索引過濾(Index Filters)

? ? ? Index Filters決定了優化器將為query shape評價那個索引,如果Index Filters中包含了該Index Filters,優化器將僅考慮執行Index Filters指定的索引(When an index filter exists for the query shape, MongoDB ignores the hint(). To see whether MongoDB applied an index filter for a query shape, check the indexFilterSet field of either thedb.collection.explain() or the cursor.explain() method.)

Index Filters僅影響了優化器評價哪一個索引優化器也可能仍然選擇collection 掃描以得到最優查詢計劃。

索引過濾有些類似于Oracle的RBO: Rule-Based Optimization基于規則的優化器;

注釋:

? ? a. 由于Index Filters覆蓋了優化器的預期的行為和hint()方法,所以要有節制的使用index filters;

? ? b. Index filters在MongoDB關閉之后將不復存在,也可以使用命令刪除Index Filters。

7.覆蓋查詢(Covered Queries)

? ? ?當一個查詢的查詢條件和查詢計劃中只包含索引屬性時,MongoDB不需要掃描documents或者將documents調入內存中時,這樣的查詢效率將非常高。

當同時滿足如下兩個條件時,則該查詢是Covered Queries:

? ? ? a. 查詢中的所有屬性都是索引的一部分(all the fields in the query are part of an index);

? ? ? b. 所有查詢到的結果中的屬性值,都在同一個索引中(all the fields returned in the results are in the same index)。

舉例:


(文檔中有寫的有可能不準確的地方,附上了官方的英文,以方便閱讀和糾正)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容

  • 索引(index) 索引 index經常用于常用的查詢,如果設計得好,在創建索引之后的查詢會有提升效率的效果。但是...
    我看不見閱讀 3,279評論 0 6
  • MongoDB 101 參考 documentation - getting-started Documents ...
    xiaofudeng閱讀 370評論 0 1
  • 索引是數據庫中的一個重要對象,主要用于支持高效查詢操作。如果沒有索引,數據庫就只能進行全表掃描,效率將極為低下。m...
    UncleYee閱讀 2,456評論 0 5
  • plotly真是神器哇,極度方便數據觀察 對用戶行為特征數據pca降維(10000+*9->10000+*3)后的...
    RaferYY閱讀 3,999評論 0 0
  • 我特別喜歡狗,因為我喜歡陪伴。 記得在2014年的冬天,是大年三十前一天,叔叔回家過年帶回來幾只狗,暫...
    TaoLock閱讀 211評論 0 0