MongoDB 優化

優化一個簡單的例子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}

現實結果能夠得知cursor的類型,DB掃描的數據數,返回的數據數,還有執行的毫秒數。

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})

相關文章
相關標籤/搜索