優化一個簡單的例子mongodb
這部分主要講解如何優化MongoDB的性能。shell
讓咱們舉個具體示例。假使咱們的任務是現實blog的首頁-咱們但願現實最近發佈的10條posts。ts爲時間字段。數據庫
語句以下數組
articles = db.posts.find().sort({ts:-1}); // get blog posts in reverse time orderfor (var i=0; i< 10; i++) { print(articles[i].getSummary());} 優化 #1: 建立索引服務器
第一個優化就是要在ts上建立索引,用來快速排序。網絡
db.posts.ensureIndex({ts:1});app
使用索引,數據庫就能夠基於索引信息排序,不會直接查看每一個document。這樣作更快。
ide
優化#2: 限定結果工具
MongoDB遊標返回一組document,咱們叫這個爲chunks。post
這chunk可能包含超過10個對象。額外的對象對於咱們的需求是浪費,
浪費了網絡帶寬和應用服務器以及數據庫的資源。
咱們知道想要結果的個數,那麼就不須要全部的結果。咱們能夠使用limit()方法
articles = db.posts.find().sort({ts:-1}).limit(10); // 最多10條
如今,咱們從客戶端返回了10條。
優化 #3: 查詢相關的字段
post對象很是大, 如post文本和評論數組。 比較好的方式是隻查詢咱們要用到的字段。
articles = db.posts.find({}, {ts:1,title:1,author:1,abstract:1}).sort({ts:-1}).limit(10); articles.forEach( function(post) { print(post.getSummary()); } );
上面的getSummary()方法假使是能夠得到find()方法返回的字段值
注意,若是你選擇了要查詢的字段,那麼返回的就是部分對象。這個對象並不能直接進行更新。以下
a_post = db.posts.findOne({}, Post.summaryFields); a_post.x = 3; db.posts.save(a_post); // 錯誤,拋出異常使用 Profiler
MongoDB有一個數據庫的 profiler,用來顯示每一個操做的性能。
使用profiler你能夠查看到哪些查詢或者寫入的速度比較慢。
舉個例子,使用這些信息能夠知道何時須要索引。詳情查看 Database Profiler 。
Use count()優化語句
加速語句速度依賴於count(),建立一個索引,調用count()。
db.posts.ensureIndex({author:1}); db.posts.find({author:"george"}).count(); 增量操做Increment Operations
MongoDB 支持簡單對象字段的增量操做;
基本上來講, 這個操做就是 在服務器document中增量一個字段"。
這個要比"獲取一個document,更新這個字段而且在保存會服務器"這個方法快不少,
而且對於實時的計數器更爲有用。詳情請看 Updates 。
固定大小的collection。
MongoDB提供了一個特殊的collection,它提早分配好了存儲空間。
保存的項都是固定順序的,而且沒有索引。並且寫入和讀取是很是高速的。
存儲是爲了保存日誌文件所設置的。詳情查看 Capped Collections
服務端代碼執行Server Side Code Execution
也許有的時候爲了高性能,避免客戶端和服務端來回通訊,須要直接在服務端執行代碼。
這部分查看 Server-Side Processing 。
Explain工具
要想查看查詢語句的詳細性能信息,最好的方法就是使用explain方法。
返回的結果就是整個查詢執行的一些信息。
當使用shell的時候,能夠調用cursor的explain() 方法。
db.collection.find(query).explain();
返回的信息以下
{"cursor" : "BasicCursor", "indexBounds" : [ ], "nscanned" : 57594, "nscannedObjects" : 57594, "nYields" : 2 , "n" : 3 , "millis" : 108, "indexOnly" : false}
nscanned - 掃描的數據條數。這個數據多是對象也多是索引的鍵。 若是"覆蓋索引(covered index)"被調用了,nscanned 要高於nscannedObjects. nscannedObjects - 掃描對象的數。 nYields - 查詢所產生的鎖的個數。 indexOnly - 是否使用了covered index。
Hint
雖然MongoDB查詢優化器通常工做的很不錯,可是也能夠使用hints來強迫MongoDB使用一個指定的索引。
這種方法某些情形下會提高性能。 一個有索引的collection而且執行一個多字段的查詢(一些字段已經索引了)。
傳入一個指定的索引,強迫查詢進行使用。
db.collection.find({user:u, foo:d}).hint({user:1});
|
肯定建立了索引。 上面的例子,首先你肯定索引已經建立了。請使用ensureIndex()建立索引。 |
其餘的例子,有個在 {a:1, b:1} 上的索引,名稱爲"a_1_b_1":
db.collection.find({a:4,b:5,c:6}).hint({a:1,b:1}); db.collection.find({a:4,b:5,c:6}).hint("a_1_b_1");
強迫查詢不適用索引, (作一個表的掃描), 使用:
> db.collection.find().hint({$natural:1})