mongodb指南(翻譯)(二十三) – developer zone – 索引(七)索引最佳化建議

來源:互聯網
上載者:User

首先,mongodb中的索引同MySQL中的很類似,因此很多在MySQL中建立高效索引的技術也適用於mongodb。

再者,而且可能更加重要的是,索引最佳化建議也只能到此為止。對於你的應用,最好的索引依賴於幾個重要的因素,包含你期望的查詢種類,讀/寫頻率,甚至系統的剩餘記憶體。這意味著最好的策略就是對資料集準備多套索引配置方案,然後觀察那個表現最好。

索引策略

這裡有一些建立良好索引的基本原則。

建立匹配查詢的索引

如果你僅對一個關鍵字查詢,那麼使用單鍵索引就可以了。例如,你可能正在搜尋部落格發布的緩動環(slug):

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

在這種情景下,基於單個關鍵字的唯一索引是最好的:

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

但是,對多個關鍵字進行查詢並排序也是很普遍的。在這些時候,複合索引是最合適的。這裡有個例子是中查詢包含最近新加的名為“mongodb”標籤的評論:

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

那麼合適的索引是:

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

需要注意的是,如果我們期望對"created_at"進行升序排序,那麼這個索引的效率會很低。

一個查詢一個索引

有時候我們會認為對多個關鍵字的查詢會使用多個索引;在Mongodb中不是這樣的。如果你的查詢是針對多個關鍵字的,並且你希望提高查詢的效率,那麼建立一個複合索引是很有必要的。

確保你的索引可以駐留在記憶體中

shell提供了一個命令查詢某個集合的索引大小:

db.comments.totalIndexSize();
65443

留意低效率的單鍵索引

假定你有一個欄位名為“status”,它的值為“new”或者“processeed”。如果你對它建立一個索引,其效率會很低,這意味著該索引在定位記錄上協助不大並且可能會佔用很多空間。
一個更好的方法,當然依賴於你的查詢,建立包含低效率欄位的複合索引。例如,你可以對"status"和"created_at"建立複合索引。

另一個選擇,同樣也依賴於你的用例,可以使用分開的集合,為每一種狀態建立一個集合。已經有了這麼多的建議,實驗和基準測試可以幫你選擇最好的。

使用explain

Mongodb有一個explain命令查看你的查詢如何被執行,特別是有沒有使用到一個索引。
可以在驅動中使用explain,也可以在shell中:

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

這會返回很多有用的資訊,包含掃描的對象個數,查詢耗費時間(單位毫秒),嘗試使用的索引,最終使用的索引。

如果你從來沒有使用過explain,那麼現在是時候了。

理解explain的輸出

這裡有explain命令輸出的三個主要欄位:

  • cursor:cursor的值可以是BasicCursor或BtreeCursor。第二個值指明使用的索引。
  • nscanned:掃描的文檔個數。
  • n:查詢返回的文檔個數。你需要使得n與nscanned非常接近。需要避免的情況是,查詢掃描了集合中所有的文檔。這種情況下nscanned等於集合中文檔個數。
  • millis:查詢耗費時間。

關注你的應用中讀/寫比率

它之所以重要,是因為當你添加一個索引,你就會對所有的插入、更新、刪除操作都額外增加了負擔。如果你的應用是讀繁忙類型,如多數web應用,增加的索引通常是個好東西。但是如果你的應用是寫繁忙類型的,增加索引時要特別小心,因為每個索引都會對寫操作增加一定的負擔。

通常情況下,不要害怕增加索引。索引通常應當增加以完成你的查詢。記住總是有一個好的理由添加一個新的索引,並確保你已經比較了替代策略。

索引特性

這些例子假定一個基於三個欄位的複合索引: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. 範圍查詢也必須是索引的最後列。這是上面1中的一個原則。

好:

  • find(a=1,b>2)
  • find(a>1 and a<10)
  • find(a>1 and a<10).sort(a)

不好:

  • find(a>1,b=2)

3. 僅對一個列進行範圍查詢和排序

好:

  • find(a=1,b=2).sort(c)
  • find(a=1,b>2)
  • find(a=1,b>2 and b<4)
  • find(a=1,b>2).sort(b)

不好:

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

4.通過對相等性(無範圍)查詢的列進行重排序來節約索引

假定你有兩個查詢:

  • find(a=1,b=1,d=1)
  • find(a=1,b=1,c=1,d=1)

一個基於a,b,c,d的單個索引就可以滿足這兩個查詢了。

如果,你需要對最後的值進行排序,你就可能需要2個索引了。

5. Mongodb的$ne和$nin操作符,使用索引是沒有效率的

  • 當需要排序少量文檔時,最好將資料讀到用戶端後進行排除。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.