将过滤器添加到MongoDB查询会增加计数所需的时间()



我有一个名为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测试时发现的那样(。

最新更新