1、通过currentOp查看当前的操作
要想找到是哪些操作拖慢了速度,看看正在进行的操作不失为一种简单的办法。
db.currentOp()
{
"inprog" : [
{
"type" : "op",
"host" : "mongodb-0:27017",
"desc" : "WT-OplogTruncaterThread-local.oplog.rs",
"active" : true,
"currentOpTime" : "2021-05-05T02:14:46.751+0000",
"opid" : 2.0,
"op" : "none",
"ns" : "",
"command" : {
},
"numYields" : 0.0,
"locks" : {
},
"waitingForLock" : false,
"lockStats" : {
"ReplicationStateTransition" : {
"acquireCount" : {
"w" : NumberLong(2)
}
},
"Global" : {
"acquireCount" : {
"w" : NumberLong(2)
},
"acquireWaitCount" : {
"w" : NumberLong(1)
},
"timeAcquiringMicros" : {
"w" : NumberLong(12267482)
}
},
"Database" : {
"acquireCount" : {
"w" : NumberLong(1)
}
}
},
"waitingForFlowControl" : false,
"flowControlStats" : {
"acquireCount" : NumberLong(1)
}
}
......
]
}
- opid
这是操作的唯一标识符(identifier),可通过它来终止一个操作
- active
表示该操作是否正在运行。如这一字段的值是false,意味着此操作已交出或正等待其他操作交出锁。
- secs_running
表示该操作已经执行的时间。可通过它来判断是哪些查询耗时过长,或者占用了过多的数据库资源。
- op
表示操作的类型。通常是查询、插入、更新、删除中的一种。注意,数据库命令也被作为查询操作来处理。
- desc
该值可与日志(log)信息联系起来。日志中与此连接相关的每一条记录都会以[conn3]为前缀,因此可以此来筛选相关的日志信息。
- locks
描述该操作使用的锁的类型。其中“^”表示全局锁。
- waitingForLock
表示该操作是否因正在等待其他操作交出锁而处于阻塞状态。
- numYields
表示该操作交出锁(yield),而使其他操作得以运行的次数。通常,进行文档搜索的操作(查询、更新和删除)可交出锁。只有在其他操作列队等待该操作所持的锁时,它才会交出自己的锁。简单的讲,如果没有其他操作处于waitingForLock状态,则该操作不会交出锁。
- lockstats.timeAcquiringMicros
表示该操作需要多长时间才能取得所需的锁。
2、终止操作的执行
只要找到了想要终止的操作,就可将该操作的opid作为参数,通过执行db.killOp()来终止该操作的执行:
db.killOp(123)
并非所有的操作都能被终止。一般来讲,只有交出了锁的进程才能被终止,因此更新、查找、删除操作都可被终止。正在占用锁,或正在等待其他操作交出锁的操作则通常无法被终止。
3、使用系统分析器
可利用系统分析器(system profiler)来炒杂耗时过长的操作。系统分析器可记录特殊的集合system.profiler中的操作,并提供大量有关耗时过长的操作信息,但相应的,mongod的整体性能也会有所下降。因此,我们可能只需定期打开分析器来获取信息即可。默认情况下,系统分析器处于关闭状态。
开启分析器:
db.setProfilingLevel(1, 500)
//关于参数的解释
--- 2:
数据库收到的所有读写请求都将被记录到当前数据库的system.profile集合中。每一个数据库都启用了分析器,这也将带来大量的性能损失,
因为每一次写操作都会增加额外的写入时间,而每一次读操作都要等等写锁(因为它必须在system.profile集合写入记录)。
--- 1:
一般情况下,我们只想关注那些耗时过长的操作,而非数据库中正在进行的所有操作。为此,可将分析器的分析级别设为1,
即只显示长耗时的操作。级别为1的分析器会默认记录耗时大于100ms的操作。也可以自定义“耗时过长”的标准,把这个值作为
db.setprofilingLevel()函数的第二个参数。
--- 0:
将分析级别设为0可关闭分析器
db.setprofilingLevel(0)
{'was': 1, 'slowms': 500, 'ok': 1}
通常情况下,不要将slowms的值设得过小。即使分析器处于关闭状态,slowms也会对mongod有所影响,因为它决定了哪些操作将作为耗时过长操作被记录到日志中。因此,如果将slowms设置为2ms,那么哪怕分析器是关闭着的,每个耗时超过2ms的操作也都会出现在日志里。因此,如果出于某些需求降低了slowms的值,那么应在关闭分析器前将它重新调高。
//可以通过db.getProfilingLevel()来查看当前的分析级别
db.getProfilingLevel()
如果开启了分析器而system.profile集合并不存在,MongoDB会为其建立一个大小为若干MB的固定集合。如希望分析器运行更长时间,可能需要更大的空间来记录更多的操作。此时可关闭分析器,删除并重新建立一个新的名为system.profile的固定集合,并名其容量符合要求。然后在数据库上重新启用分析器。
4、计算空间消耗
如能得知文档、索引、集合、数据库各占用了多少空间,就可以方便地预留出合适的磁盘和内存空间。
文档
//在shell中对文档使用Object.bsonsize()函数
Object.bsonsize({_id: ObjectId()})
//也可以直接对集合中的文档进行查询
Object.bsonsize(db.user.find({"mobile" : "18933105536"}))
这一函数会精确地告诉文档在磁盘上占用的字节数目。然而这其中并未包含自动生成的空间间隔和索引,二者也时常是影响集合大小的重要因素。
集合
//stats函数可以用来显示一个集合的信息
db.user.stats()
{
"ns" : "model_10015.user",
"size" : 1570.0,
"count" : 4.0,
"avgObjSize" : 392.0,
"storageSize" : 36864.0,
"capped" : false,
"nindexes" : 2.0,
"indexBuilds" : [
],
"totalIndexSize" : 73728.0,
"indexSizes" : {
"_id_" : 36864.0,
"user_name_1_company_id_1" : 36864.0
},
"scaleFactor" : 1.0,
"ok" : 1.0
}
//随着集合的不断增长,stats()返回的巨大字节数目可能会变得不易识别。因此,可以传入比例因子
db.user.stats(1024*1024)
stats函数的返回结果中首先是命名空间(即model_10015.user),接下里的是集合中的文档的数目。在接下来的几个字段与集合的大小有关。size的值相当于对此集合中的所有元素执行Object.bsonsize(),再将这些结果相加得到的值,即集合中所有文档占有的字节数。将avgObjSize(平均对象大小)和count相乘,也能得到size的值。
storageSize不仅包含文档间的间隔和索引信息,还包含集合两端预留的未经使用空间。
nindexes是集合中索引的数量。索引直到建立完成后才会被算在nindexes中,也只有出现在此列表后才可以被使用。
数据库
//数据库stats函数与集合的类似
db.stats()
{
"db" : "model_10015",
"collections" : 78.0,
"views" : 0.0,
"objects" : 1068.0,
"avgObjSize" : 4728.656367041199,
"dataSize" : 5050205.0,
"storageSize" : 2912256.0,
"numExtents" : 0.0,
"indexes" : 127.0,
"indexSize" : 2371584.0,
"scaleFactor" : 1.0,
"fsUsedSize" : 26694139904.0,
"fsTotalSize" : 52709421056.0,
"ok" : 1.0
}
//与集合的stats()一样,可以传入比例因子
db.user.stats(1024*1024)
首先返回的是数据库名称和其中包含的集合数目。objects的值是数据库中所有集合包含的文档总数。
fsTotalSize应该总是最大的,即为数据库文件分配的总空间。该值应等于数据目录中所有名为“brains.*”的文件大小总和。
storageSize即为数据库正在使用的总空间大小。该值与fsTotalSize不符,因为fsTotalSize包含了预分配文件。
dataSize是此数据库中的数据鄋重用的空间大小。注意,改制并不包含空闲列表(free list)中的空间,但包含了文档间的间隔。因此改制与storageSize值的差异,应为被删除文档的大小。
5、使用mongotop和mongostat
MongoDB自带了几个命令行工具,可通过每隔几秒输出当前状态,帮助我们判断数据库正在做些什么。
mongotop类似于UNIX中的top工具,可概述哪些集合最为繁忙。可通过运行mongotop-locks,从而得知每个数据库的锁状态。
mongostat提供有关服务器的信息:
- insert / query / update / delete / getmore / command
每种对应操作的发生次数
- flushes
mongod将数据刷新(flush)到磁盘的次数
- mapped
mongod所映射的内存数量,通常约等于数据目录的大小
- vsize
mongod正在使用的虚拟内存大小,通常为数据目录的2倍大小(一次用于映射的文件,一次用于日记系统)
- res
mongod正在使用的内存大小,通常该值应尽量接近机器的所有内存大小
- locked db
在上一个时间片中,锁定时间最长的数据库。该百分比是根据数据库被锁定的时间和全局锁的锁定时间来计算的,这意味着该值可能超过100%。
- idx miss %
输出中最令人困惑的字段名。指有多少索引在访问中发生了缺页中断(page fault),即索引入口不在内存中,是的mongod必须到磁盘中进行读取。
- qr|qw
读写操作的队列大小,即有多少读写操作被阻塞,等待进行处理。
- ar|aw
指活动客户端的数量,即正在进行读写操作的客户端。
- netIn
通过网络传输进来的字节数,由MongoDB进行统计。
- netOut
通过网络传输出的字节数,由MongoDB进行统计。
本文暂时没有评论,来添加一个吧(●'◡'●)