MongoDB 關於索引的建議

我們收到了很多關於索引的問題。這一部分解答了其中的一小部分。有幾點要記住。

第一,MongoDB索引和MySQL索引非常相似並且對於MySQL的索引優化有很多也適用於MongoDB。 

第二,更重要的是,這些索引的建議對你的應用提高也是有限的。

對於應用的最佳索引策略應該基於很多的重要因素。包含了你期望查詢的類型,

數據讀取與寫入的比率,甚至於你服務器的空閒內存。意思就是,

需要對線上的產品做很多的測試剖析工作,才能調整出最佳的索引策略。

沒有什麼好的方法可以替代實際經驗的。

注意: 如果你是個新手,建議閱讀 read this introductory article first.


索引策略

下面有些索引的基本法則

創建的索引要匹配查詢。

如果你僅僅要查詢單個字段。索引這個字段即可。如

db.posts.find({ slug : 'state-of-mongodb-2010' })

這個例子中,唯一索引是最佳的

db.posts.ensureIndex({ slug: 1 }, {unique: true});

然而,一般都查詢多個鍵並且排序結果。這種情況,組合索引是最佳的,例子如下

db.comments.find({ tags : 'mongodb'}).sort({ created_at : -1 });

創建的索引如下

db.comments.ensureIndex({tags : 1, created_at : -1});

要注意的是如果我們按照升序排序created_at。索引效率就低下了。

每個查詢一個索引。

有的時候查詢多個鍵,需要多個索引。在MongoDB中,這麼做沒問題。

如果你有個查詢要匹配多個鍵,並且你想更有效地使用索引,請使用組合索引。

要確定所有的索引都在RAM中。

Shell中提供了一個查看索引大小的命令,如下:

db.comments.totalIndexSize();
65443

如果你的查詢有點遲緩,你應該查看下索引是否都存入到RAM中了。

一個實例,如果你運行在4GB的RAM機器並且有3GB的索引,那麼索引可能並不能全存在RAM中。

你需要添加RAM以及/或者校驗實際的索引使用量。

要小心單鍵索引的低選擇性。

假使你有個字段叫做'status',就有兩個值new和processed。

如果在status上創建索引那麼這就是個低選擇性的索引。

意味着,查詢中沒有什麼優勢並且還佔大量的空間。

一個更好一點的策略,當然依賴具體查詢需求,可以創建組合索引包括這個低選擇性的字段。

舉例來說,你可以創建一個組合索引在status和created_at字段上。

另一個選擇,當然也依賴你的需求,可以分離collection, 一個狀態一個。

當然這些建議一定要進行測試,選擇最優的方案。

使用explain.
MongoDB提供了一個explain命令,
用來查看查詢的過程並且可以查看是否使用縮影。explain可以在驅動中使用,也可以在SHELL中使用:
db.comments.find({ tags : 'mongodb'}).sort({ created_at : -1 }).explain();
返回了很多有用的信息。包含了檢索的條數,消耗的毫秒數,優化器嘗試的索引以及最終所使用的索引。

如果你從來沒有使用過explain,請開始使用吧。

理解explain的 輸出.

explain輸出主要有三個字段:

  • cursor: 遊標不是 BasicCursor就是 BtreeCursor. 第二種意味着使用了索引。
  • nscanned: 掃描document的行數。
  • n: 查詢返回的行數。你希望n的值和nsanned值接近。要避免做collection的掃描,
  • 也就是訪問所有的document。
  • millis: 查詢完成的毫秒數。這個對於比較索引和非索引性能非常有用。
要關注應用讀/寫( read/write) 比率

這個很重要,因爲,添加索引意味着添加,更新,刪除操作變慢。

如果你的應用是偏向於讀取,使用索引是非常好的事情。

但是如果你的應用偏向於寫,那麼創建索引就要小心了。增加索引都很影響寫入的性能。

一般來說, 不要隨便添加索引。索引應該按照你的查詢來添加。

添加索引的理由總是很多的, 以及要進行大量的測試選擇合適的索引策略。

索引特性

組合索引有許多特性要記住。

下面的例子都假想在 a, b, c上創建組合索引。因此創建索引語句如下

db.foo.ensureIndex({a: 1, b: 1, c: 1})

 

1. 排序的列一定要在索引的最後。

好的:

  • find(a=1).sort(a)
  • find(a=1).sort(b)
  • find(a=1, b=2).sort(c)

不好的:

  • find(a=1).sort(c)
  • 即使c是索引的最後一列,a列是所使用的最後一列,因此你只能通過a或者b列進行排序。
2,3 ,4在1.6+已經不適用了。推薦使用1.6+以上版本。

5. MongoDB's $ne 或者$nin 操作在索因傷是無效的。
  • 當要排除很少的documents。最好的方法就是在MongoDB查詢出結果,在服務端進行排除。

轉自:http://xiayuanfeng.iteye.com/blog/997767

 
發佈了209 篇原創文章 · 獲贊 76 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章