返回顶部
首页 > 资讯 > 数据库 >MongoDB慢查询与索引实例详解
  • 368
分享到

MongoDB慢查询与索引实例详解

mongodb索引原理mongodb慢查询日志MongoDB索引查询 2022-07-29 10:07:11 368人浏览 泡泡鱼
摘要

目录mongoDB慢查询MonGoDB索引总结 MongoDB慢查询 慢查询分析 开启内置的慢查询分析器 db.setProfilingLevel(n,m),n的取值可选0,1,2 0:表示不记录1:表示记录

MongoDB慢查询

慢查询分析

  • 开启内置的慢查询分析器
db.setProfilingLevel(n,m),n的取值可选0,1,2
  • 0:表示不记录
  • 1:表示记录慢速操作,如果值为1,m需要传慢查询的阈值,单位为ms
  • 2:表示记录所有的读写操作

示例:

db.setProfilingLevel(1,3)
db.system.profile.find().sort({millis:-1}).limit(3)

MongoDB索引

什么是索引?

索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。索引目标是提高数据库的查询效率,没有索引的话,查询会进行全表扫描(scaneverydocumentinacollection),数据量大时严重降低了查询效率。默认情况下Mongo在一个集合(collection)创建时,自动地对集合的_id创建了唯一索引。

索引结构

MongoDB的索引结构为B树

B树非叶子节点也存了数据,查询效率不固定,最好的情况是O(1),在单次查询的情况下平均性能是优于B+树的。而MongoDB是被作为一个单一查询比较多,遍历数据比较少的一个定位。所以采用了B树。

那为什么不用单次性能更好的Hash结构呢?

因为虽然遍历数据的情况较少,但是对于遍历数据也需要有相对较好的性能支持。Hash这种性能表现较为极端的数据结构往往只能在简单、极端的场景下使用。

索引分类

  • 单键索引

MongoDB支持所有数据类型中的单个字段索引,并且可以在文档的任何字段定义。对于单个字段索引,索引键的排序顺序无关紧要,因为MongoDB可以在任一方向读取索引。

db.集合名.createIndex({"字段名":排序方式})

示例:

db.user.createIndex({"name":1})

创建后可以通过查询索引命令查看是否创建成功。

db.user.getIndexes()
  • 唯一索引

设置unique为true。示例:

db.book.createIndex({title:1},{unique:true})
  • 过期索引TTL

TTL索引是MongoDB中一种特殊的索引,可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,并且字段类型必须是日期类型。

db.集合名.createIndex({"日期字段":排序方式}, {expireAfterSeconds: 秒数})

示例:

db.user.createIndex({"bithday":1}, {expireAfterSeconds: 10})

创建过期索引后,有bithday字段的文档会在约10秒后自动删除。

  • 复合索引

通常我们需要在多个字段上进行搜索,如果是这种情况,可以考虑使用复合索引。复合索引支持基于多个字段的索引,这扩展了索引的概念并将它们扩展到索引中的更大域。

建立复合索引需要注意:字段顺序和索引方向。它也是遵循最左前缀原则。

db.集合名.createIndex( { "字段名1" : 排序方式, "字段名2" : 排序方式 } )
  • 多键索引

针对属性包含数组数据的情况,MongoDB支持针对数组中每一个element创建索引,支持Strings、numbers、nested documents。

示例:

//type是集合类型的数据,创建的就是多键索引
db.book.insert({title:"Java",type:["技术","IT"]})

db.book.createIndex({type:1})
  • 哈希索引

针对属性的哈希值进行索引查询,当要使用Hashed Index时,MongoDB能够自动计算hash值来进行查询。

db.集合.createIndex({"字段": "hashed"})
  • 地理空间索引

针对地理空间坐标数据创建索引。2dsphere索引:用于存储和查找球面上的点。

2d索引:用于存储和查找平面上的点。

db.集合名.ensureIndex({字段名:"2dsphere"})

示例:

//插入数据
db.company.insert({
    loc:{type:"Point",coordinates:[116.482451,39.914176]},
    name:"大望路",
    category:"Parks"
})

//创建索引
db.company.ensureIndex({loc:"2dsphere"})

//查询范围内的数据
db.company.find({
    "loc":{
    "$geoWithin":{
        "$center":[[116.482450,39.914176],0.05]
    }
}
})

//距离指定位置最近的2个点
db.company.aggregate([
    {
        $geoNear: {
          near: {
              type: "Point",
              coordinates: [ 116.472451,39.814176]
          },
          key:"loc",
          distanceField: "dist.calculated",
          spherical: true
        }
    },
    {
        $limit: 2
    }
    ])

索引管理

  • 创建索引并在后台运行

有时数据量大的时候,创建索引的动作是比较耗费时间的,这时后台运行就比较有用了。

db.COLLECTION_NAME.createIndex({"字段":排序方式}, {background: true});
  • 查询某个集合的索引
db.COLLECTION_NAME.getIndexes()
  • 查看索引大小
db.COLLECTION_NAME.totalIndexSize()
  • 索引重建
db.COLLECTION_NAME.reIndex()
  • 索引删除
db.COLLECTION_NAME.dropIndex("INDEX-NAME")
db.COLLECTION_NAME.dropIndexes()
注意: _id 对应的索引是删除不了的

Explain分析

explain()是一个查询分析的方法,它还可以接收不同的参数来查看更详细的查询计划。

简单示例:

db.user.find().explain()
db.user.find({name:"test1"}).explain("executionStats")

参数介绍:

  • queryPlanner:queryPlanner是默认参数,具体执行计划信息参考下面的表格
  • executionStats:executionStats会返回执行计划的一些统计信息(有些版本中和allPlansExecution等同)。
  • allPlansExecution:allPlansExecution用来获取所有执行计划,结果参数基本与上文相同
  • queryPlanner参数查询返回值含义
参数含义
plannerVersion查询计划版本
namespace要查询的集合(该值返回的是该query所查询的表)数据库.集合
indexFilterSet针对该query是否有indexFilter
parsedQuery查询条件
winningPlan被选中的执行计划
winningPlan.stage被选中执行计划的stage(查询方式),常见的有:COLLSCAN/全表扫描:(应该知道就是CollectionScan,就是所谓的“集合扫描”,和Mysql中tablescan/heapscan类似,这个就是所谓的性能最烂最无奈的由来)、IXSCAN/索引扫描:(是IndexScan,这就说明我们已经命中索引了)、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询等
winningPlan.inputStage用来描述子stage,并且为其父stage提供文档和索引关键字。
winningPlan.stage的child stage如果此处是IXSCAN,表示进行的是index scanning。
winningPlan.keyPattern所扫描的index内容
winningPlan.indexNamewinning plan所选用的index。
winningPlan.isMultiKey是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。
winningPlan.direction此query的查询顺序,此处是forward,如果用了.sort({字段:-1})将显示backward。
filter过滤条件
winningPlan.indexBoundswinningplan所扫描的索引范围,如果没有制定范围就是[MaxKey,MinKey],这主要是直接定位到mongodb的chunck中去查找数据,加快数据读取。
rejectedPlans被拒绝的执行计划的详细返回,其中具体信息与winningPlan的返回中意义相同,故不在此赘述
serverInfoMongoDB服务器信息
  • executionStats参数查询返回值含义
参数含义
executionSuccess是否执行成功
nReturned返回的文档数
executionTimeMillis执行耗时
totalKeysExamined索引扫描次数
totalDocsExamined文档扫描次数
executionStages这个分类下描述执行的状态
stage扫描方式,具体可选值与上文的相同
nReturned查询结果数量
executionTimeMillisEstimate检索document获得数据的时间
inputStage.executionTimeMillisEstimate该查询扫描文档 index所用时间
works工作单元数,一个查询会分解成小的工作单元
advanced优先返回的结果数
docsExamined文档检查数目,与totalDocsExamined一致。检查了总共的document个数,而从返回上面的nReturned数量

这么多返回值我们怎么分析呢?

首先我们先造点数据:

for(var i=0;i<100000;i++){
    db.user.insert({
        name:"test"+i,
        explectSalary:10+i
    })
}

查询耗时115

db.user.find({name:'test1'}).explain("allPlansExecution")

然后创建索引

db.user.createIndex({name:1})

再次查询,查看耗时变为了2。速度直线飙升。我们再对返回结果做一个分析:

{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test.user",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "name" : {
                                "$eq" : "test1"
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "name" : 1
                                },
                                "indexName" : "name_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "name" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "name" : [
                                                "[\"test1\", \"test1\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 2,
                "executionTimeMillis" : 2,
                "totalKeysExamined" : 2,
                "totalDocsExamined" : 2,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 2,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 3,
                        "advanced" : 2,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "iseoF" : 1,
                        "docsExamined" : 2,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 2,
                                "executionTimeMillisEstimate" : 0,
                                "works" : 3,
                                "advanced" : 2,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 0,
                                "restoreState" : 0,
                                "isEOF" : 1,
                                "keyPattern" : {
                                        "name" : 1
                                },
                                "indexName" : "name_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "name" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "name" : [
                                                "[\"test1\", \"test1\"]"
                                        ]
                                },
                                "keysExamined" : 2,
                                "seeks" : 1,
                                "dupsTested" : 0,
                                "dupsDropped" : 0
                        }
                },
                "allPlansExecution" : [ ]
        },
        "serverInfo" : {
                "host" : "10.0.3.15",
                "port" : 27017,
                "version" : "4.2.21",
                "gitVersion" : "b0aeed9445ff41af07449fa757e1f231bce990b3"
        },
        "ok" : 1
}

折叠

重要参数介绍:

  • executionStats.executionTimeMillis 整体查询时间
  • executionStats.executionStages.executionTimeMillisEstimate 该查询检索document获得数据的时间
  • executionStats.inputStage.executionTimeMillisEstimate 该查询扫描文档index所用的时间
  • executionStats.nReturned 查询返回的条数
  • executionStats.totalKeysExamined:索引扫描条数
  • executionStats.totalDocsExamined:文档扫描条数

对于一个查询,我们最理想的状态是:nReturned=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运算
  • TEXT:使用全文索引进行查询时候的stage返回
  • PROJECTION:限定返回字段时候stage的返回

还有的是上面的组合

  • Fetch+IDHACK
  • Fetch+IXSCAN
  • Limit+(Fetch+IXSCAN)
  • PROJECTION+IXSCAN
  • SHARDING_FITER+IXSCAN

总结 

到此这篇关于MongoDB慢查询与索引的文章就介绍到这了,更多相关MongoDB慢查询与索引内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: MongoDB慢查询与索引实例详解

本文链接: https://lsjlt.com/news/33494.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MongoDB慢查询与索引实例详解
    目录MongoDB慢查询MongoDB索引总结 MongoDB慢查询 慢查询分析 开启内置的慢查询分析器 db.setProfilingLevel(n,m),n的取值可选0,1,2 0:表示不记录1:表示记录...
    99+
    2022-07-29
    mongodb索引原理 mongodb慢查询日志 MongoDB索引查询
  • mongodb查询与索引优化
    索引:    查询语句:        db.products.find({            "details.manufacturer": "acme",            "pricing.s...
    99+
    2024-04-02
  • MongoDB TTL索引的实例详解
    MongoDB TTL索引的实例详解 TTL索引是一种特殊类型的单字段索引,主要用于当满足某个特定时间之后自动删除相应的文档。也就是说集合中的文档有一定的有效期,超过有效期的文档就会失效,会被移除。也即是数...
    99+
    2024-04-02
  • MongoDB 查询操作的实例详解
    MongoDB 查询操作的实例详解 使用find或findOne进行查询。并可以进行范围查询、数据集查询、不等式查询,以及其他的一些查询。 查询将会返回DBcursor 游标只有在你需要的时候返回文档 ...
    99+
    2024-04-02
  • mongodb怎么查询指定索引
    在 MongoDB 中,可以使用 `db.collection.find()` 方法来查询指定索引。可以通过使用 `.hint()`...
    99+
    2023-09-04
    mongodb
  • mysql in索引慢查询优化实现步骤解析
    目录记一次mysql慢查询优化第一步、分析SQL第二步、检查索引,执行explainwhywhy第三步、检查两个关联字段的字段类型、长度和字符类型是否一致第四步、强制使用索引操作第五...
    99+
    2023-05-20
    mysql in慢查询优化 mysql in索引
  • 实例讲解MySQL 慢查询
    简介        开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。 一、配...
    99+
    2022-05-25
    MySQL 慢查询 MySQL 查询
  • 一个索引导致查询缓慢
    一、环境centos 6.7 、oracle 11.2,表根据日期按月分区二、测试1、查询表存在索引ind_1(org_id,visit_date,visit_no,patient_id)执行查询语句执行计...
    99+
    2024-04-02
  • mysql or走索引加索引及慢查询的作用
    目录 前言一 概述二 实验表结构声明三 mysql不走索引归类以及详细解析1. 查询条件在索引列上使用函数操作,或者运算的情况2. 查询条件字符串和数字之间的隐式转换3. 特殊修饰符 %%, Or 将不走索引4...
    99+
    2024-04-02
  • mysql or走索引加索引及慢查询的作用
    目录 前言一 概述二 实验表结构声明三 Mysql不走索引归类以及详细解析1. 查询条件在索引列上使用函数操作,或者运算的情况2. 查询条件字符串和数字之间的隐式转换3. ...
    99+
    2024-04-02
  • 深入解析MongoDB的查询优化与索引设计原则
    MongoDB是一种流行的NoSQL数据库,它被广泛应用于许多大规模的Web应用程序和数据驱动的应用程序。在使用MongoDB时,查询优化和索引设计是非常重要的,可以显著提高数据库的性能和响应速度。本文将深入解析MongoDB的查询优化和索...
    99+
    2023-11-02
    MongoDB 查询优化 索引设计
  • 详解MySQL 慢查询
    查询mysql的操作信息 show status -- 显示全部mysql操作信息 show status like "com_insert%"; -- 获得mysql的插入次数; show status l...
    99+
    2022-05-30
    MySQL 查询 MySQL 慢查询
  • 慢查询sql详解
    慢查询sql 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边...
    99+
    2023-09-05
    sql mysql 数据库
  • mongodb索引速度慢如何解决
    当MongoDB的索引查询速度变慢时,可以尝试以下几种解决方法:1. 优化查询语句:检查查询语句是否能够充分利用现有索引,是否存在不...
    99+
    2023-09-04
    mongodb
  • MySQL索引原理及慢查询优化
      MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库。虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程师的必修课,...
    99+
    2022-05-31
    MySQL
  • MongoDB中的定时索引示例详解
    MongoDB中存在一种索引,叫做TTL索引(time-to-live index,具有生命周期的索引),这种索引允许为每一个文档设置一个超时时间。一个文档达到预设置的老化程度后就会被删除。 数据到期对于...
    99+
    2024-04-02
  • MongoDB多表关联查询操作实例详解
    本文实例讲述了MongoDB多表关联查询操作。分享给大家供大家参考,具体如下: Mongoose的多表关联查询 首先,我们回忆一下,MySQL多表关联查询的语句: student表: calss表: 通...
    99+
    2024-04-02
  • MongoDB索引机制详解
    目录⭐ MongoDB 的索引机制⭐ 索引的类型 创建索引 - 单字段索引 创建索引 - 多字段索引 创建索引 - 唯一性索引 创建索引 - 文本索引 创建索引 - 地理空间索引⭐ 查看所有索引⭐ 删除索引⭐ Mongo...
    99+
    2023-04-23
    MongoDB的索引机制 MongoDB的索引 Python MongoDB
  • Redis慢查询日志及慢查询分析详解
    目录前提介绍单线程命令的处理机制本章内容什么是慢查询慢查询日志Redis慢查询日志Redis慢查询的危害Redis客户端执行一条命令的步骤慢查询引发的问题阈值和慢查询的日志的设置阈值...
    99+
    2023-01-28
    Redis慢查询日志分析 Redis慢查询
  • 一个cp命令引发的mongodb大量慢查询
    遇到问题:凌晨收到报警,某mongodb服务器cpu load超过8。由于没有影响到业务,第二天一早开始查原因。查原因:1. 先了解该服务器上的应用有哪些    该db服务器主要应用只有...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作