优化器Profile
类似于MySQL中的SlowQuery(慢查询日志)。
慢查询日志一般作为优化步骤里的第一步。通过慢查询日志,定位每一条语句的查询时间。比如超过了100ms,那么查询超过100ms的语句需要优化。然后它通过.explain解析影响行数是不是过大,所以导致查询语句超过100ms。所以我们的优化步骤一般就是:1.用慢查询日志找到超过100ms的语句,2.然后再通过explain解析影响行数,分析为什么超过100ms,3.决定是不是需要家加索引。
MongoDB Database Profile是一种慢查询日志功能,可以作为我们优化数据库的依据。
Profile慢查询日志功能默认情况下是关闭的。
有两种方式可以控制Profiling的开关和级别。
方法1:启动MongoDB时加上--profile=级别 即可。
方法2:在客户端调用db.setProfilingLevel( ..级别..)命令来实现实时配置。
Profile信息保存再system.profile中。我们可以通过db.getProfilingLevel()命令来获取当前的Profile级别。
上面profile的级别可以取0,1,2, 含义为:
profile级别 | 语义 |
0 | 不开启 |
1 | 记录慢查询(默认为>100ms) |
2 | 记录所有命令 |
Profile再级别1时候会记录慢命令,上面的默认值为100ms,有默认就有设置,其设置方法和级别有两种方法:
一种是通过添加--slowms启动参数配置。
另一种是db.setProfilingLevel时加上第二个参数。
首先我们还是先准备一个数据库:
> use dt6
switched to db dt6
> db
dt6
> for(i=0;i<10;i++){db.c1.insert({name:"s"+i,age:20+i,parents:{father:"f"+i,mother:"m"+i}})}
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("550aac29f237dcbf6bee2cb2"), "name" : "s0", "age" : 20, "parents" : { "father" : "f0", "mother" : "m0" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb3"), "name" : "s1", "age" : 21, "parents" : { "father" : "f1", "mother" : "m1" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb4"), "name" : "s2", "age" : 22, "parents" : { "father" : "f2", "mother" : "m2" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb5"), "name" : "s3", "age" : 23, "parents" : { "father" : "f3", "mother" : "m3" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb6"), "name" : "s4", "age" : 24, "parents" : { "father" : "f4", "mother" : "m4" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb7"), "name" : "s5", "age" : 25, "parents" : { "father" : "f5", "mother" : "m5" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb8"), "name" : "s6", "age" : 26, "parents" : { "father" : "f6", "mother" : "m6" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cb9"), "name" : "s7", "age" : 27, "parents" : { "father" : "f7", "mother" : "m7" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cba"), "name" : "s8", "age" : 28, "parents" : { "father" : "f8", "mother" : "m8" } }
{ "_id" : ObjectId("550aac2af237dcbf6bee2cbb"), "name" : "s9", "age" : 29, "parents" : { "father" : "f9", "mother" : "m9" } }
>
现在,我们先用第一种方法尝试启动Profile慢查询。
> db.getProfilingLevel()
0
>
> db.setProfilingLevel(1)
{ "was" : 0, "slowms" : 100, "ok" : 1 }
> db.getProfilingLevel()
1
> db.setProfilingLevel(1,10)
{ "was" : 1, "slowms" : 100, "ok" : 1 }
>
> db.setProfilingLevel(1,1000)
{ "was" : 1, "slowms" : 10, "ok" : 1 }
>
> db.setProfilingLevel(1,1000)
{ "was" : 1, "slowms" : 1000, "ok" : 1 }
>
> db.setProfilingLevel(0)
{ "was" : 1, "slowms" : 1000, "ok" : 1 }
> db.getProfilingLevel()
0
>
这里,有个地方需要注意,每次设置之后返回给你的结果是修改之前的状态(包括级别、时间参数)。
第二种方法需要先关闭mongod服务,然后重新启动,并设置--profile和--slowms来设置。
这种方法对整个mongodb的所有数据库有效!!
[neil@neilhost ~]$ sudo pkill mongod
[neil@neilhost ~]$ pstree -p |grep mongod
[neil@neilhost ~]$ sudo /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/dblogs --profile=1 --slowms=200 --fork
about to fork child process, waiting until server is ready for connections.
forked process: 3244
child process started successfully, parent exiting
[neil@neilhost ~]$ pstree -p |grep mongod |-mongod(3244)-+-{mongod}(3245)
| |-{mongod}(3246)
| |-{mongod}(3247)
| |-{mongod}(3248)
| |-{mongod}(3249)
| |-{mongod}(3250)
| |-{mongod}(3251)
| |-{mongod}(3252)
| `-{mongod}(3253)
[neil@neilhost ~]$ sudo /usr/local/mongodb/bin/mongo
MongoDB shell version: 2.6.8
connecting to: test
> db.getProfilingLevel()
1
> use dt6
switched to db dt6
> db.getProfilingLevel()
1
之后,我们再看看关闭服务后,我们重新按照原来的默认方法启动,重新查看数据库的Profile级别,发现已经恢复原样了。这说明,第二种方法,虽然是对所有数据库有效,但是再服务关闭后,这种Profile的级别设置并不会被保存。或者可以理解为,第二种方法是对“服务”的Prolfe设置,而不是对“数据库”的,所以当服务停止时,通过启动参数设置的Profile便消失了。反之,第一种方法,是在客户端控制数据库时对特定数据库的设置,所以设置结果是保存下来的。
话说回来,慢查询的“慢”的定义是什么?
可以理解为比较耗费时间的命令
如果一个查询耗时10ms,就会被记录像下来,记录在system.profile