猿教程 Logo

.Net连接MongoDb:查询计划和我们的第一个索引

介绍

在上一篇文章中,我们在本系列中介绍了一个新的子部分,即索引如何在MongoDb中工作。 我们经过一般性的介绍,而不实际创建一个索引。 我们还查看了可以在集合上调用的stats()函数来查找一些基本统计信息,例如文档数量和索引大小。 此外,我们了解了一个存储引擎是什么,MongoDb 3.2.4附带的默认存储引擎称为WiredTiger。

在这篇文章中,我们将在Mongo shell中开始创建索引。 让mongo客户端和mongo服务器都可以在两个不同的控制台窗口中准备好。 记住,这是“mongo”和“mongod”命令。

查询计划

我们将把注意力转到演示邮政编码数据库。 这是一个单一的文件提醒:

{
        "_id" : "01001",
        "city" : "AGAWAM",
        "loc" : [
                -72.622739,
                42.070206
        ],
        "pop" : 15338,
        "state" : "MA"
}

我们可以想到针对这个集合的多个常见查询,但我们将从一个简单的开始。 我们要在状态字段上进行过滤,例如 我们想查找加利福尼亚州的所有地方,即“CA”:

db.zipcodes.find({"state" : "CA"})

有一个非常有用的函数叫做“explain”可以附加到集合。 它返回查询的查询计划,即有关MongoDb如何执行查询的一些信息。 解释函数后跟我们要分析的查询。 以下是检索上述搜索查询计划的示例:

db.zipcodes.explain().find({"state" : "CA"})

它返回一个名为“queryPlanner”的子文档的JSON文档。 我得到以下结果:

"queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "model.zipcodes",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "state" : {
                                "$eq" : "CA"
                        }
                },
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "state" : {
                                        "$eq" : "CA"
                                }
                        },
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        }

我们现在最重要的一些信息是“wonPlan”部分。 COLLSCAN的“阶段”值意味着收集扫描。 收集扫描是MongoDb必须扫描集合中每个文档的位置。 为了证明它,我们可以使用一个真正的输入参数来执行explain命令,该参数也将执行查询。 explain()本身不会实际执行要分析的命令。

这个解释版本返回一个更长的JSON文档:

db.zipcodes.explain(true).find({"state" : "CA"})

返回的文档包括以前输出的所有内容以及一个名为“executionStats”的部分:

"executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1516,
                "executionTimeMillis" : 13,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 29353,
                "executionStages" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "state" : {
                                        "$eq" : "CA"
                                }
                        },
                        "nReturned" : 1516,
                        "executionTimeMillisEstimate" : 10,
                        "works" : 29355,
                        "advanced" : 1516,
                        "needTime" : 27838,
                        "needYield" : 0,
                        "saveState" : 229,
                        "restoreState" : 229,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "direction" : "forward",
                        "docsExamined" : 29353
                },
                "allPlansExecution" : [ ]
        }

我们现在可以专注于以下条目:

  • nReturned:查询返回的文档数

  • executionTimeMillis:以毫秒为单位执行查询所花费的时间

  • totalDocsExpected:为完成查询而必须扫描的文档数。 它现在相当于邮政编码集合中的文件总数,证明MongoDb必须考虑所有文件

在state属性上创建索引

使用createIndex函数创建索引。 第一个参数是一个JSON文档,描述应该编入索引的字段,以及它是按升序还是降序。 如果您想以某种顺序对结果进行排序,则索引排序最经常。 对于像上述情况那样的搜索,索引排序通常没有任何区别。 但是,如果您经常搜索两个字段,例如 在示范餐馆收藏中,您可以随时按照菜肴排序结果,相应的复合指数应该反映出来。 我们稍后再回到这一点。

我们在状态字段上创建一个索引,并给它一个名字:

db.zipcodes.createIndex({"state" : 1}, {"name" : "state-asc"})

第一个参数描述索引的字段和排序顺序,其中1表示升序,-1表示降序。 第二个参数是可选的,我们可以指定可选参数的范围,如索引名称。 稍后我们再回来一些这些选项。

响应告诉我们,索引数量从1增加到2:

{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

stats()函数也将显示我们刚创建的索引。

让我们检查索引是否在查询计划中有任何差异。 解释功能...

db.zipcodes.explain(true).find({"state" : "CA"})

...显示了一些重要的改进:

"inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "state" : 1
                                },
                                "indexName" : "state-asc",
                                [some ignored fields]
                                "indexBounds" : {
                                        "state" : [
                                                "[\"CA\", \"CA\"]"
                                        ]
                                }
                        }
...

"executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1516,
                "executionTimeMillis" : 13,
                "totalKeysExamined" : 1516,
                "totalDocsExamined" : 1516,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 1516,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 1517,
                        "advanced" : 1516,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 11,
                        "restoreState" : 11,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 1516,
                        "alreadyHasObj" : 0,
  • “winnerPlan”子文档现在显示了IXSCAN的舞台类型,代表索引扫描。 该文档还显示用于扫描的索引的名称

  • 这里有一个有趣的字段是“indexBounds”,它显示了检查的索引的范围。 我们只对单个值进行过滤,因此范围以CA开始和结束

  • 在这个例子中,13ms的执行时间没有改变,但是由于邮政编码收集很小。 索引显示他们的力量与大量的数百万个文件的集合

  • totalDocsExpected:1516,而不是我们以前的总收集大小29353。 这意味着只需要扫描1516个文档,而不是整个集合。 1516也是返回的文档数量,即扫描和返回的文档之间的1:1匹配

  • totalKeysExpected:检查1516个索引键,而不是0

构建索引时,这通常是一个很好的策略。 在索引创建之前和之后运行explain命令,最好在alpha数据库上,而不是搞乱生产数据库。 目标是减少扫描得到结果集的文档数量。 最好的是扫描文件的数量等于返回的文件的数量。

我们将在下一篇文章中继续讨论。


版权声明:本站所有教程均为本站原创或翻译,转载请注明出处,请尊重他人劳动果实。请记住本站地址:www.yuanjiaocheng.net (猿教程) 作者:卿文刚
本文标题: C#环境
本文地址:http://www.yuanjiaocheng.net/CsharpMongo/31.html