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

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: MongoDB的索引和查询分析(explain)

 索引

    1. 索引就是用来加速查询的。

    2. 数据库索引与书籍的索引类似:
    3. 有了索引就不需要翻遍整本书,数据库则可以直接在索引中查找,使得查找速度能提高几个数量级。
    4. 在索引中找到条目以后,就可以直接跳转到目标文档的位置。
      1. 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,
      2. 索引是对数据库表中一列或多列的值进行排序的一种结构
        • 创建普通索引,使用命令 db.collection.ensureIndex({key:1})
        • 创建唯一索引,使用命令 db.collection.ensureIndex({key:1},{unique:true})
          1. 语法中Key值为你要创建的索引字段,
          2. 1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。
            • ensureIndex() 接收可选参数,可选参数列表如下:

            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.

            • 在后台创建索引:
              1. 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 集合中创建 nameage的索引:
                      1. db.users.ensureIndex({name:1,age:1})

                      现在在查询语句中使用 explain :

                        1. db.users.find({name:"ghost"}).explain()

                        以上的 explain() 查询返回如下结果:

                          1. /* 1 */
                          2. {
                          3. "queryPlanner":{
                          4. "plannerVersion":1,
                          5. "namespace":"mongotest.users",
                          6. "indexFilterSet":false,
                          7. "parsedQuery":{
                          8. "name":{
                          9. "$eq":"ghost"
                          10. }
                          11. },
                          12. "winningPlan":{
                          13. "stage":"FETCH",
                          14. "inputStage":{
                          15. "stage":"IXSCAN",
                          16. "keyPattern":{
                          17. "name":1.0,
                          18. "age":1.0
                          19. },
                          20. "indexName":"name_1_age_1",
                          21. "isMultiKey":false,
                          22. "multiKeyPaths":{
                          23. "name":[],
                          24. "age":[]
                          25. },
                          26. "isUnique":false,
                          27. "isSparse":false,
                          28. "isPartial":false,
                          29. "indexVersion":2,
                          30. "direction":"forward",
                          31. "indexBounds":{
                          32. "name":[
                          33. "[\"ghost\", \"ghost\"]"
                          34. ],
                          35. "age":[
                          36. "[MinKey, MaxKey]"
                          37. ]
                          38. }
                          39. }
                          40. },
                          41. "rejectedPlans":[]
                          42. },
                          43. "serverInfo":{
                          44. "host":"kf-PC",
                          45. "port":27017,
                          46. "version":"3.4.9",
                          47. "gitVersion":"876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
                          48. },
                          49. "ok":1.0
                          50. }

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

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

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

                              1. explain.queryPlanner: queryPlanner

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

                              stage的类型的意义

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

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

                                17. 附:explain查询结果解析官方文档:
                                18. https://docs.mongodb.org/v3.0/reference/explain-results/

                                使用 hint()

                                  • 虽然MongoDB查询优化器一般工作的很不错,但是也可以使用 hint 来强制 MongoDB 使用一个指定的索引
                                  • 这种方法某些情形下会提升性能。 一个有索引的 collection 并且执行一个多字段的查询(一些字段已经索引了)。

                                  如下查询实例指定了使用 nameage索引字段来查询:

                                    1. db.users.find({name:"ghost"}).hint({name:1,age:1})

                                    可以使用 explain() 函数来分析以上查询:

                                      1. db.users.find({name:"ghost"}).hint({name:1,age:1}).explain()

                                      参考来源: Mongodb使用explain优化查询(1)--explain输出参数解析-danliz_nh-ChinaUnix博客

                                      参考来源:http://www.runoob.com/mongodb/mongodb-analyzing-queries.html


                                      相关实践学习
                                      MongoDB数据库入门
                                      MongoDB数据库入门实验。
                                      快速掌握 MongoDB 数据库
                                      本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
                                      目录
                                      相关文章
                                      |
                                      3月前
                                      |
                                      存储 NoSQL 关系型数据库
                                      |
                                      3月前
                                      |
                                      NoSQL 关系型数据库 MySQL
                                      深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
                                      在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样
                                      65 1
                                      |
                                      16天前
                                      |
                                      JSON NoSQL MongoDB
                                      mongodb导出聚合查询的数据
                                      mongodb导出聚合查询的数据
                                      |
                                      20天前
                                      |
                                      NoSQL MongoDB 索引
                                      【MongoDB】MongoDB 覆盖索引
                                      【4月更文挑战第3天】【MongoDB】MongoDB 覆盖索引
                                      |
                                      3月前
                                      |
                                      存储 NoSQL 关系型数据库
                                      4-MongoDB索引知识
                                      MongoDB索引知识
                                      |
                                      3月前
                                      |
                                      NoSQL MongoDB 索引
                                      【待完善】MongoDB - 使用索引
                                      【待完善】MongoDB - 使用索引
                                      30 0
                                      |
                                      3月前
                                      |
                                      存储 NoSQL MongoDB
                                      MongoDB之索引和聚合
                                      【1月更文挑战第21天】 一、索引 1、说明 2、原理 3、相关操作 3.1、创建索引 3.2、查看集合索引 3.3、查看集合索引大小 3.4、删除集合所有索引(不包含_id索引) 3.5、删除集合指定索引 4、复合索引 二、聚合 1、说明 2、使用
                                      65 0
                                      |
                                      3月前
                                      |
                                      存储 NoSQL 安全
                                      go 连接mongodb执行查询的代码
                                      在Go语言中,你可以使用官方的MongoDB驱动程序 `"go.mongodb.org/mongo-driver/mongo"` 来连接MongoDB并执行查询。以下是一个简单的示例代码,演示如何连接MongoDB并执行查询: 首先,确保你已经安装了MongoDB驱动程序: ```bash go get go.mongodb.org/mongo-driver/mongo ``` 然后,可以使用以下示例代码: ```go package main import ( "context" "fmt" "log" "time" "go.mongodb.org/mongo-driv
                                      |
                                      4月前
                                      |
                                      存储 监控 NoSQL
                                      数据存储与分析:办公室电脑屏幕监控的MongoDB应用实例
                                      在当今数字时代,数据的存储和分析变得愈发重要,尤其是在办公环境中,对电脑屏幕进行监控成为一种日益普遍的需求。本文将介绍如何利用MongoDB数据库实现办公室电脑屏幕监控,并通过代码实例展示其应用。
                                      219 0
                                      |
                                      4月前
                                      |
                                      缓存 NoSQL MongoDB
                                      MongoDB数据库查询性能提高40倍?
                                      MongoDB数据库查询性能提高40倍?
                                      95 0