MongoDB on Ubuntu: Performance Tuning Best Practices
Optimizing MongoDB performance on Ubuntu involves a combination of hardware provisioning, system configuration, MongoDB parameter tuning, and ongoing monitoring. Below are actionable steps categorized by key optimization areas:
noatime to the mount options (in /etc/fstab) to prevent unnecessary timestamp updates on file access. For XFS (recommended), ensure allocsize=16m is set to align with WiredTiger’s block size./etc/security/limits.conf (add * soft nofile 65536; * hard nofile 65536) and applying the changes./etc/mongod.conf, set storage.wiredTiger.engineConfig.cacheSizeGB to 50%-75% of available system memory (e.g., cacheSizeGB: 8 for a 16GB server). This controls how much RAM MongoDB uses for caching data and indexes.operationProfiling.mode: slowOp and operationProfiling.slowOpThresholdMs: 100 (adjust threshold as needed) to the config file. This logs queries taking longer than the specified threshold.net.maxIncomingConnections (e.g., to 10000) to handle high concurrency. Bind MongoDB to specific IPs using net.bindIp (e.g., 127.0.0.1,<server-ip>) to restrict access.storage.journal.enabled: true (default) for data durability. For write-heavy workloads, consider increasing journal.commitIntervalMs (e.g., to 100ms) to batch commits and improve write throughput.db.collection.createIndex({field: 1}) to index fields frequently used in queries (e.g., username, timestamp). Compound indexes (e.g., db.collection.createIndex({field1: 1, field2: -1})) can optimize queries with multiple filter conditions.db.collection.getIndexes() to list existing indexes and remove those not used by queries (identified via explain()). Each index increases write overhead and storage usage.db.collection.createIndex({name: 1, age: 1}) for find({name: "John"}, {name: 1, age: 1})). This allows MongoDB to retrieve data from the index alone, avoiding disk reads.explain("executionStats") on queries to check if they use indexes (look for “IXSCAN” in the execution plan) and identify slow stages (e.g., “COLLSCAN” for full table scans).db.users.find({age: {$gt: 18}}, {name: 1, age: 1, _id: 0})). This reduces network traffic and processing time.skip() and limit() (e.g., db.users.find().skip(20).limit(10)) instead of retrieving all documents at once.insertMany() or bulkWrite() to minimize network round-trips.replication.replSetName in mongod.conf) to distribute read operations across secondary nodes. This improves read throughput and provides high availability._id or a frequently queried field). Sharding distributes data and queries horizontally, enabling linear scalability.mongostat (tracks operations per second) and mongotop (shows read/write times by collection). These tools help identify bottlenecks in real-time.db.collection.reIndex() to reduce fragmentation. Clean up old data (e.g., logs, temporary collections) to free up disk space.security.authorization: enabled in mongod.conf) and creating users with least-privilege roles. This prevents unauthorized access and reduces the risk of malicious activity impacting performance.