我有一个名为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
子句的查询的 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]}
时,它快并使用与causelist_type: {$eq: -1}
相同的索引和输入阶段,只是一个不同的过滤器。
他们都没有使用索引交集,因为explain results documentation表示在使用索引交集的情况下我们应该"stage" : "AND_SORTED"
。
答案 0 :(得分:1)
如果查询中没有causelist_type
字词,则dated
上的索引完全涵盖了计数查询,这使得它非常快。
请注意此案例的获胜计划中的"stage" : "COUNT"
。
将causelist_type
添加到查询中需要从磁盘读取满足查询dated
部分的每个文档,以便可以检查其causelist_type
值以查看它是否&# 39; s $ne: -1
。
请注意此案例的获胜计划中的"stage" : "FETCH"
。
至于为什么索引交集在这里与causelist_type
索引一起使用时,可能是因为你正在使用$ne
查询,这使得索引更多效率低于匹配(正如您在使用$eq
进行测试时发现的那样)。