與MySQL一樣,MongoDB中也使用索引提高查詢效率。那索引是什么呢?索引是⼀種單獨的、物理的對數據庫表中⼀列或多列的值進⾏排序的⼀種存儲結構,它是某個表中⼀列或若⼲列值的集合和相應的指向表中物理標識這些值的數據⻚的邏輯指針清單。索引的作⽤相當於圖書的⽬錄,可以根據⽬錄中的⻚碼快速找到所需的內容。索引⽬標是提⾼數據庫的查詢效率,沒有索引的話,查詢會進⾏全表掃描(scan every document in a collection) ,數據量⼤時嚴重降低了查詢效率。
默認情況下Mongo在⼀個集合(collection)創建時,⾃動地對集合的_id創建了唯⼀索引。MongoDB中索引類型如下:
1、單鍵索引 (Single Field)
MongoDB⽀持所有數據類型中的單個字段索引,並且可以在⽂檔的任何字段上定義。對於單個字段索引,索引鍵的排序順序⽆關緊要,因為MongoDB可以在任⼀⽅向讀取索引。
單個例上創建索引:
db.collection_name.createIndex({"字段名":排序⽅式})
1表示升序,-1表示降序。
需要注意的是:MongoDB中有一個特殊的單鍵索引 ——過期索引 TTL ( Time To Live)。TTL索引是MongoDB中⼀種特殊的索引, 可以⽀持⽂檔在⼀定時間之后⾃動過期刪除,⽬前TTL索引只能在單字段上建⽴,並且字段類型必須是⽇期類型。
db.collection_name.createIndex({"⽇期字段":排序⽅式}, {expireAfterSeconds: 秒數})
2、復合索引(Compound Index)
實際生產中通常需要在多個字段的基礎上搜索表/集合,這是⾮常頻繁的。 如果是這種情況,可能會考慮在MongoDB中制作復合索引。 復合索引⽀持基於多個字段的索引,這擴展了索引的概念並將它們擴展到索引中的更⼤域。
制作復合索引時要注意的重要事項包括:字段順序與索引⽅向。
db.collection_name.createIndex( { "字段名1" : 排序⽅式, "字段名2" : 排序⽅式 } )
3、多鍵索引(Multikey indexes)
針對屬性包含數組數據的情況, MongoDB⽀持針對數組中每⼀個element創建索引, Multikey indexes⽀持strings, numbers和nested documents。
4、地理空間索引(Geospatial Index)
針對地理空間坐標數據創建索引。
1)2dsphere索引,⽤於存儲和查找球⾯上的點
2)2d索引,⽤於存儲和查找平⾯上的點
5、全⽂索引
全文索引是MongoDB提供的專門針對string內容的⽂本查詢, Text Index⽀持任意屬性值為string或string數組元素的索引查詢。需要注意的是:⼀個集合僅⽀持最多⼀個Text Index,中⽂分詞不理想 推薦ES。
db.collection_name.createIndex({"字段": "text"})
db.collection_name.find({"$text": {"$search": "coffee"}})
6、哈希索引 Hashed Index
該索引針對屬性的哈希值進⾏索引查詢,當要使⽤Hashed index時, MongoDB能夠⾃動的計算hash值,⽆需程序計算hash值。
db.collection_name.createIndex({"字段": "hashed"})
注意: hash index僅⽀持等於查詢,不⽀持范圍查詢。
通過以上索引分類,對比MySQL索引分類(MySQL索引原理之索引類型 - 池塘里洗澡的鴨子 - 博客園 (cnblogs.com))差別還是相當大的。
另外通過db.mycoll.help可以查看集合相關的方法。上面已經實踐了索引的建立,那索引的查看、修改、刪除等分別是用什么方法呢?下面揭曉:
創建索引並在后台運⾏
db.collection_name.createIndex({"字段":排序⽅式}, {background: true});
獲取針對某個集合的索引
db.collection_name.getIndexes()
索引的⼤⼩
db.collection_name.totalIndexSize()
索引的重建
db.collection_name.reIndex()
索引的刪除
db.collection_name.dropIndex("INDEX-NAME")
db.collection_name.dropIndexes()
需要注意的是:_id 對應的索引是刪除不了的(這個系統根據_id會自動創建索引)
MongoDB中索引如何實現的呢?關於索引的實現原理與MySQL索引實現原理對比進行分析:MySQL是關系型數據庫,數據的關聯性是⾮常強的,區間訪問是常⻅的⼀種情況,底層索引組織數據使⽤B+樹, B+樹由於數據全部存儲在葉⼦節點,並且通過指針串在⼀起,這樣就很容易的進⾏區間遍歷甚⾄全部遍歷。 MongoDB使⽤B-樹,所有節點都有Data域,只要找到指定索引就可以進⾏訪問,單次查詢從結構上來看要快於MySQL。
對於B-樹及B+樹的結構在MySQL索引原理之索引原理 - 池塘里洗澡的鴨子 - 博客園 (cnblogs.com)已經有詳細的介紹,可以看出最核⼼的區別主要有倆:⼀個是數據的保存位置,⼀個是相鄰節點的指向。就是這倆造成了MongoDB和MySql的差別:
1) B+樹相鄰接點的指針可以⼤⼤增加區間訪問性,可使⽤在范圍查詢等,⽽B-樹每個節點 key 和 data 在⼀起適合隨機讀寫 ,⽽區間查找效率很差。
2) B+樹更適合外部存儲,也就是磁盤存儲,使⽤B-結構的話,每次磁盤預讀中的很多數據是⽤不上的數據。因此,它沒能利⽤好磁盤預讀的提供的數據。由於節點內⽆ data 域,每個節點能索引的范圍更⼤更精確。
3)注意這個區別相當重要, B-樹每個節點即保存數據⼜保存索引導致樹的深度⼤,所以磁盤IO的次數多, B+樹只有葉⼦節點保存,較B樹⽽⾔深度⼩,磁盤IO少,有利於區間訪問。