2015-06-15 88 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用户组,然后你可以更好地访问一般不公开发布的信息,或者至少有机会与其他直接使用该产品的人进行交互,在这两种形式中,与核心交互的机会更大团队和获取信息。或者只是在这里发布问题,人们看看。 –