如果你的应用使用的是MongoDB,那么你就有可能需要关注它的性能问题,一般访问数据的方式,硬件,数据库连接数会引起性能问题。
索引建立不合适,数据结构不合理也会限制性能,在后面会讲到这些如何影响数据库锁
也有可能已经到达数据库的最大性能,需要进行扩容,对硬件升级,比如需要合适大小的内存容量。这部分可以关注内存和MMAPv1 存储引擎
有时候性能问题可能只是暂时的,请求突然增加引起。这会在数据库连接数部分进行讨论,扩容可以解决这类问题。
数据库日志可以帮助我们找到哪些操作会引起性能问题。
锁性能
MongoDB是通过锁机制来保持数据的一致性。如果有耗时操作,或者很多请求,会导致一直等待锁。
如果要了解锁是否影响了性能,可以查看serverStatus输出的globalLock 部分
局部锁模式下的平均等待时间可以通过 locks.timeAcquiringMicros查看
locks.deadlockCount可以查看出现死锁的次数
如果globalLock.currentQueue.total数据比较高,那说明有很多请求等待锁,在并发模式下,会存在性能问题
如果globalLock.totalTime比较大,说明锁占用时间很长
不合理的查询,系统架构问题,RAM不足都会引起页错误,以及磁盘读写,这大大降低了性能
内存和MMAPv1存储引擎
MMAPv1存储引擎是通过内存映射的方式来存储数据。合理大小的数据,都会加载到内存中供系统使用。
但是这种方式让我们无法判断内存中是否是有效数据。
serverStatus输出里面有具体的内存使用情况
mem.resident字段表示需要使用的内存大小,如果超过了系统内存,说明有一部分数据在硬盘中,超过了系统承受能力
通过mem.mapped字段可以查看mongod使用的映射内存大小,如果这个值超过了系统内存大小,会出现页错误,表明有些数据是从硬盘读取。
页错误
如果是MMAPv1存储引擎, 请求的数据不在物理内存中会出现页错误。例如:物理内存不够用,需要把数据写入硬盘中。
MongoDB报告展示的是每秒钟的页错误。如果需要查看页错误,可以看serverStatus中的extra_info.page_faults字段
页错误次数不断增加说明系统的物理内存太小了。页错误出现也可能由于扫描整个表或者访问大量的数据。
偶尔出现少量页错误这个没什么问题。但是如果使用aggregate操作数据,出现大量页错误,说明MongoDB从硬盘中读取了大量数据。
在出现页错误后,会允许其它数据库进行读操作,同时加载下一页到内存中,这提高了并发能力,同时也提高了系统的容忍度。
增加内存可以降低页错误出现的概率。如果无法增加内存,可以考虑进行分片处理
连接数
有时候,应用和数据库的连接数超过服务可以处理的范围。可以通过查看serverStatus输出的数据来了解。
globalLock.activeClients 表示有多少个活动的客户端连接数
connections包含以下两个字段:
connections.current 表示当前有多少个客户端连接者数据库
connections.available 表示还有多少个可以使用的连接数
如果有大量的并发,需要提升系统的最大连接数。
对于读需求比较高的情况,可以增加复制的数据库数量,通过复制集读取数据。
对于写需要比较高的情况,可以通过增加分片数来提高写的并发能力。
大量的连接数会导致错误。官方发布的MongoDB驱动都支持连接池,连接池支持连接的重复利用。如果出现大量连接数,并且部分无相应,那可能说明你的配置错误或者数据库驱动不对。
MongoDB对连接数是没有限制的,除非系统限制。基于Unix的系统,可以通过ulimit指令或者修改/etc/sysctl来改变连接数
Database Profiling
MongoDB的Profiler可以帮助我们分析出系统中存在的性能问题。
profiler提供以下几种级别设置:
级别 设置
0 关闭. 没有输出
1 打开. 打印比较慢的操作
2 打开. 打印所有操作
可以在mongo shell中通过以下指令来打开或者设置profiler:
db.setProfilingLevel(1)
slowOpThresholdMs 设置定义了多长时间为慢操作。slowOpThresholdMs 可以动态调整,立即生效
系统默认设置是此级别
注意:
profiler会影响系统的性能,线上环境设置的值越小越好。