Skip to main content

Performance Monitoring and Troubleshooting

In this final lesson, we'll explore how to monitor MongoDB performance and troubleshoot common issues. You'll learn to identify performance bottlenecks, use built-in monitoring tools, and apply practical debugging techniques.

By the end of this lesson, you'll be able to:

  • Use MongoDB's built-in monitoring tools and commands
  • Analyze query performance with explain plans
  • Identify and resolve common performance issues
  • Monitor database health and set up alerts

MongoDB Monitoring Tools

Database Commands

MongoDB provides several built-in commands for real-time monitoring:

serverStatus.js
// Get comprehensive server status
db.serverStatus()

// Get collection statistics
db.stats()

// Get operation counters
db.serverStatus().opcounters

// Check current operations
db.currentOp()
tip

Run db.serverStatus() regularly to establish performance baselines. Compare metrics over time to identify trends and potential issues before they become critical.

MongoDB Atlas Monitoring

If you're using MongoDB Atlas, the cloud platform provides extensive monitoring dashboards:

atlas-monitoring.js
// While Atlas provides GUI monitoring, you can also access metrics via API
// This example shows the type of metrics available:
{
"opsCounters": {
"insert": 1500,
"query": 4200,
"update": 800,
"delete": 50
},
"memory": {
"resident": 256,
"virtual": 512,
"mapped": 128
},
"network": {
"bytesIn": 10485760,
"bytesOut": 5242880
}
}

Query Performance Analysis

Explain Plans

The explain() method helps you understand how MongoDB executes queries:

explain-query.js
// Analyze a query execution plan
db.users.find(
{ age: { $gte: 25 }, city: "New York" }
).explain("executionStats")

// Check with specific index
db.users.find(
{ email: "user@example.com" }
).hint({ email: 1 }).explain()

Identifying Slow Queries

MongoDB can log slow operations for analysis:

slow-query-log.js
// Set slow query threshold (in milliseconds)
db.setProfilingLevel(1, { slowms: 100 })

// Check current profiling level
db.getProfilingStatus()

// View slow queries
db.system.profile.find().sort({ ts: -1 }).limit(10)
warning

Be cautious when enabling profiling in production. It can impact performance and consume significant disk space. Use it temporarily for troubleshooting specific issues.

Performance Optimization Techniques

Index Usage Analysis

Check if your queries are properly using indexes:

index-analysis.js
// Check index usage statistics
db.users.aggregate([{ $indexStats: {} }])

// Force collection scan to compare performance
db.users.find({ name: "John" }).hint({ $natural: 1 })

// Check if index is being used
db.users.find({ email: "test@example.com" }).explain()

Connection Pool Monitoring

Monitor and optimize connection usage:

connection-monitoring.js
// Check current connections
db.serverStatus().connections

// Typical healthy connection metrics
{
"current": 45,
"available": 255,
"totalCreated": 1200
}

Real-time Monitoring Setup

monitor.js
const { MongoClient } = require('mongodb');

class DatabaseMonitor {
constructor(uri) {
this.client = new MongoClient(uri);
this.metrics = [];
}

async collectMetrics() {
const db = this.client.db();
const status = await db.command({ serverStatus: 1 });

this.metrics.push({
timestamp: new Date(),
operations: status.opcounters,
memory: status.mem,
connections: status.connections
});

// Keep only last 100 metrics
if (this.metrics.length > 100) {
this.metrics.shift();
}
}

async checkHealth() {
try {
await this.client.db().command({ ping: 1 });
return { status: 'healthy', responseTime: Date.now() };
} catch (error) {
return { status: 'unhealthy', error: error.message };
}
}
}

Common Performance Issues

Memory Pressure

memory-check.js
// Check memory usage
const mem = db.serverStatus().mem;
console.log(`Resident memory: ${mem.resident}MB`);
console.log(`Virtual memory: ${mem.virtual}MB`);

// If resident memory is consistently high and virtual memory is growing,
// you may need to optimize queries or add more RAM

Lock Contention

lock-monitoring.js
// Check global lock percentage
const locks = db.serverStatus().globalLock;
console.log(`Lock percentage: ${locks.lockTime / locks.totalTime * 100}%`);

// High lock percentage indicates contention - consider:
// 1. Adding more indexes
// 2. Optimizing write operations
// 3. Sharding for write scalability

Common Pitfalls

  • Ignoring explain() results: Always analyze query execution plans before deploying to production
  • Over-indexing: Too many indexes can slow down write operations and consume memory
  • Missing connection pooling: Creating new connections for each operation causes significant overhead
  • Not monitoring memory usage: MongoDB performance degrades quickly when working sets don't fit in RAM
  • Ignoring slow query logs: Regularly review and optimize slow operations before they impact users
  • Poor document design: Large documents or excessive nesting can impact read/write performance

Summary

Performance monitoring is an ongoing process that requires regular attention. Use MongoDB's built-in tools like explain(), serverStatus(), and profiling to identify bottlenecks. Establish performance baselines, monitor key metrics, and optimize queries and indexes based on actual usage patterns. Remember that prevention is better than cure - proactive monitoring helps catch issues before they affect your users.

Show quiz
  1. What command provides comprehensive server statistics including operations counters and memory usage?

    • A) db.stats()
    • B) db.serverStatus()
    • C) db.healthCheck()
    • D) db.metrics()
  2. Which explain() verbosity level provides the most detailed execution statistics?

    • A) "queryPlanner"
    • B) "executionStats"
    • C) "allPlansExecution"
    • D) "verbose"
  3. What is a potential risk of setting the profiling level too low in production?

    • A) It might impact performance and consume disk space
    • B) It will automatically create indexes
    • C) It disables authentication
    • D) It clears existing indexes
  4. How can you force a query to use a specific index?

    • A) .useIndex()
    • B) .forceIndex()
    • C) .hint()
    • D) .index()
  5. What does high lock percentage in globalLock statistics typically indicate?

    • A) Too many read operations
    • B) Insufficient disk space
    • C) Write contention
    • D) Network latency

Answers:

  1. B) db.serverStatus()
  2. B) "executionStats"
  3. A) It might impact performance and consume disk space
  4. C) .hint()
  5. C) Write contention