MongoDB实战指南(二):索引与查询优化
數據庫保存記錄的機制是建立在文件系統(tǒng)上的,索引也是以文件的形式存儲在磁盤上,在數據庫中用到最多的索引結構就是B樹。盡管索引在數據庫領域是不可缺少的,但是對一個表建立過多的索引會帶來一些問題,索引的建立要花費系統(tǒng)時間,同時索引文件也會占用磁盤空間。如果并發(fā)寫入的量很大,每個插入的文檔都要建立索引,可想而知,性能會較低。因此合理的建立索引是關鍵,搞清楚哪些字段上面需要建立索引,索引以什么樣的方式建立,我們需要對每個查詢過程進行分析,才能得出合理的結論。
1. 索引
在MongoDB上面,索引能夠提高讀操作及查詢性能。沒有索引,Mongodb必須掃描集合中的每一個文檔,然后選擇與查詢條件匹配的文檔,這種全表掃描的方式是非常低效的。MongoDB索引的數據結構也是B+樹,它能夠存儲一小部分集合的數據,集體來說就是存儲集合中建有索引的一個或多個字段的值,而且按照值的升序或者降序排列。對于一個查詢來說,如果存在合適的索引,MongoDB能夠利用這個索引減少文檔的掃描數量,甚至對于某些查詢能夠直接從索引中返回結果,不需要再去掃描數據集合,這種查詢是非常高效的。
1.1 單字段索引
MongoDB默認為所有集合都建立了一個_id字段的單字段索引,而且這個索引是唯一的,不能被刪除,_id字段作為一個集合的主鍵,值是唯一的,對于一個集合來說,也可以在其他字段上創(chuàng)建單字段的唯一索引,如下面所述。
先插入一些數據:
> for(var i=1;i<10;i++){db.customers.insert({"name":"jordan"+i,"country":"American"})} > for(var i=1;i<10;i++){db.customers.insert({"name":"gaga"+i,"country":"American"})} > for(var i=1;i<10;i++){db.customers.insert({"name":"ham"+i,"country":"UK"})} > for(var i=1;i<10;i++){db.customers.insert({"name":"brown"+i,"country":"UK"})} > for(var i=1;i<10;i++){db.customers.insert({"name":"ramda"+i,"country":"Malaysia"})}下面建立單字段唯一索引
> db.customers.ensureIndex({name:1},{unique:true})單字段唯一索引去掉{unique:true}選項就是一個普通的單字段索引。
唯一索引創(chuàng)建成功后,會在相應數據庫的系統(tǒng)集合system.indexs中增加一條索引記錄,如下所示:
> db.system.indexes.find()最后一條畫紅線的是剛剛添加的唯一索引。索引記錄中v表示索引的版本;key表示索引建立在哪個字段上;1表示索引按照升序排列;索引記錄所在的命名空間,name表示唯一索引的名稱。唯一索引與普通索引的區(qū)別是要求插入的所有記錄在創(chuàng)建索引的鍵值上唯一。
下面執(zhí)行查詢,一個用索引字段作為查詢選擇器;一個不用索引字段作為查詢選擇器進行比較。
> db.customers.find({"name":"ramda9"}).explain()以上查詢語句執(zhí)行返回的結果用到了剛剛創(chuàng)建的索引:
> db.customers.find({"country":"Malaysia"}).explain()以上查詢語句執(zhí)行返回的結果沒有用到剛剛創(chuàng)建的索引。
1.2 復合索引
MongoDB支持多個字段的復合索引,復合索引支持匹配多個字段的查詢。
給上面插入的數據創(chuàng)建一個復合索引:
> db.customers.ensureIndex({name:1,country:1})1.3 數組的多鍵索引
如果對一個值為數組類型的字段創(chuàng)建索引,則會默認對數組中的每一個元素創(chuàng)建索引。
1.4 索引管理
通過上面創(chuàng)建的索引可以看到,索引記錄都保存在特殊的集合system.indexs中。創(chuàng)建索引的語法如下所示:
>db.collection.ensureIndex(keys,options)keys是一個document文檔,包含需要添加索引的字段和索引的排序方向;option是可選參數,控制索引的創(chuàng)建方式。
索引的刪除并不是直接找到索引所在的集合system.indexs,通過在集合上執(zhí)行remove命令來刪除,而是通過執(zhí)行集合上的命令dropIndex來刪除的。例如刪除上面創(chuàng)建的如下復合索引。
> db.customers.dropIndex("name_1_country_1")其中參數為索引的名稱。
2. 查詢優(yōu)化
查詢優(yōu)化的目的是找出慢的查詢語句,分析慢的原因,然后優(yōu)化此查詢語句。
Mongodb對于超過100ms的查詢語句,會自動地輸出到日志文件里面,因此找出慢查詢的第一步是查看MongoDB的日志文件,如果覺得這100ms閾值過大,可以通過mongod的服務啟動選項showms來設置,它的默認值是100ms。
用上面的方法找出慢查詢可能比較粗糙,第二種定位慢查詢的方法是打開數據庫的監(jiān)視功能,它默認是關閉的,可以通過下面的命令打開。
db.setProfilingLevel(level,[slowms])參數level是監(jiān)視級別,值為0表示關閉數據庫的監(jiān)視功能,為1表示只記錄慢查詢,為2表示記錄所有操作;slown為可選參數,設定慢查詢的閾值。
所有監(jiān)視的結果都將保存到一個特殊的集合systemn.profile中。
通過上面的兩種方法可以找出慢查詢的語句,然后通過建立相應的索引基本可以解決絕大部分的問題。但是有時我們需要更加精細的優(yōu)化代碼,這就需要分析這些慢查詢的執(zhí)行計劃,查看查詢是否用到索引,是否與我們想要的執(zhí)行計劃相同,用Mongodb的explian命令可以查看執(zhí)行計劃。
轉載于:https://www.cnblogs.com/longshiyVip/p/5095935.html
總結
以上是生活随笔為你收集整理的MongoDB实战指南(二):索引与查询优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 映像劫持技术(2):实例
- 下一篇: WinForm - 两个窗体之间的方法调