我有一个名为listings
的集合,其中超过500万个文档和索引(仅相关(与键:
{"_id": 1}
{"dated": 1}
{"causelist_type": 1}
我正在尝试运行查询
db.listings.count({
dated: {
$in: [ISODate("2018-02-17T00:00:00Z"), ISODate("2018-02-16T00:00:00Z"),ISODate("2018-02-10T00:00:00Z")]
},
causelist_type: {$ne: -1}
})
它需要130秒。(通过使用print(new Date())
进行准备和附加命令记录(
但是,如果我删除过滤器causelist_type: {$ne: -1}
,则查询几乎瞬间运行(〜1s(。
explain().queryPlanner
for causelist_type
子句的查询:
{
"plannerVersion" : 1,
"namespace" : "kl.listings",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"dated" : {
"$in" : [
ISODate("2018-02-10T00:00:00Z"),
ISODate("2018-02-16T00:00:00Z"),
ISODate("2018-02-17T00:00:00Z")
]
}
},
{
"$nor" : [{
"causelist_type" : {
"$eq" : -1
}
}]
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$nor" : [{
"causelist_type" : {
"$eq" : -1
}
}]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"dated" : 1
},
"indexName" : "dated_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"dated" : [
"[new Date(1518220800000), new Date(1518220800000)]",
"[new Date(1518739200000), new Date(1518739200000)]",
"[new Date(1518825600000), new Date(1518825600000)]"
]
}
}
},
"rejectedPlans" : [{
"stage" : "FETCH",
"filter" : {
"dated" : {
"$in" : [
ISODate("2018-02-10T00:00:00Z"),
ISODate("2018-02-16T00:00:00Z"),
ISODate("2018-02-17T00:00:00Z")
]
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"causelist_type" : 1
},
"indexName" : "causelist_type_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"causelist_type" : [
"[MinKey, -1.0)",
"(-1.0, MaxKey]"
]
}
}
}]
}
explain().queryPlanner
用于查询没有 causelist_type
子句:
{
"plannerVersion" : 1,
"namespace" : "kl.listings",
"indexFilterSet" : false,
"parsedQuery" : {
"dated" : {
"$in" : [
ISODate("2018-02-10T00:00:00Z"),
ISODate("2018-02-16T00:00:00Z"),
ISODate("2018-02-17T00:00:00Z")
]
}
},
"winningPlan" : {
"stage" : "COUNT",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"dated" : 1
},
"indexName" : "dated_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"dated" : [
"[new Date(1518220800000), new Date(1518220800000)]",
"[new Date(1518739200000), new Date(1518739200000)]",
"[new Date(1518825600000), new Date(1518825600000)]"
]
}
}
},
"rejectedPlans" : [ ]
}
我正在使用mongodb 3.6.2。
我不明白的是,当使用或不使用"过滤器"的查询中使用相同的索引时,添加"过滤器"如何增加查询时间。
让我知道您是否需要更多信息。
编辑:
我还尝试将causelist_type
子句修改为causelist_type: {$eq: -1}
,并且查询即时运行。请解释。
编辑2: explain().queryPlanner
使用causelist_type: {$eq: -1}
子句:
{
"plannerVersion" : 1,
"namespace" : "kl.listings",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [{
"causelist_type" : {
"$eq" : -1
}
},
{
"dated" : {
"$in" : [
ISODate("2018-02-10T00:00:00Z"),
ISODate("2018-02-16T00:00:00Z"),
ISODate("2018-02-17T00:00:00Z")
]
}
}]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"causelist_type" : {
"$eq" : -1
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"dated" : 1
},
"indexName" : "dated_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"dated" : [
"[new Date(1518220800000), new Date(1518220800000)]",
"[new Date(1518739200000), new Date(1518739200000)]",
"[new Date(1518825600000), new Date(1518825600000)]"
]
}
}
},
"rejectedPlans" : [{
"stage" : "FETCH",
"filter" : {
"dated" : {
"$in" : [
ISODate("2018-02-10T00:00:00Z"),
ISODate("2018-02-16T00:00:00Z"),
ISODate("2018-02-17T00:00:00Z")
]
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"causelist_type" : 1
},
"indexName" : "causelist_type_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"causelist_type" : [
"[-1.0, -1.0]"
]
}
}
}]
}
同样,当我将causelist_type
子句更改为causelist_type: {$nin: [-1, -2]}
时,它是 fast ,并使用与causelist_type: {$eq: -1}
相同的索引和输入阶段,只是另一个过滤器。
,它们都没有使用索引交点,正如解释结果文档所说,在使用索引交叉点的情况下,我们应该SE "stage" : "AND_SORTED"
。
在查询中没有 causelist_type
项,计数查询完全由 dated
上的索引覆盖,这使得它非常快。
请注意此案的获胜计划中的"stage" : "COUNT"
。
将causelist_type
添加到查询中,要求每个满足查询dated
部分的文档要从磁盘读取,以便可以检查其causelist_type
值以查看是否是$ne: -1
。
请注意此案的获胜计划中的"stage" : "FETCH"
。
至于为什么在causelist_type
索引上不使用索引交叉点,这可能是因为您使用的是$ne
查询,这使得索引效率不如匹配(正如您在使用$eq
测试时发现的那样(。