为什么Mongo在执行IXSCAN后在FETCH中查询空过滤器

时间:2017-08-23 03:48:00

标签: mongodb null mongodb-query mongodb-indexes query-planner

根据Mongo Documentation

  

{ item : null }查询匹配包含该文件的文档   item字段,其值为null或不包含item   字段。

我无法找到相关文档,但据我所知,两种情况(值null或字段缺失)都存储在索引中null

因此,如果我db.orders.createIndex({item: 1})然后db.orders.find({item: null}),我希望IXSCAN找到包含值为{{1}的item字段的所有文档或者不包含null字段,只包含那些文档。

那么为什么item在执行db.orders.find({item: null}).explain()filter: {item: {$eq: null}}阶段执行FETCH?可能需要过滤哪些可能的文件?

IXSCAN

我认为可能会将{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "temp.orders", "indexFilterSet" : false, "parsedQuery" : { "item" : { "$eq" : null } }, "winningPlan" : { "stage" : "FETCH", "filter" : { "item" : { "$eq" : null } }, "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "item" : 1 }, "indexName" : "item_1", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "item" : [ "[null, null]" ] } } }, "rejectedPlans" : [ ] }, "serverInfo" : { "host" : "Andys-MacBook-Pro-2.local", "port" : 27017, "version" : "3.2.8", "gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0" }, "ok" : 1 } 值编入索引为undefined,但简单的实验会对此进行排除:

null

1 个答案:

答案 0 :(得分:1)

空等式匹配谓词(例如{"a.b": null})的语义非常复杂,因为字段可能包含单独索引扫描不足以提供正确结果的子文档。

根据https://jira.mongodb.org/browse/SERVER-18653?focusedCommentId=931817&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-931817

  

服务器版本2.6.0改变了空相等的语义   匹配谓词,以便文档{a:[]}不再存在   被认为是查询谓词{“a.b”:null}的匹配(在之前的   服务器的这个版本被认为是匹配的   谓语)。这在2.6兼容性说明中有记录   “空比较”部分。

     

对于具有键模式{“a.b”:1}的索引,此文档{a:[]}   生成索引键{“”:null}。其他文件如{a:null}和   空文档{}也生成索引键{“”:null}。作为一个   结果,如果带有谓词{“a.b”:null}的查询使用此索引,则   查询系统无法告诉索引键{“”:null}是否或   不是关联的文档与谓词匹配。结果是,   分配INEXACT_FETCH边界而不是EXACT边界,因此a   FETCH阶段被添加到查询执行树中。

补充说明:

  
      
  1. 文档{}为具有键模式{“a.b”:1}的索引生成索引键{“”:null}。
  2.   
  3. 文档{a:[]}还为具有键模式{“a.b”:1}的索引生成索引键{“”:null}。
  4.   
  5. 文档{}与查询{“a.b”:null}匹配。
  6.   
  7. 文档{a:[]}与查询{“a.b”:null}不匹配。
  8.         

    因此,查询{“a.b”:null}由带有键的索引回答   pattern {“a.b”:1}必须获取文档并重新检查谓词,   以确保文档{}包含在结果集中   并且文档{a:[]}未包含在结果集中。