CentOS環境下MongoDB性能瓶頸破解方法
/etc/sysctl.conf
添加vm.nr_hugepages=0
,并執行sudo sysctl -p
生效;同時修改/etc/rc.local
確保開機自動禁用。vm.swappiness
設置為0(默認60),減少系統使用swap分區的概率,避免內存不足時頻繁換頁導致的性能下降。noop
或deadline
調度算法(編輯/etc/default/grub
,修改GRUB_CMDLINE_LINUX
參數,如GRUB_CMDLINE_LINUX="quiet elevator=noop"
,然后更新grub并重啟)。WiredTiger是MongoDB的默認存儲引擎(MongoDB 3.2+),其緩存大小直接影響性能。編輯/etc/mongod.conf
,設置storage.wiredTiger.engineConfig.cacheSizeGB
為物理內存的50%-80%(如16GB內存可設置為8GB),避免緩存過大占用過多內存導致系統或其他應用內存不足。
storage.journal.commitIntervalMs
(默認100ms)控制journal日志的刷新頻率,降低該值可提高數據持久性但增加I/O負載;提高該值則相反,需根據數據安全性需求權衡(如測試環境可設置為500ms,生產環境建議保持默認)。/etc/mongod.conf
,設置systemLog.logRotate: rename
,并配合logrotate
工具定期切割日志,避免日志文件過大占用磁盤空間。find
、sort
、update
的字段創建索引(如db.collection.createIndex({username: 1})
)。db.collection.createIndex({status: 1, createTime: -1})
,適用于status=1
且按createTime
降序查詢的場景)。db.collection.createIndex({name: 1, age: 1})
,查詢{name: "張三", age: {$gt: 18}}
時可使用覆蓋索引)。db.collection.getIndexes()
查看現有索引,刪除不再使用的索引(如db.collection.dropIndex({old_field: 1})
),減少索引維護開銷。db.collection.reIndex()
重建索引(注意:重建期間會鎖表,建議在低峰期操作)。db.collection.aggregate([{ $indexStats: {} }])
查看索引使用頻率,刪除長期未使用的索引(如usageCount
為0的索引)。db.collection.find({username: "張三"}, {name: 1, age: 1, _id: 0})
)。explain("executionStats")
查看執行計劃,確認winningPlan
中使用了索引)。$or
:$or
查詢可能導致索引失效,盡量改用$in
(如db.collection.find({$or: [{status: 1}, {status: 2}]})
可改為db.collection.find({status: {$in: [1, 2]}})
)。skip()
+limit()
的大偏移量分頁(如skip(10000).limit(10)
)會導致性能下降,建議使用“游標分頁”(記錄上一頁的最后一條記錄的_id
,下次查詢find({_id: {$gt: last_id}}, {limit: 10})
)。通過副本集實現讀寫分離,在連接字符串中設置readPreference="secondaryPreferred"
,將讀請求分發到從節點,減輕主節點的壓力(注意:從節點數據可能有延遲,不適合實時性要求高的場景)。
對于海量數據(如TB級),使用分片將數據分散到多個服務器。選擇合適的分片鍵(如user_id
、order_id
等高基數字段),避免數據傾斜(如避免使用status
等低基數字段作為分片鍵),提高查詢和寫入的橫向擴展能力。
mongostat
(查看每秒操作數、延遲等)、mongotop
(查看集合級別的讀寫時間)定期監控數據庫性能。operationProfiling.slowOpThresholdMs
設置為100ms),定期分析慢查詢日志,針對性優化查詢語句或索引。