MongoDB索引使用總結(jié)
背景MongoDB 是目前最流行的文檔型數(shù)據(jù)庫。MongoDB 的采用類 json 的存儲格式對開發(fā)者來說非常友好。本文梳理了 MongoDB 索引的底層結(jié)構(gòu)以及使用經(jīng)驗,不足之處歡迎大家指正。
MongoDB 提供范圍廣泛的索引類型和功能以及特定于語言的排序順序,以支持對數(shù)據(jù)的復(fù)雜訪問模式。 MongoDB 索引可以按需創(chuàng)建和刪除來適應(yīng)不斷變化的應(yīng)用程序需求和查詢模式,并且可以在文檔中的任何字段上聲明,包括嵌套在數(shù)組中的字段。本文介紹一下 MongoDB 中的索引底層結(jié)構(gòu)、索引遍歷過程、建索引以及如何使用。
基本使用
分類
MongoDB 中的索引與其他數(shù)據(jù)庫系統(tǒng)中的索引類似。 MongoDB 在集合級別定義索引,并支持 MongoDB 集合中文檔的任何字段或子字段的索引。 常見的有以下類型: 鍵索引、復(fù)合索引、多鍵索引、地理空間索引、全文本索引和哈希索引。
創(chuàng)建/刪除/隱藏
- MongoDB 使用 createIndex 方法來創(chuàng)建索引:`db.collection.createIndex(keys, options)`
語法中 Key 值為你要創(chuàng)建的索引字段,1 為指定按升序創(chuàng)建索引,如果你想按降序來創(chuàng)建索引指定為 -1 即可。`db.col.createIndex({"a":1})`
createIndex 方法中你也可以設(shè)置使用多個字段創(chuàng)建索引(關(guān)系型數(shù)據(jù)庫中稱作復(fù)合索引)。db.col.createIndex({"a":1,"b":-1})
- 刪除索引:db.collection.dropIndex
刪除索引在底層直接刪除文件,然后修改元數(shù)據(jù)
- 從 4.4 開始支持隱藏索引db.collection.hideIndex()
在刪除索引前,可以先隱藏索引,查看集群是否異常后,才真正刪除索引, 可有效幫助業(yè)務(wù)判斷索引是否可以刪除。
底層文件存儲
MongoDB 底層是如何存儲數(shù)據(jù)的,一個 collection 一個文件嗎?索引在底層是如何組織的? 一個 collection 對應(yīng)到底層存儲引擎就是一個文件,另外每個索引也是單獨的文件,每個數(shù)據(jù)和索引文件的默認(rèn)結(jié)構(gòu)是 b 樹,用戶建表的時候也可以指定 lsm 結(jié)構(gòu),不過絕大多數(shù)用戶基本都是使用 b 樹結(jié)構(gòu),本文的討論主要圍繞 b 樹這種結(jié)構(gòu)來進(jìn)行。
比如用戶建一個普通的表,默認(rèn)會帶一個_id 索引,會產(chǎn)生倆個文件,一個文件存放數(shù)據(jù),一個存放_id 索引,這倆個文件通過 RecordId 來連接,用戶每插入一條數(shù)據(jù),mongo 會生成一條與之對應(yīng)的自增的 RecordId, 不過用戶不感知,RecordId 是與 MySQL 中的自增主鍵類似。數(shù)據(jù)文件是 RecordId 到數(shù)據(jù)的映射, _id 索引文件是_id 到 RecordId 的映射,如果通過指定_id 查詢,會現(xiàn)在_id 索引文件中找到 RecordId, 然后再到數(shù)據(jù)文件中查詢數(shù)據(jù),如果用戶再新建索引,那么在 wt 就會再新建一個文件,同樣按 b 樹組織,該文件記錄了索引到 RecordId 的映射,用戶使用索引查詢時,同樣的如同_id 索引,先找到 RecordId, 然后再到數(shù)據(jù)文件中查詢數(shù)據(jù)。
可以通過以下方式查找數(shù)據(jù)對應(yīng)的RecordId PRIMARY> db.coll.find.showRecordId { "_id" : ObjectId("647861f72b531acaacf4afb2"), "a" : 1, "b" : 1, "$recordId" : NumberLong(1) } { "_id" : ObjectId("647861fa2b531acaacf4afb3"), "a" : 1, "b" : 2, "$recordId" : NumberLong(2) }
底層格式存儲
在 MongoDB 的 Schema-free 架構(gòu)下,索引字段可以存儲不同類型的值,在索引 b 樹中,有個基本的問題,實現(xiàn)不同類型的比較呢? MongoDB 通過 BSON 結(jié)構(gòu)來存儲數(shù)據(jù),具體結(jié)構(gòu)的解析可見BSON 結(jié)構(gòu)解析 ,并且規(guī)定了不同類型之間的大小關(guān)系。
1. MinKey (internal type) 2. Null 3. Numbers (ints, longs, doubles, decimals) 4. Symbol, String 5. Object 6. Array 7. BinData 8. ObjectId 9. Boolean 10. Date 11. Timestamp 12. Regular Expression 13. MaxKey (internal type)
在這個限制下, 就只需要對比同種類型的大小了,BSON 的基本比較流程如下:先比較類型,如果類型一樣才使用 BSONElement::compareElements 比較值。
但是對于索引如果直接使用上述方法去做大小比較,具有以下的倆個缺點: