Mongodb性能检查与处理
一、检查server、db、collection状态... 1
一、检查server、db、collection状态
1、检查server状态:
db.serverStatus()
2、检查db状态:
use testdb;
db.stats();
3、检查collection状态:
use testdb;
db.collection_name.stats();
mongostat会间隔固定时间获取mongodb的当前运行状态,并输出。如果发现数据库突然变慢或者有其他问题的话,可采用mongostat来查看mongo的状态
1、 Mongostat命令参数说明
./mongostat -help
View live MongoDB performancestatistics.
usage: mongostat [options][sleep time]
sleep time: time to wait (inseconds) between calls
Options:
--help produce helpmessage
-v [ --verbose ] be more verbose (includemultiple times
for more verbosity e.g. -vvvvv)
--quiet silence all nonerror diagnostic
messages
--version print theprogram's version and exit
-h [ --host ] arg mongo host to connect to (<set
name>/s1,s2 for sets)
--port arg server port. Canalso use --host
hostname:port
--ipv6 enable IPv6support (disabled by
default)
-u [ --username ] arg username
-p [ --password ] arg password
--authenticationDatabase arg user source (defaults to dbname)
--authenticationMechanism arg (=MONGODB-CR)
authentication mechanism
--gssapiServiceName arg (=mongodb) Service name to use when authenticating
using GSSAPI/Kerberos
--gssapiHostName arg Remote host name to use forpurpose of
GSSAPI/Kerberos authentication
--noheaders don't output columnnames
-n [ --rowcount ] arg (=0) number of stats lines to print (0for
indefinite)
--http use httpinstead of raw db connection
--discover discover nodes anddisplay stats for
all
--all all optionalfields
2、 mongostat输出结果
输出结果说明:
insert: 一秒内的插入数
query : 一秒内的查询数
update: 一秒内的更新数
delete: 一秒内的删除数
10条简单的查询可能比一条复杂的查询速度还快, 所以数值的大小,意义并不大。但至少可以知道,现在是否在处理查询,是否在插入。
getmore: 查询时游标(cursor)的getmore操作
command: 一秒内执行的命令数。比如批量插入,也只认为是一条命令。 因此意义不大。
如果是副本集,会显示两个值, local|replicated,通过这两个数值的比较,或许可以看出点问题。
flushes: 一秒内flush的次数(一般都是0,或者1,通过计算两个1之间的间隔时间,可以大致了解多长时间flush一次。 flush开销是很大的,如果频繁的flush,可能就要找找原因了。)
mapped,vsize,res: 这个和用top看到的一样,mapped,vsize一般不会有大的变动, res会慢慢的上升,如果res经常突然下降,去查查是否有别的程序狂吃内存。
faults:别被这个名字吓着,与serverStatus()中的pageFaults的意义相同。大压力下这个数值往往不为0。如果经常不为0,那就该考虑内存配置是否合理。
locked:这里指的是databae上的写锁锁住的时间百分比。如果这个数值过大(经常超过10%),并且结合faults值持续加大,说明由于未能在内存中即使获取数据,导致db出现锁阻塞的情况很严重。那就需要检查内存配置,存储配置是否合理。
idx miss: 非常重要的参数, 正常情况下,对于oltp系统,所有的查询都应该通过索引,也就是idx miss为0。如果这里数值较大,是不是缺少索引。
qr|qw:queue lengths for clients waiting (read|write)
ar|aw: active clients (read|write)
如果这两个数值很大,那么就是DB被堵住了,DB的处理速度不及请求速度。
看看是否有开销很大的慢查询。如果查询一切正常,确实是负载很大,就需要加机器了。
netIn:network traffic in - bits
netOut: network traffic out - bits
网络带宽压力,一般MongoDB,网络不会成为瓶颈
conn:number of open connections。MongoDB为每一个连接创建一个线程,线程的创建和释放也是有开销的。尽量不要让这个数值很大。
repl: 服务器当前状态
M -master
SEC - secondary
REC - recovering
UNK - unknown
SLV - slave
time: 当前时间
---mongostat返回每一秒的数据,持续20s
方法1:
mongostat -h cnsz081233 --port 24000--authenticationDatabase admin -udbmgr -ppwd -rowcount 20 1
方法2:
mongostat -h cnsz081233 --port 24000--authenticationDatabase admin -udbmgr -ppwd -rowcount 20
方法3:
mongostat -h cnsz081233 --port 24000--authenticationDatabase admin -udbmgr -ppwd -n 20 1
---mongostat返回每5min(300s)返回一次数据
方法1:
mongostat -hcnsz081233 --port 24000 --authenticationDatabase admin -udbmgr -ppwd - rowcount0 300
方法2:
mongostat -h cnsz081233 --port 24000--authenticationDatabase admin -udbmgr -ppwd -n 0 300
方法3:
mongostat -h cnsz081233 --port 24000–authenticationDatabase -udbmgr -ppwd admin 300
---mongostat每5分钟返回一次数据,持续1小时(即返回12次)
方法1:
mongostat -h cnsz081233 --port 24000–authenticationDatabase -udbmgr -ppwd -rowcount 12 300
方法2:
mongostat -h cnsz081233 --port 24000 –authenticationDatabase-udbmgr -ppwd -n 12 300
---显示整个集群所有成员的信息
mongostat -h cnsz081233 --port 24000--authenticationDatabase admin -udbmgr -ppwd --discover
三、检查当前server的读写压力:mongotop
用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。 mongotop提供每个集合的水平的统计数据
1、 mongotop命令参数
>mongotop --help
View live MongoDB collectionstatistics.
Options:
--help produce helpmessage
-v [ --verbose ] be more verbose (includemultiple times
formore verbosity e.g. -vvvvv)
--quiet silence all nonerror diagnostic
messages
--version print theprogram's version and exit
-h [ --host ] arg mongo host to connect to ( <set
name>/s1,s2 for sets)
--port arg server port. Canalso use --host
hostname:port
--ipv6 enable IPv6support (disabled by
default)
-u [ --username ] arg username
-p [ --password ] arg password
--authenticationDatabase arg user source (defaults to dbname)
--authenticationMechanism arg (=MONGODB-CR)
authentication mechanism
--gssapiServiceName arg (=mongodb) Service name to use when authenticating
using GSSAPI/Kerberos
--gssapiHostName arg Remote host name to use forpurpose of
GSSAPI/Kerberos authentication
--locks use db lock infoinstead of top
2、 mongotop输出结果
没有--locks参数,输出结果为:
加入--locks参数,输出结果为:
输出属性说明:
ns:数据库命名空间,后者结合了数据库名称和集合。
db:数据库的名称。名为 . 的数据库针对全局锁定,而非特定数据库。
total:mongod在这个命令空间上花费的总时间。
read:在这个命令空间上mongod执行读操作花费的时间。
write:在这个命名空间上mongod进行写操作花费的时间。
--查询cnsz081233主机上port=24000的节点的读写情况,刷新频率为1s:
./mongotop --port 24000 --host cnsz081233 --authenticationDatabase admin-udbmgr -ppwd
db.currentOp();
或:db.$cmd.sys.inprog.find();
产出结果为:
重要参数说明:
opid:操作进程号
op:操作类型(query,update...)
ns:命名空间(namespace),即操作对象
query:显示操作的具体内容
lockType:锁类型,表明是写锁or读锁
如果在没有负载的机器上,执行db.currentOp(),则显示:{
"inprog"
: [ ] }
根据上步获取进程号后,执行:
db.killOP(opid);
>db.getLastError()
在mongodb中是否提供慢查询记录功能呢,可以,通过开启profiling。此功能在运行的实例上搜集有关MongoDB的写操作、游标、数据命令等。可以在数据库级别开启,也可以在实例级别开启,搜集到的信息放在system.profile集合中,该集合为capped collection,会被轮循清理。
profiling level说明:
0:关闭,不收集任何数据。
1:收集慢查询数据,默认是100毫秒。
2:收集所有数据
---查看当前profiling level:
db.getProfilingLevel()
---查看当前profiling status:
db.getProfilingStatus()
开启慢查询记录,并设置时间阀值为200ms:
db.setProfilingLevel(1,200)
--如果不设置时间阀值,则默认为慢查询记录时间阀值为100ms:
db.setProfilingLevel(1)
db.setProfilingLevel(0)
db.setProfilingLevel(2)
--调整慢查询时间阀值为200ms
db.setProfilingLevel(1,200)
>db.system.profile.find()
重要参数说明:
op:操作类型,有insert、query、update、remove、getmore、command
ns : 操作的集合
ts :命令在何时执行
info :命令的详细信息
reslen: 返回结果集的大小
nscanned:本次查询扫描的记录数
nreturned: 本次查询实际返回的结果集
mills:该命令的执行耗时(单位:毫秒)
query : 查询语句
ntoreturn : 返回的记录数
ntoskip :skip()方法指定的跳跃数
nscanned : 扫描数量
keyUpdates : 索引更新的数量,改变一个索引键带有一个小的性能开销,因为数据库必须删除旧的key,并插入一个新的key到B-树索引
lockStats :锁信息,R:全局读锁;W:全局写锁;r:特定数据库的读锁;w:特定数据库的写锁
timeLockedMicros : 锁
timeAcquiringMicros :锁等待
responseLength: 结果字节长度
millis: 消耗的时间(毫秒)
ts : 语句执行的时间
client :链接ip或则主机
allUsers ,user:用户
scanAndOrder:是一个布尔值,是True当一个查询不能使用的文件的顺序在索引中的排序返回结果:MongoDB中必须将其接收到的文件从一个游标后的文件进行排序。如果scanAndOrder是False,MongoDB的可使用这些文件的顺序索引返回排序的结果。
moved:更新操作在磁盘上移动一个或多个文件到新的位置。表明本次update是否移动了硬盘上的数据,如果新记录比原记录短,通常不会移动当前记录,如果新记录比原记录长,那么可能会移动记录到其它位置,这时候会导致相关索引的更新.磁盘操作更多,加上索引更新,会使得这样的操作比较慢.
nupdated:更新文档的数目
getmore:这是一个getmore 操作,getmore通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取的。
如果nscanned(扫描的记录数)远大于nreturned(返回结果的记录数)的话,要考虑通过加索引来优化记录定位了。
responseLength 如果过大,说明返回的结果集太大了,这时要看是否只需要必要的字段。
---返回最近的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()
---返回大于500毫秒的慢操作
db.system.profile.find( { millis : { $gt : 500 } }).pretty()
---返回特定的时间范围内的慢查询信息
db.system.profile.find( { ts : { $gt : newISODate("2015-06-09T03:00:00Z") , $lt : newISODate("2015-06-09T03:40:00Z") } } ).pretty()
--返回特定时间,特定用户,按照消耗时间排序
db.system.profile.find( { ts: { $gt : new ISODate("2015-06-09T03:00:00Z") , $lt : newISODate("2015-06-09T03:40:00Z") } }, { user : “ucms@ucms” } ).sort( {millis : -1 } )
八、查询sql执行计划
---显示查询的执行计划:
db.checkupinfo.find({"checkupid": "70200009"}).explain()
显示结果:cursor为BtreeCursor,说明使用了checkupid_1的索引。如果是basicCursor,则说明走全表扫描。
{
"cursor" : "BtreeCursorcheckupid_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1, --扫描对象数量
"nscanned" : 1,
"nscannedObjectsAllPlans" :1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false, --是否扫描后还进行排序操作
"indexOnly" : false, --是否只是使用索引,因为此处还需要返回doc获取其他属性,因此不可能只使用索引。
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0, --查询用时
"indexBounds" : {
"checkupid" : [
[
"70200009",
"70200009"
]
]
},
"server" :"cnsz081235:24002",
"filterSet" : false
}
九、强制sql使用索引
db.checkupinfo.find({"checkupid": "70200009"}).hint({checkupid:1})
可以通过hint来强制使用checkupid的索引。