2015-07-11 79 views
2

我想弄清楚如何處理這種情況。最終應該是日期範圍。爲什麼這個mongo查詢會這麼慢?

db.article_raw.count({ 
    "date": {$gt:ISODate("2015-07-08T00:00:00.000Z")}, 
    "searchTerms.term":"iPhone" 
}) 

我有以下3個指標(我知道是重複的,但我試圖弄明白)

{ 
    "date" : 1, 
    "searchTerms.term" : 1 
} 

{ 
    "date" : 1 
} 

{ 
    "searchTerms.term" : 1 
} 

的數據看起來像

{ 
    title: "a cool title", 
    date: ISODate("2015-07-09T11:58:36.000Z"), 
    "searchTerms" : [ 
     { 
      "term" : "According to Jim", 
      "relevance" : "0.315" 
     }, 
     { 
      "term" : "iPhone", 
      "relevance" : "0.057" 
     } 
    } 
} 

最後,這是explain()對find()版本的結果。

{ 
    "cursor" : "BtreeCursor date & search", 
    "isMultiKey" : true, 
    "n" : 275, 
    "nscannedObjects" : 275, 
    "nscanned" : 11022, 
    "nscannedObjectsAllPlans" : 16142, 
    "nscannedAllPlans" : 26889, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 1074, 
    "nChunkSkips" : 0, 
    "millis" : 59548, 
    "indexBounds" : { 
     "date" : [ 
      [ 
       ISODate("2015-07-08T00:00:00.000Z"), 
       Date(9223372036854775807) 
      ] 
     ], 
     "searchTerms.term" : [ 
      [ 
       "iPhone", 
       "iPhone" 
      ] 
     ] 
    }, 
    "server" : "...", 
    "filterSet" : false, 
    "stats" : { 
     "type" : "FETCH", 
     "works" : 11023, 
     "yields" : 1074, 
     "unyields" : 1074, 
     "invalidates" : 90, 
     "advanced" : 275, 
     "needTime" : 10746, 
     "needFetch" : 1, 
     "isEOF" : 1, 
     "alreadyHasObj" : 0, 
     "forcedFetches" : 0, 
     "matchTested" : 0, 
     "children" : [ 
      { 
       "type" : "IXSCAN", 
       "works" : 11022, 
       "yields" : 1074, 
       "unyields" : 1074, 
       "invalidates" : 90, 
       "advanced" : 275, 
       "needTime" : 10746, 
       "needFetch" : 0, 
       "isEOF" : 1, 
       "keyPattern" : "{ date: 1, searchTerms.term: 1 }", 
       "isMultiKey" : 1, 
       "boundsVerbose" : "field #0['date']: (new Date(1436313600000), new Date(9223372036854775807)], field #1['searchTerms.term']: [\"iPhone\", \"iPhone\"]", 
       "yieldMovedCursor" : 0, 
       "dupsTested" : 275, 
       "dupsDropped" : 0, 
       "seenInvalidated" : 0, 
       "matchTested" : 0, 
       "keysExamined" : 11022, 
       "children" : [] 
      } 
     ] 
    } 
} 

如果這些索引是正確的,我看不到這個查詢如何運行80秒。系統中有近百萬篇文章。而這個計數的結果是大約250.

+2

你應該考慮使用'[searchTerms.term,date]'索引;在範圍匹配之前執行精確匹配總是可取的。 –

+0

你能提供.explain(true)的結果嗎? –

+0

機器有多少內存以及您使用的是哪種版本的mongo。 – ThrowsException

回答

0

這似乎是預期的行爲肖恩在一個大型的數據集,索引是由於高基數創建日期。如果列值有數百萬個不同的值(因爲日期是精確的,直到毫秒和它的大多數不相同),那麼MongoDB現在使用B(alance) - 樹索引,然後最終使用索引但它沒有給出任何好處在這種情況下的索引。 通常在這種情況下,您必須根據某個日期範圍查找數據,因此,您最好多列一列,其中只包含應用索引的日期部分並在查詢條件中使用該日期部分,這可能有助於提高業績大大的...

- $

+0

即使是做日期範圍,如$ GT這仍然適用? –

+0

是的,在任何種類的條件檢查它必須旅行,並決定哪個節點去...我的意思是,在美元GT條件也使用日期指數也建議解釋計劃,但它沒用,因爲高基數。散列索引是唯一用於相等性檢查並且在範圍檢查的情況下被忽略的索引,因爲它們依賴於散列。 –

+0

此外,現在我看到了所有的評論..克里斯孤獨是完美的,指數順序非常imp。,在你的情況下,它會首先嚐試匹配由於高基數慢,然後該術語,但如果ü逆該命令然後首先它會立即找到iPhone這個詞,然後在這些有限的數據集中,它會檢查日期條件,肯定會比你最初做的更快......但我會建議去通過額外的日期只是部分n在術語中創建一個索引:1,date_part:1,這樣做會使得在更大的數據集中搜索得更快,比較ur curnt one –