2015-06-15 25 views
2

我已經得到了50個文檔(試行目的)或多或少像MongoDB的這一個:爲什麼查詢掃描發現8X倍的文件 -

"_id" : ObjectId("5461c8f0426f727f16010000"), 
    "f" : [ 
     { 
      "t" : "ry", 
      "v" : 1972 
     }, 
     { 
      "t" : "g", 
      "v" : [ 
       "Crime", 
       "Drama" 
      ] 
     }, 
     { 
      "t" : "ml", 
      "v" : "English" 
     }, 
     { 
      "t" : "k", 
      "v" : "movie" 
     }, 
     { 
      "t" : "ai", 
      "v" : 972353 
     }, 
     { 
      "t" : "ec", 
      "v" : 46 
     }, 
     { 
      "t" : "rel", 
      "v" : true 
     } 
    ] 
} 

我做了如下指標:

{ 
    "f.t" : 1, 
    "f.v" : 1 
} 

所以,我提出以下查詢:

db.items.find( 
    { 
     "$and": [ 
      {"f": {$elemMatch: {"t": "ry", "v": {$gt: 1980, $lt: 2000}}}}, 
      {"f": {$elemMatch: {"t": "g", "v": {$in: ["Drama"]}}}}, 
         {"f": {$elemMatch: {"t": "k", "v": "movie"}}} 
     ] 
    } 

).explain() 

說明文件:

{ 
    "cursor" : "BtreeCursor f.t_1_f.v_1", 
    "isMultiKey" : true, 
    "n" : 6, 
    "nscannedObjects" : 50, 
    "nscanned" : 50, 
    "nscannedObjectsAllPlans" : 50, 
    "nscannedAllPlans" : 50, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 0, 
    "indexBounds" : { 
     "f.t" : [ 
      [ 
       "k", 
       "k" 
      ] 
     ], 
     "f.v" : [ 
      [ 
       "movie", 
       "movie" 
      ] 
     ] 
    }, 
    "server" : "b009115.mongolab.com:42700", 
    "filterSet" : false, 
    "stats" : { 
     "type" : "KEEP_MUTATIONS", 
     "works" : 51, 
     "yields" : 0, 
     "unyields" : 0, 
     "invalidates" : 0, 
     "advanced" : 6, 
     "needTime" : 44, 
     "needFetch" : 0, 
     "isEOF" : 1, 
     "children" : [ 
      { 
       "type" : "FETCH", 
       "works" : 51, 
       "yields" : 0, 
       "unyields" : 0, 
       "invalidates" : 0, 
       "advanced" : 6, 
       "needTime" : 44, 
       "needFetch" : 0, 
       "isEOF" : 1, 
       "alreadyHasObj" : 0, 
       "forcedFetches" : 0, 
       "matchTested" : 6, 
       "children" : [ 
        { 
         "type" : "IXSCAN", 
         "works" : 51, 
         "yields" : 0, 
         "unyields" : 0, 
         "invalidates" : 0, 
         "advanced" : 50, 
         "needTime" : 0, 
         "needFetch" : 0, 
         "isEOF" : 1, 
         "keyPattern" : "{ f.t: 1.0, f.v: 1.0 }", 
         "isMultiKey" : 1, 
         "boundsVerbose" : "field #0['f.t']: [\"k\", \"k\"], field #1['f.v']: [\"movie\", \"movie\"]", 
         "yieldMovedCursor" : 0, 
         "dupsTested" : 50, 
         "dupsDropped" : 0, 
         "seenInvalidated" : 0, 
         "matchTested" : 0, 
         "keysExamined" : 50, 
         "children" : [] 
        } 
       ] 
      } 
     ] 
    } 
} 

正如我所看到的,當只有六個匹配的文檔時,它掃描了所有文檔(50)。爲什麼掃描/匹配的文檔比例很差(是嗎?)。有沒有更好的方法來改善它?

謝謝!

回答

1

正如所述,它不是「文件」,而是「對象」,但您不會是第一個不完全理解.explain()輸出的人。簡而言之,您的索引中包含一個「數組」元素(實際上允許的最大值爲「2」),這意味着您的索引就是我們所說的「MultiKey」。這意味着在非常基本的術語中,「複合」索引具有在其內指定的值的「各種可能的組合」。

所以索引數據的「非常基本」的觀點可能是這樣的:

{ "f.t": "ry", "f.v": 1972 }, 
{ "f.t": "g", "f.v": "Crime" }, 
{ "f.t": "g", "f.v": "Drama" } 

總之,這是「三化」(3)您的收藏中對應於「單一文件」條目會在集合中進行掃描。

當然,根據您的查詢條件「過濾」。所以在這裏尋找"f.t": "g"意味着「兩個」(2)對象被掃描。

這實質上是「對象」和「文檔」之間的區別與查詢規劃器給出的輸出之間的關係。

注意:根據引擎實際存儲事物的方式以及如何在與查詢進行交互時如何檢索它們以及在此處解釋輸出報告類似的文檔擴展超出預期的情況,「Geospatial」文件計數。但是,索引中的所有對象都是以這種方式處理的。

所以:

  • n是 「結果」 的文件
  • nScannedObjects爲對象
+0

謝謝!非常好的見解。你知道一本深入探索索引和掃描程序的書或文章嗎? – borjagvo

+1

@borjagvo沒有資源,我知道其實。無論如何,儘管可能應該發佈。加入一個MongoDB用戶組,然後你可以更好地訪問一般不公開發布的信息,或者至少有機會與其他直接使用該產品的人進行交互,在這兩種形式中,與核心交互的機會更大團隊和獲取信息。或者只是在這裏發佈問題,人們看看。 –

相關問題