2012-04-11 92 views
2

我正在運行一個非常普通的MongoDB查詢,沒有什麼真正的複雜或特殊的,我想知道如果它需要的時間(> 1秒)是正常的,或者如果我的索引有問題。優化MongoDB查詢或索引

我爲這個特定的查詢提供了一個索引,explain()也告訴我它已經被使用了,但是它每次都會對這個集合進行全面掃描,並且整個網頁速度減慢大於1秒。

查詢:

db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"}) 

解釋:

> db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"}).explain() 
{ 
    "cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1", 
    "nscanned" : 21306, 
    "nscannedObjects" : 21306, 
    "n" : 21306, 
    "millis" : 1180, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 
     "art_filter" : [ 
      [ 
       null, 
       null 
      ] 
     ], 
     "art_hauptartikelnr" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ] 
    } 
} 

指數:

{ 
    "v": 1, 
    "key": { 
    "art_filter": 1, 
    "art_hauptartikelnr": 1 
    }, 
    "ns": "togshop.tog_artikel", 
    "background": true, 
    "name": "art_filter_1_art_hauptartikelnr_1" 
} 

爲什麼全額徵收掃描的每一次?爲什麼isMultiKey是錯誤的,我該如何優化這個查詢/索引?

環境是一個獨立的服務器,MongoDB的2.0.1,64位Linux,訪問從PHP瓦特/ PHP-1.2.6蒙哥

回答

7

爲什麼全額徵收掃描的每一次?

不是。這是要通過指數:

"cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1", 

這意味着指數「art_filter_1_art_hauptartikelnr_1」用於滿足$存在條件。

如果該過濾器不是非常有選擇性的(即有很多記錄滿足它),查詢仍然需要很長時間。

爲什麼isMultiKey假

,因爲沒有使用多鍵索引它是假的。多鍵索引是一個索引,其中包含數組作爲值的字段。它與組合索引無關(即有多個字段)。

$where":"this._id == this.art_hauptartikelnr" 

你的第二個條件是一個JavaScript表達式和索引不能在這裏使用(因爲查詢分析器不明白你在做什麼)。 即使這樣做,您也需要一個包含_id的索引。

我該如何優化這個查詢/索引?

非規範化您的數據,使其具有值爲true或false的新字段「idIsHauptArtikelNr」。 創建上(art_filter,idIsHauptArtikelNr)的索引,並將其替換您的查詢

{ art_filter :{ $exists :false}, idIsHauptArtikelNr : true } 
+2

我將添加到,雖然存在$不使用索引,這些天它仍然走大部分的B樹來滿足它。換句話說,在性能方面,您設法在一個查詢中使用兩個最糟糕的操作($ exists和$ where)。 – 2012-04-11 12:38:42

+2

@RemonvanVliet:我剛纔提到,但後來我認爲存在$存在:在非稀疏索引中false應該是相對有效的(而$ exists:true必須走大部分樹)。 YMMV取決於數據傾斜。 – Thilo 2012-04-11 12:42:27

+1

非常真實。 $ exists:false是由於在樹中行走而提前更有效的方法。無論如何,避免使用$ exists,如果可以的話,通常會更好; $ – 2012-04-11 12:56:14