30-11之MongoDB索引(1)的哩哩扣扣
IT 鐵人賽 2016 mongodb
Lastmod: 2019-12-14

本篇文章將會說明以下幾點。

  • 什麼是索引?
  • 索引的優點與缺點
  • 索引的建立
  • 索引與非索引搜尋比較
  • 不要使用索引的時機

P.S +u^11鐵人們 ~ 事實上我已快gg了

~ 什麼是索引? ~

索引是什麼?最常見的說法是,一本字典中,你要找單字,會先去前面的索引找他在第幾頁,是的這就是索引,可以幫助我們更快速的尋找到document,下面畫張圖來比較一下不使用索引和使用索引的搜尋概念圖。

~ 索引的優缺點 ~

索引竟然可以幫助我們著麼快的找到目標,那是不是以後都用索引就好??著麼可能!~ 索引好歸好,但他就像雙刃刀,用的不好會gg的。

優點

  • 搜尋速度更(飛)快 ~
  • 在使用分組或排度時更快 ~

缺點

  • 每次進行操作(新增、更新、刪除)時,都會更費時,因為也要修改索引。
  • 索引需要佔據空間。

使用時機

所以根據以上的優缺點可知,不是什麼都要建立索引的,通常只有下列時機才會使用。

  • 搜尋結果佔原collection越小,才越適合(下面會說明更清楚)。
  • 常用的搜尋。
  • 該搜尋造成性能瓶頸。
  • 在經常需要排序的搜尋。
  • 當索引性能大於操作性能時。

~ 索引的建立 ~

我們簡單建立個索引使用範例。

db.tests.insert( {"x" : "hello"} )

然後這時我們建立x欄位的索引。

db.tests.ensureIndex({ "x" : 1 })

然後我們可以達行下列指令,來查看有沒有建立成功。

db.tests.getIndexs()

結果如下,建立成功x的索引,其中_id那個是預設的,mongodb會自動幫objectId建立索引。

~ 索引與非索引搜尋比較 ~

mongodb中排序是非常的耗費內存資源,如果排序時內存耗費到32mb(這裡),mongodb就會報錯,如果超出值,那麼必須使用索引來獲取經過排序的結果。

我們這裡建立些資料,來比較看看兩者的資源耗費不同點。

for (var i=0;i<100000;i++){
	db.test.insert({
		"x" : i
	})
}

然後建立x的索引。

db.test.ensureIndex({ "x" : 1 })

然後我們在有索引與無索引的情況下指行下列指令。

db.test.find({ "x" : {"$gt" : 50000}})
		.sort({"x" : -1})
		.explain("executionStats")

首先來看看無索引的,可知它耗用了不少的內存,並且速度也比較慢。

在來看看有索引的,由於有使用到索引進行排序,所以不需要在內存中進行排序。

從上面兩張圖的結果可知有用索引的速度較快,也較省內存,但要注意並不是建立了索引就代表它一定會用索引排序,這在下一章複合索引會提到。

~ 不要使用索引的時機 ~

我們這邊將使用時機的搜尋結果佔原collection越小,才越適合來進行分析一下。

我們來試試結果佔原collection比大於60%會如何

我們這邊將要來驗證一下,在這種情況下,索引搜尋和全文搜尋(未使用索引)那個比較快。

首先來建立資料一百萬筆,然後有60%x都為1

for (var i=0;i<1000000;i++){
	var value = (i<600000)?"1":"2" ;
	db.test.insert({
	  "x" : value
	})
}

然後建立x的索引。

db.test.ensureIndex({ "x" : 1 })

然後我們來比較看看兩者的搜尋速度,我們要尋找x1的。

首先看看沒有用索引的速度,嗯…418ms

在來看看有索引的速度,嗯…657ms

從上面結果可看出有用索引的比較慢,主要原因為他要先去掃索引然後,再去找全文,正常情況下索引會比較快,但是如果結果原collection比過多時就會發生索引反而比較慢。

所以記好當你要找的結果可能會佔你原資料太多部份的,請不要用索引 ~

~結語~

索引是一把雙刃刀,用的好的話效能非常的好,用的不好就和大便一樣,所以要學好~

~參考資料~

comments powered by Disqus