Mongodb 为什么在执行IXSCAN后,Mongo在FETCH中查询空过滤器
根据,Mongodb 为什么在执行IXSCAN后,Mongo在FETCH中查询空过滤器,mongodb,null,mongodb-query,mongodb-indexes,query-planner,Mongodb,Null,Mongodb Query,Mongodb Indexes,Query Planner,根据, {item:null}查询匹配包含 item字段,其值为null或不包含项 场 我找不到这方面的文档,但据我所知,这两种情况(值为null或字段缺失)都以null的形式存储在索引中 因此,如果我执行db.orders.createIndex({item:1}),然后执行db.orders.find({item:null}),我将期望一个IXSCAN查找所有包含值为null的item字段的文档,并且只查找那些文档 那么为什么db.orders.find({item:null}).expla
{item:null}
查询匹配包含
item
字段,其值为null
或不包含项
场
我找不到这方面的文档,但据我所知,这两种情况(值为null
或字段缺失)都以null
的形式存储在索引中
因此,如果我执行db.orders.createIndex({item:1})
,然后执行db.orders.find({item:null})
,我将期望一个IXSCAN
查找所有包含值为null
的item
字段的文档,并且只查找那些文档
那么为什么db.orders.find({item:null}).explain()执行filter:{item:{$eq:null}}
在执行IXSCAN
之后,在FETCH
阶段执行?哪些可能的文档需要过滤掉
{
"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
}
我想,未定义的
值可能会被索引为null
,但简单的实验排除了这一点:
> db.orders.createIndex({item: 1})
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.orders.insert({item: undefined})
WriteResult({ "nInserted" : 1 })
> db.orders.find({item: {$type: 6}}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "temp.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"item" : {
"$type" : 6
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$type" : 6
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"item" : 1
},
"indexName" : "item_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[undefined, undefined]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "Andys-MacBook-Pro-2.local",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1
}
null相等匹配谓词(例如,{“a.b”:null}
)的语义非常复杂,因为字段可能包含子文档,仅索引扫描不足以提供正确的结果
根据,
服务器的2.6.0版本更改了空相等的语义
匹配谓词,这样文档{a:[]}就不再是
认为查询谓词{“a.b”:null}(在前面的
在服务器的版本中,此文档被视为与此
谓词)。这记录在2.6兼容性说明中,在
“空比较”部分
对于键模式为{“a.b”:1}的索引,此文档为{a:[]}
生成索引键{“”:null}。其他文档,如{a:null}和
空文档{}还生成索引键{“”:null}。作为一个
结果,如果谓词为{“a.b”:null}的查询使用此索引,则
查询系统无法仅从索引键{“”:null}判断
关联文档与谓词不匹配。因此,
不精确的获取边界被指定,而不是精确的边界,因此
FETCH阶段添加到查询执行树中
补充说明:
文档{}为键模式为{“a.b”:1}的索引生成索引键{“”:null}
文档{a:[]}还为键模式为{“a.b”:1}的索引生成索引键{“”:null}
文档{}与查询{“a.b”:null}匹配
文档{a:[]}与查询{“a.b”:null}不匹配
因此,一个查询{“a.b”:null}被一个带有key的索引所回答
模式{“a.b”:1}必须获取文档并重新检查谓词,
为了确保结果集中包含文档{}
并且结果集中不包括文档{a:[]}