MongoDB的索引和查询分析(explain)

• 创建普通索引,使用命令 db.collection.createIndex({key:1})
• 创建唯一索引,使用命令 db.collection.createIndex({key:1},{unique:true})

  • a. 语法中 Key 值为你要创建的索引字段,
  • b. 1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

• createIndex() 接收可选参数,可选参数列表如下:

Parameter Type Description
background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。
unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups Boolean 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparse Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSeconds integer 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
v index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weights document 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_language string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_override string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.
  • 在后台创建索引: db.values.ensureIndex({open: 1, close: 1}, {background: true})
  • 查看关于索引的相关信息,使用命令 db.collection.stats()
  • 查看查询使用索引的情况,使用命令 db.collection.find({key:value}).explain()
  • 删除索引,使用命令 db.collection.dropIndex({key:1})
  • 删除集合,也会将集合中的索引全部删除

MongoDB 查询分析
1. MongoDB 查询分析
2. MongoDB 查询分析可以确保我们建议的索引是否有效,是查询语句性能分析的重要工具。
3. MongoDB 查询分析常用函数有:explain() 和 hint()。
使用 explain()

  • explain 操作提供了查询信息,使用索引及查询统计等。有利于我们对索引的优化。
  • 接下来我们在 users 集合中创建 name和 age的索引:

1. db.users.ensureIndex({name:1,age:1})
现在在查询语句中使用 explain :
1. db.users.find({name:"ghost"}).explain(),以上的 explain() 查询返回如下结果:

复制代码
{
    "queryPlanner": {
        "plannerVersion": 1,
        "namespace": "mongotest.users",
        "indexFilterSet": false,
        "parsedQuery": {
            "name": {
                "$eq": "ghost"
            }
        },
        "winningPlan": {
            "stage": "FETCH",
            "inputStage": {
                "stage": "IXSCAN",
                "keyPattern": {
                    "name": 1.0,
                    "age": 1.0
                },
                "indexName": "name_1_age_1",
                "isMultiKey": false,
                "multiKeyPaths": {
                    "name": [],
                    "age": []
                },
                "isUnique": false,
                "isSparse": false,
                "isPartial": false,
                "indexVersion": 2,
                "direction": "forward",
                "indexBounds": {
                    "name": [
                        "[\"ghost\", \"ghost\"]"
                    ],
                    "age": [
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans": []
    },
    "serverInfo": {
        "host": "kf-PC",
        "port": 27017,
        "version": "3.4.9",
        "gitVersion": "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
    },
    "ok": 1.0
}
复制代码

本人使用的是Moongdb3.4.9版本,Mongodb3.0版本的explain返回结果和以前的版本有很大的不同,介于Mongodb3.0的许多优秀特色,将3.0版本的返回分成了3个不同层面:

  • queryPlanner:查询计划的选择器,首先进行查询分析,最终选择一个winningPlan,是explain返回的默认层面。
  • executionStats:为执行统计层面,返回winningPlan的统计结果
  • allPlansExecution:为返回所有执行计划的统计,包括rejectedPlan

所以:我们在查询优化的时候,只需要关注queryPlanner, executionStats即可,因为queryPlanner为我们选择出了winningPlan, 而executionStats为我们统计了winningPlan的所有关键数据。

  • explain.queryPlanner: queryPlanner的
  • explain.queryPlanner.namespace:该值返回的是该query所查询的表
  • explain.queryPlanner.indexFilterSet:针对该query是否有indexfilter
  • explain.queryPlanner.winningPlan:查询优化器针对该query所返回的最优执行计划的详细内容。
  • explain.queryPlanner.winningPlan.stage:最优执行计划的stage,这里返回是FETCH,可以理解为通过返回的index位置去检索具体的文档(stage有多个模式,将在后文中进行详解)。
  • Explain.queryPlanner.winningPlan.inputStage:用来描述子stage,并且为其父stage提供文档和索引关键字。
  • explain.queryPlanner.winningPlan.stage的child stage,此处是IXSCAN,表示进行的是index scanning。
  • explain.queryPlanner.winningPlan.keyPattern:所扫描的index内容,此处是did:1,status:1,modify_time: -1与scid : 1
  • explain.queryPlanner.winningPlan.indexName:winning plan所选用的index。
  • explain.queryPlanner.winningPlan.isMultiKey是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。
  • explain.queryPlanner.winningPlan.direction:此query的查询顺序,此处是forward,如果用了.sort({modify_time:-1})将显示backward。
  • explain.queryPlanner.winningPlan.indexBounds:winningplan所扫描的索引范围,如果没有制定范围就是[MaxKey, MinKey],这主要是直接定位到mongodb的chunck中去查找数据,加快数据读取。
  • explain.queryPlanner.rejectedPlans:其他执行计划(非最优而被查询优化器reject的)的详细返回,其中具体信息与winningPlan的返回中意义相同,故不在此赘述。

stage的类型的意义
mongodb的文档中列出了前4种类型,还有一些没有列出来,但是会比较常见,这里一并解释一下。

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

使用 hint()
• 虽然MongoDB查询优化器一般工作的很不错,但是也可以使用 hint 来强制 MongoDB 使用一个指定的索引。
• 这种方法某些情形下会提升性能。 一个有索引的 collection 并且执行一个多字段的查询(一些字段已经索引了)。
如下查询实例指定了使用 name和 age索引字段来查询:
1. db.users.find({name:"ghost"}).hint({name:1,age:1})
可以使用 explain() 函数来分析以上查询:
1. db.users.find({name:"ghost"}).hint({name:1,age:1}).explain()

 

posted @   郭慕荣  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
历史上的今天:
2022-01-06 spring事务注解@Transactional注解失效场景
2021-01-06 大数据量数据分页查询优化方案
点击右上角即可分享
微信分享提示