为什么MongoDB不同的查询计划显示不同的nReturned值?

2024-05-01

我有一个收藏faults in my MongoDB每个文档都有这些字段的数据库:rack_name, timestamp

只是为了测试和比较性能,我创建了这两个索引:

rack -> {'rack_name': 1}

and

time -> {'timestamp': 1}

现在我用explain()执行了以下查询:

db.faults.find({
    'rack_name': {
        $in: [ 'providence1', 'helena2' ]
    }, 
    'timestamp': {
        $gt: 1501548359000
    }
})
.explain('allPlansExecution') 

这是结果:

 {
"queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "quicktester_clone.faults",
    "indexFilterSet" : false,
    "parsedQuery" : {
        "$and" : [ 
            {
                "timestamp" : {
                    "$gt" : 1501548359000.0
                }
            }, 
            {
                "rack_name" : {
                    "$in" : [ 
                        "helena2", 
                        "providence1"
                    ]
                }
            }
        ]
    },
    "winningPlan" : {
        "stage" : "FETCH",
        "filter" : {
            "timestamp" : {
                "$gt" : 1501548359000.0
            }
        },
        "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
                "rack_name" : 1
            },
            "indexName" : "rack",
            "isMultiKey" : false,
            "multiKeyPaths" : {
                "rack_name" : []
            },
            "isUnique" : false,
            "isSparse" : false,
            "isPartial" : false,
            "indexVersion" : 2,
            "direction" : "forward",
            "indexBounds" : {
                "rack_name" : [ 
                    "[\"helena2\", \"helena2\"]", 
                    "[\"providence1\", \"providence1\"]"
                ]
            }
        }
    },
    "rejectedPlans" : [ 
        {
            "stage" : "FETCH",
            "filter" : {
                "rack_name" : {
                    "$in" : [ 
                        "helena2", 
                        "providence1"
                    ]
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "timestamp" : 1
                },
                "indexName" : "time",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "timestamp" : []
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "timestamp" : [ 
                        "(1501548359000.0, inf.0]"
                    ]
                }
            }
        }
    ]
},
"executionStats" : {
    "executionSuccess" : true,
    "nReturned" : 43,
    "executionTimeMillis" : 1512,
    "totalKeysExamined" : 221,
    "totalDocsExamined" : 219,
    "executionStages" : {
        "stage" : "FETCH",
        "filter" : {
            "timestamp" : {
                "$gt" : 1501548359000.0
            }
        },
        "nReturned" : 43,
        "executionTimeMillisEstimate" : 1431,
        "works" : 222,
        "advanced" : 43,
        "needTime" : 177,
        "needYield" : 0,
        "saveState" : 64,
        "restoreState" : 64,
        "isEOF" : 1,
        "invalidates" : 0,
        "docsExamined" : 219,
        "alreadyHasObj" : 0,
        "inputStage" : {
            "stage" : "IXSCAN",
            "nReturned" : 219,
            "executionTimeMillisEstimate" : 71,
            "works" : 221,
            "advanced" : 219,
            "needTime" : 1,
            "needYield" : 0,
            "saveState" : 64,
            "restoreState" : 64,
            "isEOF" : 1,
            "invalidates" : 0,
            "keyPattern" : {
                "rack_name" : 1
            },
            "indexName" : "rack",
            "isMultiKey" : false,
            "multiKeyPaths" : {
                "rack_name" : []
            },
            "isUnique" : false,
            "isSparse" : false,
            "isPartial" : false,
            "indexVersion" : 2,
            "direction" : "forward",
            "indexBounds" : {
                "rack_name" : [ 
                    "[\"helena2\", \"helena2\"]", 
                    "[\"providence1\", \"providence1\"]"
                ]
            },
            "keysExamined" : 221,
            "seeks" : 2,
            "dupsTested" : 0,
            "dupsDropped" : 0,
            "seenInvalidated" : 0
        }
    },
    "allPlansExecution" : [ 
        {
            "nReturned" : 2,
            "executionTimeMillisEstimate" : 31,
            "totalKeysExamined" : 221,
            "totalDocsExamined" : 221,
            "executionStages" : {
                "stage" : "FETCH",
                "filter" : {
                    "rack_name" : {
                        "$in" : [ 
                            "helena2", 
                            "providence1"
                        ]
                    }
                },
                "nReturned" : 2,
                "executionTimeMillisEstimate" : 31,
                "works" : 221,
                "advanced" : 2,
                "needTime" : 219,
                "needYield" : 0,
                "saveState" : 64,
                "restoreState" : 64,
                "isEOF" : 0,
                "invalidates" : 0,
                "docsExamined" : 221,
                "alreadyHasObj" : 0,
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "nReturned" : 221,
                    "executionTimeMillisEstimate" : 10,
                    "works" : 221,
                    "advanced" : 221,
                    "needTime" : 0,
                    "needYield" : 0,
                    "saveState" : 64,
                    "restoreState" : 64,
                    "isEOF" : 0,
                    "invalidates" : 0,
                    "keyPattern" : {
                        "timestamp" : 1
                    },
                    "indexName" : "time",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "timestamp" : []
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "timestamp" : [ 
                            "(1501548359000.0, inf.0]"
                        ]
                    },
                    "keysExamined" : 221,
                    "seeks" : 1,
                    "dupsTested" : 0,
                    "dupsDropped" : 0,
                    "seenInvalidated" : 0
                }
            }
        }, 
        {
            "nReturned" : 43,
            "executionTimeMillisEstimate" : 1431,
            "totalKeysExamined" : 221,
            "totalDocsExamined" : 219,
            "executionStages" : {
                "stage" : "FETCH",
                "filter" : {
                    "timestamp" : {
                        "$gt" : 1501548359000.0
                    }
                },
                "nReturned" : 43,
                "executionTimeMillisEstimate" : 1431,
                "works" : 221,
                "advanced" : 43,
                "needTime" : 177,
                "needYield" : 0,
                "saveState" : 64,
                "restoreState" : 64,
                "isEOF" : 1,
                "invalidates" : 0,
                "docsExamined" : 219,
                "alreadyHasObj" : 0,
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "nReturned" : 219,
                    "executionTimeMillisEstimate" : 71,
                    "works" : 221,
                    "advanced" : 219,
                    "needTime" : 1,
                    "needYield" : 0,
                    "saveState" : 64,
                    "restoreState" : 64,
                    "isEOF" : 1,
                    "invalidates" : 0,
                    "keyPattern" : {
                        "rack_name" : 1
                    },
                    "indexName" : "rack",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "rack_name" : []
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "rack_name" : [ 
                            "[\"helena2\", \"helena2\"]", 
                            "[\"providence1\", \"providence1\"]"
                        ]
                    },
                    "keysExamined" : 221,
                    "seeks" : 2,
                    "dupsTested" : 0,
                    "dupsDropped" : 0,
                    "seenInvalidated" : 0
                }
            }
        }
    ]
},
"serverInfo" : {
    "host" : "dtauto-sna01.mascorp.com",
    "port" : 27017,
    "version" : "3.4.4",
    "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
},
"ok" : 1.0
}

有两件事我不明白:

  1. 当你看着AllPlansExecution the nReturned键有不同 每个计划的价值。第二个计划(索引:rack)实际上是胜利者 plan并返回43个结果,这是实际的返回结果 整个查询,但是那两个是什么nReturned从第一个结果

  2. 更多的挑战来到了这一点,为什么第一个计划(索引: 时间(即被拒绝的计划)已报告较少executionTimeMillis比获胜者计划值31executionTimeMillis 1431?

这是怎么回事?


这在所有计划执行模式 https://docs.mongodb.com/manual/reference/method/db.collection.explain/#allplansexecution-mode文档页面。转述一下:

MongoDB 运行查询优化器来选择获胜计划并执行获胜计划直至完成。在“allPlansExecution”模式下,MongoDB 返回描述获胜计划执行情况的统计信息以及在计划选择期间捕获的其他候选计划的统计信息。

在计划选择过程中,如果有多个索引可以满足查询,MongoDB 将使用所有有效计划进行试验,以确定哪一个执行效果最好。看查询计划 https://docs.mongodb.com/manual/core/query-plans/有关此过程的详细信息。

从 MongoDB 3.4.6 开始,计划选择涉及在“竞赛”中并行运行候选计划,并查看哪个候选计划首先返回 101 个结果。在上面的示例中,当获胜计划在比赛中返回 101 个结果时,失败计划仅管理 2 个结果。然后获胜的计划将得到执行直至完成。这就是为什么失败的计划只显示的原因nReturned: 2在统计数据中。

执行这种“竞赛”是因为,如果有两个看起来相同的计划,由于 JSON 文档的灵活性,MongoDB 不知道哪个计划最适合特定查询(与 SQL 不同,其中表的结构是已知的) 。当然,MongoDB 完全有可能猜测错误,并最终得到一个性能不佳的计划,因为这是一个经验过程。因此,最好创建支持您的查询的索引,这样 MongoDB 就不必猜测。否则,您可以使用hint()告诉 MongoDB 某个查询使用哪个索引。

Hence:

  • 获胜计划的统计数据是实际查询的结果统计数据。
  • 丢失计划的统计信息仅显示查询计划试运行的统计信息。
  • 计划选择包括进行一场“竞赛”,争取 101 个结果。仅当有多个索引可以满足查询时才会执行此竞争。

Note 1:您看到的两个计划都不是很好。获胜计划显示"nReturned" : 43, "totalKeysExamined" : 221, and "totalDocsExamined" : 219。这意味着 MongoDB 只需检查 219 个文档即可返回其中 43 个:效率只有20%。理想情况下,您希望拥有nReturned数字等于totalDocsExamined.

Note 2:尝试创建复合索引{'rack_name': 1, 'timestamp': 1}。使用相同的查询,您应该获得更好的效率数字。

Note 3: 请注意,自从allPlansExecution被指定,all统计数据将由 MongoDB 及时返回给您,以保证完整性,但与最终结果没有任何关系nReturned结果。这是一个被拒绝的计划nReturned: 2 number can令人困惑。如果您使用,您将看不到此统计信息executionStats环境。首先,allPlansExecution用于微调和确定某些计划被拒绝的原因。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么MongoDB不同的查询计划显示不同的nReturned值? 的相关文章

随机推荐