MongoDB性能查询优化工具:MongoDB分析器

MongoDB有两个用于优化查询性能的工具,explain()和MongoDB分析器。explain()是研究单个查询的好工具,通过它可以判断查询的执行性能;而MongoDB分析器有点类似于MySQL的慢查询日志

1.启用MongoDB分析器

在conf文件里面启用分析器

profile=1    #1表示记录超过slowms指定的时间的查询才记录
slowms=500    #单位是毫秒

慢查询将会记录到system.profile中,它的集合大小会被限制在1024KB,所以不必担心磁盘空间会被分析器的日志填满。

Mongo shell启用分析器

$Mongo
>use blog
>db.setProfilingLevel(1,500);

禁用分析器:

$Mongo
>use blog
>db.setProfilingLevel(0);

查看当前分析器状态:

$Mongo
>use blog
>db.getProfilingStatus();

为所有查询启用分析器:(不推荐)

$Mongo
>use blog
>db.setProfilingLevel(2);


2.查找慢查询

>db.system.profile.find()

其中每条记录都包含了一些字段:
● op:操作的类型,比如:insert,query,command,remove...
● query:查询的具体语句,如果是insert操作,则会是insert的语句
● ns:被查询目标的命名空间,一般是数据库名和collection名的组合
● command:如果操作是一个command,则command语句记录在此
keysExamined:以前是nscanned,3.2版本之后改为keysExamined,表示执行此次操作所扫描的索引键记录数
● updateobj:如果操作是一个update,则update语句记录在此
● ndeleted:此次操作删除的文档数
● ninserted: 此次操作插入的文档数
● nModified:此次操作的update的文档数
● writeConflicts:如果一个update语句正在操作一个文档,而另一个update同时进行操作此文档,从而造成的冲突数量
● locks:此次操作产生锁的相关信息
● ntoreturn:返回文档的数目
● nscanned:未返回该文档而扫描的索引条目数目
● ntoskip:被忽略的文档数目
● keyUpdates:该查询更新的索引键数目
● numYields:该查询为其他查询让出锁的次数
● lockStats:数据库花费在获取写锁上的毫秒数
nrturned:返回文档的数目
responseLength:响应的字节长度
millis:执行查询所花费的毫秒数
● ts:以UTC格式显示出查询执行时的时间戳
● client:运行该查询的客户端的连接信息
● user:运行该操作的用户

因为system.profile只是一个普通的集合,所以可以使用MongoDB的查询工具快速找到有问题的查询
# 样例:查找出所有执行时间长于10ms的查询,按照执行时间进行降序排序

>db.system.profile.find({millis:{$gt:10}}) .sort({millis:-1})


3.调整分析器集合的大小

如果处于某种原因,发现分析器集合太小,可以增加它的大小,步骤如下
#停止分析器

$Mongo
>use blog
>db.setProfilingLevel(0);

#删除现有的system.profile集合

>db.system.profile.drop();

#创建新的集合,假设为50M

>db.createCollection("system.profile",{capped:true,size:50*1024*1024})
>{"OK":1}

#重新启用分析器

>db.setProfilingLevel(1)


4.日常使用查询

#返回最近的10条记录

db.system.profile.find().limit(10).sort({ ts : -1 }).pretty()

#返回所有的操作,除command类型的

db.system.profile.find( { op: { $ne : 'command' } } ).pretty()

#返回特定集合

db.system.profile.find( { ns : 'mydb.test' } ).pretty()

#返回大于5毫秒慢的操作

db.system.profile.find( { millis : { $gt : 5 } } ).pretty()

#从一个特定的时间范围内返回信息

db.system.profile.find(
                       {
                        ts : {
                              $gt : new ISODate("2012-12-09T03:00:00Z") ,
                              $lt : new ISODate("2012-12-09T03:40:00Z")
                             }
                       }
                      ).pretty()

#特定时间,限制用户,按照消耗时间排序

db.system.profile.find(
                       {
                         ts : {
                               $gt : new ISODate("2011-07-12T03:00:00Z") ,
                               $lt : new ISODate("2011-07-12T03:40:00Z")
                              }
                       },
                       { user : 0 }
                      ).sort( { millis : -1 } )
添加新评论