mongdb 查询性能分析及索引优化详解

您所在的位置:网站首页 mongodb统计聚合条数效率 mongdb 查询性能分析及索引优化详解

mongdb 查询性能分析及索引优化详解

2023-09-23 12:28| 来源: 网络整理| 查看: 265

mongo 性能分析 explain() 方法

MongoDB 查询分析可以确保我们所建立的索引是否有效,是查询语句性能分析的重要工具。 参考文档

可以设置以下参数:

queryPlanner executionStats allPlansExecution

常用的是 executionStats 模式

准备工作

我们现在有一张表,一共 5584702 条数据,数据结构和索引状况如下。 单条结构如下:

{ "_id" : ObjectId("5ff8287c47ec3c1813536e5c"), "x" : 1, //递增 "name" : "MACLEAN", "name1" : "MACLEAN", "name2" : "MACLEAN", "name3" : "MACLEAN" }

索引状况如下,目前除了 mongodb 默认 _id 索引外,没有添加任何索引:

> db.testdatas.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.testdatas" } ] 开始测试

执行如下查询语句:

> db.testdatas.find({}).limit(10).sort({x: 1}).explain("executionStats")

返回结果

{ "queryPlanner" : { // 查询计划信息 "plannerVersion" : 1, "namespace" : "test.testdatas", // 该 query 所查询的表 "indexFilterSet" : false, // 针对该query是否应用索引 "parsedQuery" : { }, "winningPlan" : { // 最优执行计划的详细内容 "stage" : "SORT", // 最优执行计划的stage "sortPattern" : { "x" : 1 }, "limitAmount" : 10, "inputStage" : { // 子阶段列表 "stage" : "SORT_KEY_GENERATOR", "inputStage" : { "stage" : "COLLSCAN", "direction" : "forward" } } }, "rejectedPlans" : [ ] // 其他执行计划 }, "executionStats" : { //查询结果执行情况 "executionSuccess" : true, "nReturned" : 10, // 符合查询条件的文档数 "executionTimeMillis" : 14920, // 选择查询计划和执行查询所需的总时间(以毫秒为单位) "totalKeysExamined" : 0, // 索引扫描条目 "totalDocsExamined" : 5584702, // 扫描文档数 "executionStages" : { "stage" : "SORT", "nReturned" : 10, "executionTimeMillisEstimate" : 14071, "works" : 5584716, "advanced" : 10, "needTime" : 5584705, "needYield" : 0, "saveState" : 44054, "restoreState" : 44054, "isEOF" : 1, "invalidates" : 0, "sortPattern" : { "x" : 1 }, "memUsage" : 1160, "memLimit" : 33554432, "limitAmount" : 10, "inputStage" : { "stage" : "SORT_KEY_GENERATOR", "nReturned" : 5584702, "executionTimeMillisEstimate" : 11874, "works" : 5584705, "advanced" : 5584702, "needTime" : 2, "needYield" : 0, "saveState" : 44054, "restoreState" : 44054, "isEOF" : 1, "invalidates" : 0, "inputStage" : { "stage" : "COLLSCAN", "nReturned" : 5584702, "executionTimeMillisEstimate" : 7506, "works" : 5584704, "advanced" : 5584702, "needTime" : 1, "needYield" : 0, "saveState" : 44054, "restoreState" : 44054, "isEOF" : 1, "invalidates" : 0, "direction" : "forward", "docsExamined" : 5584702 } } } }, "serverInfo" : { "host" : "localhost", "port" : 27017, "version" : "4.0.8", "gitVersion" : "9b00696ed75f65e1ebc8d635593bed79b290cfbb" }, "ok" : 1 } 对executionStats返回逐层分析 第一步,分析 executionStats 字段名说明(参考上述查询结果)executionTimeMillis查询语句总耗时。上述查询语句 5584702 条一共耗时 14920 mstotalKeysExamined索引扫描条目。 上述结果为 0,说明本次查询可能没有用到索引totalDocsExamined文档扫描条数。 上述结果为 5584702,说明本次查询把文档全部扫描了一遍nReturned返回结果条数。 上述结果返回10条

 

第二步,分析 executionStages

这个主要讨论3个返回项,nReturned、totalKeysExamined、totalDocsExamined,

分别代表该条 查询返回的条目、索引扫描条目、文档扫描条目。 这些都是直观地影响到 executionTimeMillis,我们需要扫描的越少速度越快。

对于一个查询,我们最理想的状态是: nReturned = totalKeysExamined = totalDocsExamined

第三步,分析 stage 状态 字段名说明(参考上述查询结果)stage查询计划类型。上述结果 SORT, 表明在内存中进行了排序inputStage用来描述子stage,并且为其父stage提供文档和索引关键字

那么又是什么影响到了totalKeysExamined和totalDocsExamined?是stage的类型。类型列举如下:

COLLSCAN:全表扫描 IXSCAN:索引扫描 FETCH:根据索引去检索指定document SHARD_MERGE:将各个分片返回数据进行merge SORT:表明在内存中进行了排序 LIMIT:使用limit限制返回数 SKIP:使用skip进行跳过 IDHACK:针对_id进行查询 SHARDING_FILTER:通过mongos对分片数据进行查询 COUNT:利用db.coll.explain().count()之类进行count运算 COUNTSCAN: count不使用Index进行count时的stage返回 COUNT_SCAN: count使用了Index进行count时的stage返回 SUBPLA:未使用到索引的$or查询的stage返回 TEXT:使用全文索引进行查询时候的stage返回 PROJECTION:限定返回字段时候stage的返回

添加索引后执行同样的查询语句

给该集合添加一个 { x: 1 } 索引

> db.testdatas.createIndex({x: 1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }

执行上文同样的查询语句:

> db.testdatas.find({}).limit(10).sort({x: 1}).explain("executionStats")

返回结果:

{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.testdatas", "indexFilterSet" : false, "parsedQuery" : { }, "winningPlan" : { "stage" : "LIMIT", "limitAmount" : 10, "inputStage" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "x" : 1 }, "indexName" : "x_1", "isMultiKey" : false, "multiKeyPaths" : { "x" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "x" : [ "[MinKey, MaxKey]" ] } } } }, "rejectedPlans" : [ ] }, "executionStats" : { "executionSuccess" : true, "nReturned" : 10, "executionTimeMillis" : 1, "totalKeysExamined" : 10, "totalDocsExamined" : 10, "executionStages" : { "stage" : "LIMIT", "nReturned" : 10, "executionTimeMillisEstimate" : 0, "works" : 11, "advanced" : 10, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "limitAmount" : 10, "inputStage" : { "stage" : "FETCH", "nReturned" : 10, "executionTimeMillisEstimate" : 0, "works" : 10, "advanced" : 10, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 0, "invalidates" : 0, "docsExamined" : 10, "alreadyHasObj" : 0, "inputStage" : { "stage" : "IXSCAN", "nReturned" : 10, "executionTimeMillisEstimate" : 0, "works" : 10, "advanced" : 10, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 0, "invalidates" : 0, "keyPattern" : { "x" : 1 }, "indexName" : "x_1", "isMultiKey" : false, "multiKeyPaths" : { "x" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "x" : [ "[MinKey, MaxKey]" ] }, "keysExamined" : 10, "seeks" : 1, "dupsTested" : 0, "dupsDropped" : 0, "seenInvalidated" : 0 } } } }, "serverInfo" : { "host" : "localhost", "port" : 27017, "version" : "4.0.8", "gitVersion" : "9b00696ed75f65e1ebc8d635593bed79b290cfbb" }, "ok" : 1 } 加索引后结果分析 第一步,分析 executionStats

executionTimeMillis : 查询总耗时 1ms totalKeysExamined : 索引扫描条目 10 totalDocsExamined : 文档扫描条目 10

第二步,分析 executionStages

nReturned = 10 totalKeysExamined = 10 totalDocsExamined = 10 目前已达到理想的状态: nReturned = totalKeysExamined = totalDocsExamined

第三步,分析 stage 状态

从结果看 stage 组合为: Limit+(Fetch+ixscan)

良好的查询组合

对于一般查询,建议stage组合(查询的时候尽可能用上索引):

Fetch+IDHACK Fetch+ixscan Limit+(Fetch+ixscan) PROJECTION+ixscan SHARDING_FITER+ixscan COUNT_SCAN



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3