MongoDB采用内存映射存储引擎(默认为WiredTiger),将磁盘IO操作转换为内存操作。读操作时,内存中的数据作为缓存提升读取速度;写操作时,内存将随机写转换为顺序写,显著提升性能。需注意的是,MongoDB会将可用内存交由操作系统虚拟内存管理器处理,会占用几乎所有可用内存,因此不建议与其他内存密集型服务共用服务器。
WiredTiger是MongoDB的默认存储引擎(MongoDB 3.2+),其缓存大小通过storage.wiredTiger.engineConfig.cacheSizeGB参数配置。建议设置为服务器物理内存的50%-70%,但需预留1GB以上给系统和其他应用(如32GB内存服务器可设置为16-22GB)。
/etc/mongod.conf):storage:
wiredTiger:
engineConfig:
cacheSizeGB: 4 # 设置为4GB
mongod --wiredTigerCacheSizeGB=4
通过processManagement.memoryLimitMB参数限制MongoDB进程的最大内存使用(单位:MB),避免单个进程占用过多内存导致系统崩溃。修改配置文件后需重启服务生效:
processManagement:
fork: true
pidFilePath: /var/run/mongodb/mongod.pid
memoryLimitMB: 4096 # 限制为4GB
执行sudo systemctl restart mongod使配置生效。
vm.swappiness参数vm.swappiness控制系统使用交换空间(Swap)的倾向,取值范围为0-100(0表示尽量避免使用Swap,100表示积极使用)。MongoDB为内存密集型应用,建议设置为10或更低,减少Swap使用以提升性能:
# 临时生效
echo 10 | sudo tee /proc/sys/vm/swappiness
# 持久化设置(添加到/etc/sysctl.conf)
echo "vm.swappiness = 10" | sudo tee -a /etc/sysctl.conf
# 生效配置
sudo sysctl -p
overcommit_memory参数vm.overcommit_memory控制内核是否允许内存超额分配,取值:0(默认,启发式分配)、1(允许超额分配)、2(严格限制,不允许超额)。建议设置为1,避免MongoDB因内存分配失败而崩溃:
# 临时生效
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
# 持久化设置(添加到/etc/sysctl.conf)
echo "vm.overcommit_memory = 1" | sudo tee -a /etc/sysctl.conf
# 生效配置
sudo sysctl -p
虽然降低Swap使用有助于提升性能,但完全关闭Swap(swapoff -a)可能导致内存不足时系统崩溃。建议保留少量Swap(如服务器内存的1-2倍),作为内存溢出的缓冲。
db.serverStatus().mem:查看MongoDB内存使用详情,包括当前使用量(resident,单位MB)、最大限制(virtual,单位MB)、映射文件大小(mapped,单位MB)等:use admin
db.serverStatus().mem
mongostat:实时监控内存使用、磁盘IO、查询响应时间等指标,每秒刷新一次:mongostat --host localhost --port 27017
mongotop:按集合统计读写时间,定位慢查询或高内存占用的集合:mongotop --host localhost --port 27017
free -m:查看系统内存使用情况(包括free、used、buffers、cached等):free -m
sar -r:监控内存使用趋势(每秒刷新一次):sar -r 1
vmstat 1:查看内存、Swap、IO等系统级指标:vmstat 1
sudo systemctl restart mongod
closeAllDatabases命令关闭所有数据库,释放内存:use admin
db.runCommand({closeAllDatabases:1})
drop_caches释放系统缓存(不影响MongoDB运行):sudo sysctl -w vm.drop_caches=1
_id、name)创建索引,减少全表扫描,降低内存占用:db.collection.createIndex({field: 1})
limit()减少查询返回的文档数量,通过投影操作符(如{field: 1, _id: 0})明确需要的字段,降低内存消耗:db.collection.find({}).limit(10).project({field: 1, _id: 0})
user.address)代替引用(如user_id),减少关联查询的内存开销;db.collection.dropIndex("index_name"))、过期数据(db.collection.remove({expire_field: {$lt: new Date()}})),优化数据库性能;