本文将详细介绍 MongoDB 数据库索引构建情况分析
创建索引可以加快索引相关的查询,但是会增加磁盘空间的消耗,降低写入性能。这时,就需要评判当前索引的构建情况是否合理。有 4 种方法可以使用
1、mongostat 工具
2、profile 集合介绍
3、日志
4、explain 分析
mongostat 是 mongodb 自带的状态检测工具,在命令行下使用。它会间隔固定时间获取 mongodb 的当前运行状态,并输出。如果发现数据库突然变慢或者有其他问题的话,首先就要考虑采用 mongostat 来查看 mongo 的状态
mongostat 是查看 mongodb 运行状态的程序,使用方式如下
- mongostat - h ip: port
【字段说明】
- insert / s: 每秒插入数据库的对象数量,如果是slave,则数值前有 * ,
- 则表示复制集操作query / s: 每秒的查询操作次数update / s: 每秒的更新操作次数delete / s: 每秒的删除操作次数getmore / s: 每秒查询cursor(游标)时的getmore操作数command: 每秒执行的命令数,在主从系统中会显示两个值 (例如3 | 0),分别代表本地 | 复制命令dirty: 脏数据字节的缓存百分比used: 正在使用中的缓存百分比flushes: checkpoint的触发次数在一个轮询间隔期间。一般都是0,间断性会是1,通过计算两个1之间的间隔时间,可以大致了解多长时间flush一次。flush开销是很大的,如果频繁的flush,可能就要找找原因了vsize:虚拟内存使用量,单位MBres: 物理内存使用量,单位MB。res会慢慢的上升,如果res经常突然下降,要查看下是否有别的程序狂吃内存qr: 客户端等待从MongoDB实例读数据的队列长度qw:客户端等待从MongoDB实例写入数据的队列长度ar: 执行读操作的活跃客户端数量aw: 执行写操作的活客户端数量。如果ar或aw数值很大,那么就是DB被堵住了,DB的处理速度不及请求速度。查看是否有开销很大的慢查询。如果查询一切正常,确实是负载很大,就需要加机器了netIn: MongoDB实例的网络进流量netOut:MongoDB实例的网络出流量conn: 打开连接的总数,是qr,
- qw,
- ar,
- aw的总和time: 当前时间
【实例】
插入 100000 条数据,并打开 mongostat 查询 mongodb 运行状态
由下图看出,插入值 insert 值在插入数据时大量增加,在插入完毕后变成 0。flush 两个 1 之间的间隔时间很长,说明性能还不错;res 在慢慢上升,没有出现突然下降的情况,说明没有其他的程序大量占用内容的情况;qrw 及 arw 数据很小,说明数据库读写状态正常,负载较小。总体而言,mongodb 数据库运行状态良好
mongodb 可以通过 profile 来监控数据,进行优化
【级别】
首先,要查看当前是否开启 profile 功能
使用下面的命令会返回 level 等级,值为 0|1|2,0 代表关闭,即不记录任何操作;1 代表记录慢命令 (默认值为 100ms),即记录运行时间超过 100ms 的操作;2 代表全部,即记录任何操作
- db.getProfilingLevel()
使用下面的命令可以设置 level 等级
- db.setProfilingLevel()
如下图所示,默认地,profile 关闭。使用 setProfilingLevel() 方法以 50ms 慢命令的方式开启 profile
【状态】
操作被记录到 system.profile 集合中
通过 db.system.profile.find() 查看当前的监控日志
- op: 操作类型ns: 命名空间query: 查询字符串responseLength: 返回长度ts: 时间mills: 执行耗时
【使用】
在系统中开启 profile 之后,如果 profile 记录的数据非常大,会比较明显的降低系统的性能。因此,profile 的使用场景一般是新系统上线之前的测试阶段,以及刚上线时的观察阶段,查看数据库的设计及应用程序的使用是否正常。如果 profile 记录了大量的字段,需要调整系统附在、调整索引等,减小它的大小
在配置日志文件时,可以使用 verbose 参数来配置日志详细程度,参数值从'v'到'vvvvv','v'越多,详细度越高
日志会记录 mongodb 的运行状态,包括连接时间、当前正在进行的操作等
MongoDB 提供了一个 explain 命令让我们获知系统如何处理查询请求。利用 explain 命令,可以很好地观察系统如何使用索引来加快检索,同时可以针对性优化索引
explain 有三种模式,分别是:queryPlanner、executionStats、allPlansExecution。现实开发中,常用的是 executionStats 模式
首先,插入 10 万条数据
在 time 字段上建立索引
接着,寻找 time 范围在 100 和 200 之间的文档,并使用 explain()
结果分为 queryPlanner、executionStats 和 serverInfo 三个部分。接下来,将分别对这三个部分的结果进行详细分析
【queryPlanner】
queryPlanner.plannerVersion: 版本
queryPlanner.namespace: 查询的表
queryPlanner.indexFilterSet: 针对该 query 是否有 indexfilter
queryPlanner.parsedQuery: 查询条件
queryPlanner.winningPlan: 查询优化器针对该 query 所返回的最优执行计划的详细内容
queryPlanner.winningPlan.stage: 最优执行计划的 stage
queryPlanner.winningPlan.inputStage: 用来描述子 stage,并且为其父 stage 提供文档和索引关键字。
queryPlanner.winningPlan.inputstage.stage,此处是 IXSCAN,表示进行的是 index scanning
queryPlanner.winningPlan.inputstage.keyPattern: 索引键值对
queryPlanner.winningPlan.inputstage.indexName:索引名称
queryPlanner.winningPlan.inputstage.isMultiKey: 是否是 Multikey,此处返回是 false,如果索引建立在 array 上,此处将是 true
queryPlanner.winningPlan.inputstage.direction:查询顺序,此处是 forward,如果用了. sort({time:-1}) 将显示 backward
queryPlanner.winningPlan.inputstage.indexBounds: 所扫描的索引范围
queryPlanner.rejectedPlans:其他执行计划
【executionStats】
executionStats.executionSuccess: 是否成功
executionStats.nReturned: 查询返回条目个数
executionStats.totalKeysExamined: 索引扫描条目个数
executionStats.totalDocsExamined: 文档扫描条目个数
executionStats.executionStages.stage: 扫描类型
executionStats.executionTimeMillis: 整体查询时间
executionStats.executionStages.executionTimeMillisEstimate: 根据索引检索文档获得数据的时间
executionStats.executionStages.inputStage.executionTimeMillisEstimate: 扫描索引所用时间
【serverInfo】
serverInfo.host: 主机名
serverInfo.port: 端口
serverInfo.version: 版本
serverInfo.gitVersion: git 版本
【性能分析】
1、执行时间
executionTimeMillis 值越小越好
2、条目数量
最理想的状态是: nReturned=totalKeysExamined=totalDocsExamined
3、stage 类型
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的返回
不希望看到包含如下的 stage:
- COLLSCAN(全表扫描) SORT(使用sort但是无index)不合理的SKIP SUBPLA(未用到index的$or) COUNTSCAN(不使用index进行count)
来源: http://www.cnblogs.com/xiaohuochai/p/7205278.html