在解決MongoDB性能問題前,需先通過監控工具和日志分析定位瓶頸根源:
mongostat查看讀寫操作、內存使用、連接數等實時指標;mongotop分析集合級別的讀寫時間分布,快速定位慢操作集合。db.setProfilingLevel(1, {slowms: 100})開啟慢查詢記錄(閾值設為100ms),用db.profile()查看慢查詢詳情,識別未走索引或執行效率低的查詢。top監控CPU使用率(若CPU占用過高,可能是查詢復雜或索引缺失);iostat -x 1查看磁盤IO(若await或%util過高,說明磁盤成為瓶頸);free -h檢查內存使用(若available內存不足,可能導致頻繁換頁)。瓶頸表現:CPU占用持續高位(>80%)、內存不足(available內存<總內存的20%)、磁盤IO延遲高(await>50ms)。
解決措施:
storage.wiredTiger.engineConfig.cacheSizeGB設置為物理內存的70%-80%)。deadline,HDD設為noop),減少IO等待;禁用atime(noatime,nodiratime)降低元數據寫入開銷。瓶頸表現:查詢執行時間長(如find、aggregate操作慢)、explain()結果顯示“COLLSCAN”(全表掃描)。
解決措施:
find、sort、aggregate中頻繁使用的字段創建索引(如db.collection.createIndex({user_id: 1, create_time: -1}));復合索引需將選擇性高的字段(如user_id)放在前面,減少索引大小。db.collection.getIndexes()審查索引,刪除未使用的索引(通過$indexStats查看accesses.ops為0的索引)。db.collection.find({status: "active"}, {name: 1, age: 1}),若索引包含status、name、age,則無需訪問文檔)。瓶頸表現:查詢返回大量不必要的數據、復雜查詢(如多層嵌套$lookup)執行慢。
解決措施:
find({}, {name: 1, age: 1, _id: 0})僅返回需要的字段,減少網絡傳輸和內存占用。$ne、$not)、正則表達式(如/^abc/,除非是前綴匹配),這類條件無法有效利用索引。find再group),減少數據往返次數;合理使用$match(盡早過濾數據)、$project(減少字段)優化管道性能。bulkWrite替代單條插入/更新(如批量插入1000條數據),減少網絡通信次數。瓶頸表現:文檔過大(超過16MB)、頻繁的$lookup操作、過度規范化(導致大量JOIN)。
解決措施:
$lookup操作(關聯查詢性能較低)。瓶頸表現:緩存命中率低(WiredTiger緩存未充分利用)、連接數過多導致資源耗盡。
解決措施:
mongod.conf中設置storage.wiredTiger.engineConfig.cacheSizeGB為物理內存的70%-80%(如128GB內存設為80GB),確保常用數據緩存在內存中。net.maxIncomingConnections(默認10000)和net.maxOutgoingConnections(默認10000),根據應用需求增加連接數;同時用ulimit -n 64000提高系統文件描述符限制,避免連接過多導致“Too many open files”錯誤。operationProfiling.mode: "slowOp"(慢查詢模式)或"all"(全量模式),監控慢操作并針對性優化。瓶頸表現:單節點數據量過大(超過TB級)、數據分布不均(分片鍵選擇不當)、副本集同步延遲。
解決措施:
user_id)、查詢頻繁的字段作為分片鍵,避免數據傾斜(如避免用status作為分片鍵,因大部分文檔狀態相同)。user_id哈希分片),提高橫向擴展能力;分片后需監控各分片的負載(如sh.status()查看數據分布)。oplog大?。?code>replication.oplogSizeMB),避免oplog過小導致同步延遲。db.reIndex()重建索引(優化索引碎片);每月備份數據(使用mongodump+異地存儲),確保數據安全。