Surveillance des performances MongoDB : commandes et métriques clés expliquées
Apprenez à surveiller de manière proactive les performances de votre MongoDB à l'aide de commandes essentielles dans le shell. Ce guide détaille comment suivre l'état des connexions via `db.currentOp()` et `db.serverStatus()`, analyser les requêtes lentes avec les commandes de profilage (`db.setProfilingLevel`), et interpréter les métriques cruciales liées à l'utilisation des ressources et à la santé des index pour un réglage optimal de la base de données.
Surveillance des performances MongoDB : commandes et métriques clés expliquées
Une gestion efficace des bases de données repose sur une surveillance robuste. Pour MongoDB, une base de données NoSQL leader, comprendre les métriques de performance est essentiel pour maintenir une haute disponibilité et une réactivité optimale. Les requêtes lentes, une consommation excessive de ressources ou des pics de connexion inattendus peuvent gravement impacter les performances des applications.
Lorsque MongoDB ralentit, la première question utile n'est pas « la base de données est-elle mauvaise ? » mais « que fait le serveur en ce moment, et est-ce différent de la normale ? ». Les commandes ci-dessous sont celles que j'utilise pour une première analyse avant de modifier les index, de redimensionner le matériel ou de blâmer l'application.
Commandes de surveillance essentielles dans le shell MongoDB (mongosh)
L'interface principale pour exécuter ces commandes est le shell MongoDB (mongosh), ou l'ancien shell mongo. Toutes les commandes présentées ici sont exécutées dans cet environnement shell.
1. Comprendre les connexions actuelles : db.currentOp() et db.serverStatus()
La surveillance des connexions actives est essentielle pour éviter l'épuisement des connexions et identifier les opérations de longue durée qui pourraient bloquer les ressources.
db.currentOp()
Cette commande renvoie des informations sur les opérations en cours d'exécution sur la base de données. Elle est indispensable pour identifier les requêtes lentes ou bloquantes en temps réel.
Exemple d'utilisation :
Pour voir toutes les opérations en cours d'exécution :
db.currentOp()
Pour rechercher spécifiquement les opérations qui s'exécutent depuis plus d'un certain seuil (par exemple, les opérations qui s'exécutent depuis plus de 5 secondes) :
db.currentOp({"secs_running": {$gt: 5}})
La sortie inclut des détails comme op, ns (espace de noms), query et secs_running.
db.serverStatus()
Bien que cette commande fournisse des informations d'état complètes, sa section connections est cruciale pour surveiller le pooling et les limites de connexion.
Métriques clés dans serverStatus (section Connexions) :
current: Le nombre de connexions actives au serveur.available: Le nombre de connexions disponibles pouvant être établies (en fonction du maximum configuré).
db.serverStatus().connections
2. Analyser les performances des requêtes : db.getProfilingStatus() et db.setProfilingLevel()
MongoDB fournit des outils de profilage intégrés qui enregistrent les détails d'exécution des opérations de base de données, permettant d'identifier les requêtes gourmandes en ressources.
Niveaux de profilage
Les niveaux de profilage déterminent quelles opérations sont enregistrées :
- 0 (Désactivé) : Aucune opération n'est profilée.
- 1 (Opérations lentes) : Seules les opérations plus lentes que le seuil configuré (
slowms) sont profilées. - 2 (Toutes les opérations) : Toutes les opérations sont profilées, ce qui génère une charge d'écriture importante et ne doit être utilisé que brièvement pour un dépannage ciblé.
Vérification de l'état
Pour voir le niveau de profilage actuel :
db.getProfilingStatus()
Définition du niveau (exemple)
Pour activer le profilage uniquement pour les opérations lentes (opérations dépassant 100 millisecondes) :
// Définir slowms à 100 millisecondes (la valeur par défaut est généralement 100)
db.setProfilingLevel(1, { slowms: 100 })
Astuce : Remettez toujours le profilage au niveau 0 après avoir recueilli les informations nécessaires pour éviter une dégradation des performances due à une journalisation excessive.
Affichage des requêtes lentes profilées
Les opérations profilées sont stockées dans la collection system.profile de la base de données spécifique surveillée. Pour afficher les 10 requêtes les plus lentes de la dernière heure :
db.system.profile.find().sort({millis: -1}).limit(10).pretty()
3. Métriques d'utilisation des ressources
Comprendre comment MongoDB utilise le CPU, la mémoire et les ressources d'E/S est essentiel pour les décisions de mise à l'échelle.
Utilisation de la mémoire et du stockage : db.serverStatus()
Les sections globalLock et storageEngine de serverStatus fournissent des informations approfondies sur la gestion des ressources.
Indicateurs de mémoire :
resident: Quantité de mémoire physique utilisée par le processus.virtual: Mémoire virtuelle totale allouée par le processus.
db.serverStatus().globalLock
Surveillance de la contention de verrouillage
MongoDB utilise des mécanismes de verrouillage internes. La surveillance de l'acquisition et des attentes de verrouillage permet d'identifier les goulots d'étranglement de concurrence.
Métriques clés dans globalLock :
currentQueue.readers: Nombre de lecteurs en attente d'un verrou.currentQueue.writers: Nombre de rédacteurs en attente d'un verrou.totalTime: Temps total passé à attendre des verrous pour toutes les opérations.
Des valeurs élevées dans currentQueue indiquent souvent que des index sont manquants ou que les opérations d'écriture sont excessivement longues, ce qui entraîne une mise en file d'attente des lecteurs/rédacteurs.
4. Utilisation et santé des index : db.collection.stats()
Des index mal utilisés ou manquants sont la cause la plus fréquente de dégradation des performances. La commande stats() aide à analyser l'efficacité des index.
Lorsqu'elle est exécutée sur une collection spécifique (par exemple, users) :
db.users.stats()
Métriques clés à vérifier :
totalIndexSize: L'espace disque total consommé par tous les index de cette collection.indexSizes: Une répartition de l'utilisation de l'espace par index.- Si un index est présent mais jamais utilisé pour les lectures, il s'agit d'une surcharge dont il faut envisager la suppression.
5. E/S disque et débit : db.serverStatus() (Réseau et opérations)
La surveillance de l'activité réseau et du taux d'opérations donne une vue du débit de la base de données.
Taux d'opérations (à partir de opcounters) :
opcounters suit le nombre total d'opérations exécutées depuis le dernier redémarrage du serveur, classées par type :
insert,query,update,delete,getmore,command.
En suivant les changements de ces compteurs au fil du temps (par exemple, en comparant deux appels consécutifs à serverStatus), vous pouvez calculer le débit opérationnel (opérations par seconde).
Exemple de comparaison :
- Exécutez
db.serverStatus().opcountersau temps T1. - Exécutez
db.serverStatus().opcountersau temps T2. - Soustrayez les valeurs T1 des valeurs T2 pour obtenir le total des opérations exécutées dans cet intervalle.
Bonnes pratiques pour une surveillance proactive
- L'automatisation est essentielle : Se fier uniquement aux commandes manuelles du shell est inefficace. Intégrez une surveillance à l'aide d'outils comme MongoDB Cloud Manager/Ops Manager ou de solutions de surveillance tierces qui interrogent automatiquement ces points de terminaison.
- Établissez des références : Exécutez les commandes lorsque le système est sain pour établir une référence de performance. Tout écart par rapport à cette référence justifie une enquête immédiate.
- Concentrez-vous sur la latence : Bien que les compteurs d'opérations soient utiles, privilégiez les métriques de latence (comme le temps rapporté par les journaux de profilage) par rapport au débit brut lors du diagnostic des problèmes d'expérience utilisateur.
- Vérifiez fréquemment les connexions : Dans les applications à fort trafic, les limites de connexion sont souvent atteintes en premier. Surveillez
db.serverStatus().connections.currentpar rapport au maximum configuré.
Une liste de contrôle pratique pour une première analyse
Quand quelqu'un dit « MongoDB est lent », évitez de sauter directement sur les modifications d'index. Commencez par une courte liste de contrôle et notez ce que vous voyez.
Vérifiez si le serveur est surchargé d'opérations actives :
db.currentOp({
active: true,
secs_running: { $gt: 2 }
});
Quelques opérations de longue durée peuvent être normales pour des tâches d'analyse. Un grand nombre d'écritures, de scans de collection ou d'opérations bloquées est différent. Recherchez l'espace de noms dans ns, le type d'opération dans op et la forme de la requête. Si de nombreuses opérations attendent derrière une mise à jour ou une construction d'index, la solution n'est pas la même qu'un index manquant sur une requête de lecture.
Ensuite, vérifiez les connexions :
db.serverStatus().connections;
current qui augmente rapidement peut signifier qu'un pool de connexions d'application a été mal configuré, qu'un déploiement a créé trop de workers, ou que les clients expirent et se reconnectent. available proche de zéro est un signal urgent car les nouveaux clients peuvent ne pas parvenir à se connecter. La bonne réponse pourrait être un réglage du pool dans l'application, et non une augmentation de la limite du serveur.
Ensuite, vérifiez les compteurs d'opérations deux fois, à un court intervalle :
const a = db.serverStatus().opcounters;
sleep(5000);
const b = db.serverStatus().opcounters;
printjson({
insertPer5s: b.insert - a.insert,
queryPer5s: b.query - a.query,
updatePer5s: b.update - a.update,
deletePer5s: b.delete - a.delete,
commandPer5s: b.command - a.command
});
Les compteurs depuis le démarrage sont utiles pour le contexte à long terme, mais les différences sur un intervalle connu vous disent ce qui se passe maintenant. Si le trafic de commandes est élevé mais que les requêtes sont faibles, vous avez peut-être affaire à des vérifications de métadonnées, du bruit de surveillance ou un comportement du pilote plutôt qu'à des lectures normales.
Utiliser explain() avant de blâmer le matériel
La collection de profilage peut vous dire quelles opérations sont lentes. explain() vous aide à comprendre pourquoi une requête est lente avant d'ajouter du CPU ou de la mémoire.
db.users.find({ email: "[email protected]" }).explain("executionStats");
Dans la sortie, comparez totalDocsExamined avec nReturned. Si MongoDB examine un grand nombre de documents pour renvoyer un seul utilisateur, la requête a probablement besoin d'un meilleur index ou d'un filtre différent. Si totalKeysExamined est élevé, un index existe mais n'est peut-être pas assez sélectif pour le modèle de requête.
Pour une requête composée, l'ordre des index est important :
db.orders.find({
accountId: "acct_123",
status: "open",
createdAt: { $gte: ISODate("2025-11-01T00:00:00Z") }
}).sort({ createdAt: -1 });
Un index utile pourrait être :
db.orders.createIndex({ accountId: 1, status: 1, createdAt: -1 });
Ce n'est pas une règle universelle. Le meilleur index dépend de la cardinalité, de l'ordre de tri et de l'ensemble complet des requêtes touchant la collection. Le but est de faire en sorte que la base de données vous montre le plan d'exécution au lieu de deviner.
Lire les données de profilage sans réagir de manière excessive
Le niveau de profilage 2 enregistre chaque opération et peut ajouter une surcharge sur les systèmes occupés. Utilisez-le uniquement pour une fenêtre courte et ciblée. Le niveau 1 avec un seuil slowms raisonnable est plus sûr pour trouver les opérations lentes.
db.setProfilingLevel(1, { slowms: 200 });
Après avoir collecté les données, inspectez les entrées les plus lentes :
db.system.profile.find(
{},
{
ns: 1,
op: 1,
millis: 1,
command: 1,
keysExamined: 1,
docsExamined: 1,
nreturned: 1
}
).sort({ millis: -1 }).limit(20).pretty();
Une requête lente ne signifie pas toujours un incident de production. Un rapport planifié, un cache froid après un redémarrage ou une tâche de maintenance rare peuvent apparaître en haut. Les modèles sont plus importants qu'un seul échantillon. Si la même forme de requête apparaît de manière répétée et examine beaucoup plus de documents qu'elle n'en renvoie, vous avez un véritable candidat à l'optimisation.
Surveiller les jeux de réplicas et la pression de stockage
Pour les jeux de réplicas, les performances ne concernent pas seulement le primaire. Un secondaire qui prend du retard peut affecter la confiance dans le basculement et les charges de travail en lecture si les clients utilisent des lectures secondaires.
rs.status();
Recherchez les membres qui ne sont pas sains, des changements d'état inattendus ou un retard de réplication qui ne se résorbe pas. Le retard acceptable exact dépend de l'application. Une charge de travail de type file d'attente peut tolérer un certain délai. Un tableau de bord qui promet des lectures quasi en temps réel peut ne pas le tolérer.
La pression de stockage nécessite le même contexte. db.serverStatus() peut montrer des métriques du moteur de stockage et de WiredTiger, mais les outils au niveau du disque comptent toujours. Si MongoDB attend sur des disques lents, les commandes shell à l'intérieur de la base de données montreront des symptômes plutôt que la cause racine. Corrélez avec les métriques de l'hôte telles que la latence du disque, l'utilisation du système de fichiers, le vol de CPU et la pression mémoire.
Transformer les vérifications manuelles en alertes
Les commandes manuelles sont les meilleures pendant l'investigation. Pour les opérations normales, convertissez les signaux utiles en vérifications automatisées : utilisation des connexions, santé de la réplication, taux de requêtes lentes, utilisation du disque, défauts de page ou pression du cache là où c'est disponible, et latence des opérations. Alertez sur un comportement mauvais soutenu, pas sur chaque pic d'une minute.
Les bonnes alertes incluent du contexte. « MongoDB slow queries high » est moins utile qu'une alerte qui inclut la base de données, la collection, la forme de la requête, le taux actuel et un lien vers des échantillons de profilage récents ou des panneaux de tableau de bord. Le but est de raccourcir les dix premières minutes de l'incident.
Ce qu'il ne faut pas faire pendant un ralentissement
Évitez de faire plusieurs changements à la fois. Ajouter un index, augmenter les limites de connexion, redémarrer l'application et modifier les tailles de pool dans le même incident peut effacer le symptôme, mais vous laisse sans savoir quelle action a aidé. Faites un changement, surveillez la métrique qui devrait s'améliorer et prenez des notes.
Soyez prudent avec killOp. Cela peut être utile lorsqu'une opération est clairement nuisible, mais tuer des opérations de longue durée au hasard peut aggraver le comportement de l'application. Si l'opération appartient à une migration, une sauvegarde, une construction d'index ou un travail de rapport, identifiez le propriétaire avant de l'arrêter, sauf si la base de données est déjà en sérieux problème.
Ne traitez pas serverStatus() comme un score de santé magique unique. C'est une collection de compteurs et d'instantanés. Une valeur élevée peut être normale sur un grand système occupé, et une valeur faible peut être mauvaise sur un petit système sensible à la latence. La question utile est de savoir si la valeur a changé d'une manière qui correspond au problème rencontré par l'utilisateur.
Séparez également les symptômes de la base de données des symptômes du déploiement. Une nouvelle version qui modifie la forme des requêtes, ouvre des pools de connexions plus grands ou démarre une migration en arrière-plan peut faire apparaître MongoDB comme la cause racine. Comparez le timing des opérations lentes avec les déploiements, les planifications de tâches, les sauvegardes et les changements de trafic avant de faire une correction uniquement sur la base de données.
La surveillance MongoDB fonctionne mieux lorsque vous comparez le comportement actuel à une référence connue. db.currentOp(), db.serverStatus(), le profilage, explain() et les vérifications des jeux de réplicas vous donnent suffisamment de preuves pour décider si le problème est une requête, un index, un comportement de connexion client, la réplication ou l'hôte sous la base de données.