E-NO
Performances MongoDB 7 min de lecture

Optimisation des performances de MongoDB avec des exemples pratiques : un guide de mise en œuvre étape par étape

calendar_today Publié : 2026-10-03
update Dernière mise à jour : 2026-10-03
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Optimisation des performances de MongoDB avec des exemples pratiques : un guide de mise en œuvre étape par étape ».

Introduction

L'optimisation des performances de MongoDB commence souvent par une plainte vague : les requêtes sont lentes, la base de données est à la traîne ou le processeur présente des pics à des heures inhabituelles. Ce guide transforme cette plainte en un flux de travail de diagnostic reproductible. Vous apprendrez à inventorier votre environnement, à profiler les requêtes lentes, à concevoir de meilleurs index, à ajuster les paramètres du serveur MongoDB en toute sécurité et à construire une pile de surveillance qui détecte les régressions avant que les utilisateurs ne les remarquent.

Nous nous concentrons sur des commandes pratiques, adaptées à la version, et des exemples réalistes. Chaque étape comprend la commande, le résultat attendu et un plan de retour en arrière. Ce n'est pas un aperçu théorique ; c'est un manuel de terrain pour les développeurs, les ingénieurs DevOps et les équipes techniques de startups qui exécutent MongoDB en production.

Inventaire de la version et de l'environnement

Avant de toucher à un paramètre, sachez exactement ce que vous exécutez. Cette étape d'inventaire évite les incompatibilités de version et les topologies qui se comportent différemment que prévu.

Prérequis

  • Accès au shell MongoDB (mongosh) ou à une connexion de pilote.
  • Autorisations de lecture sur la base de données et sur la base de données admin pour l'état du serveur.
  • Un terminal avec accès réseau à tous les nœuds mongod/mongos.

Observer avant de changer Exécutez les commandes en lecture seule suivantes et capturez la sortie :

// Connectez-vous à votre déploiement (remplacez les espaces réservés)
mongosh "mongodb://<user>:<password>@<host>:<port>/admin"

// Version du serveur et informations de build
db.version()
// Sortie attendue (exemple) : '7.0.14'

// Topologie du déploiement : autonome, ensemble de réplicas ou cluster fragmenté
db.hello()
// Recherchez les champs 'isWritablePrimary', 'setName', 'hosts'.

// Vérifier les connexions actuelles et le nombre d'opérations
db.serverStatus().connections
// Exemple de sortie : { "current" : 12, "available" : 51188, "totalCreated" : 3421 }

db.serverStatus().opcounters
// Exemple de sortie : { "insert" : 10, "query" : 2500, "update" : 300, "delete" : 45, ... }

Signal attendu vs échec

  • Si db.hello() affiche isWritablePrimary: true, le nœud agit comme primaire. Dans un ensemble de réplicas, confirmez que les autres membres sont dans l'état SECONDARY via db.hello() sur chacun.
  • Si connections.current est proche ou égal à connections.available, vous manquez de capacité de connexion, ce qui entraîne des connexions refusées.
  • Si opcounters.query est considérablement plus élevé que les autres opérations sur la même période, une optimisation de la charge de travail à forte lecture est justifiée.

Rayon d'impact et récupération Cette étape est en lecture seule, donc aucune récupération n'est nécessaire. Cependant, assurez-vous d'être connecté au bon nœud. Si vous vous connectez accidentellement à un primaire de production et exécutez un serverStatus() lourd de manière répétée, vous ajoutez une charge mineure. Utilisez une préférence de lecture secondaryPreferred pour l'observation lorsque c'est possible.

Chemin de configuration sûr

Après l'inventaire, ajustez la configuration un paramètre à la fois. Cela réduit les risques et clarifie l'attribution des effets.

Prérequis

  • Vous avez identifié un symptôme de performance spécifique (par exemple, latence d'écriture élevée, requêtes lentes).
  • Vous disposez d'une mesure de base à partir de votre outil de surveillance ou mongostat.
  • Vous savez comment revenir rapidement en arrière sur le paramètre.

Exemple : Activer le profileur pour les requêtes lentes Le profileur de base de données collecte des informations sur les opérations qui dépassent un seuil de temps. Dans MongoDB 5.0+, utilisez db.setProfilingLevel().

// Lister le niveau de profilage actuel
db.getProfilingStatus()
// Sortie attendue : { "was" : 0, "slowms" : 100, "sampleRate" : 1.0 }

// Définir le niveau de profilage 1 (journaliser les opérations lentes) avec un seuil de 50 ms
db.setProfilingLevel(1, { slowms: 50 })
// Sortie attendue : { "was" : 0, "slowms" : 100, "sampleRate" : 1.0, "ok" : 1 }

Vérification Après quelques minutes ou après avoir reproduit l'opération lente, interrogez la collection system.profile sur la base de données :

// Trouver les requêtes lentes de la dernière heure (triées par durée décroissante)
db.system.profile.find({ ts: { $gt: new Date(Date.now() - 3600*1000) } }).sort({ millis: -1 }).limit(5).pretty()

La sortie attendue inclut le prédicat de la requête, le résumé du plan et le champ millis.

Récupération Si le profilage ajoute un surcoût inacceptable (généralement minime), désactivez-le :

db.setProfilingLevel(0)

Vérification et diagnostics

Vous devez maintenant diagnostiquer les problèmes de performance réels à l'aide d'outils en lecture seule. Cette section couvre les commandes de diagnostic essentielles et comment les interpréter.

1. Identifier les requêtes lentes

Si le profilage est activé, system.profile est le premier arrêt. Sinon, exécutez currentOp() pour voir ce qui se passe en ce moment :

// Trouver les opérations actives en cours depuis plus de 100 ms
db.adminCommand({ currentOp: 1, active: true, secs_running: { $gt: 0.1 } })

Recherchez le champ op (query, insert, update, etc.), le ns (espace de noms) et secs_running. Une opération query qui s'exécute longtemps signale souvent un index manquant ou un mauvais plan.

2. Expliquer une requête

Utilisez explain() pour voir comment MongoDB exécute une requête. Exemple pour une requête sur la collection orders :

db.orders.find({ customer_id: 12345, status: "shipped" }).explain("executionStats")

Champs clés :

  • executionStats.executionTimeMillis : temps total en ms.
  • executionStats.totalDocsExamined vs executionStats.nReturned : si totalDocsExamined est beaucoup plus grand que nReturned, la requête analyse trop de documents.
  • queryPlanner.winningPlan.stage : des étapes comme COLLSCAN signifient une analyse complète de la collection ; IXSCAN signifie qu'un index a été utilisé.

Conclusion diagnostique Si vous voyez COLLSCAN et totalDocsExamined égal à la taille de la collection mais nReturned petit, vous avez besoin d'un index.

3. Vérifier l'utilisation des index

db.orders.getIndexes()

Cela liste les index existants. Pour les diagnostics de performance, vérifiez également serverStatus().metrics.queryExecutor pour les compteurs d'analyse d'index vs d'analyse de collection.

4. Ensemble de travail et cache

db.serverStatus().wiredTiger.cache

Métriques importantes :

  • bytes currently in the cache : doit être proche de la taille de cache configurée sous charge stable.
  • Des pics de pages read into cache indiquent des échecs de cache et des E/S disque.

Si les échecs de cache sont élevés, envisagez d'augmenter wiredTiger.engineConfig.cacheSizeGB (voir le réglage des paramètres ci-dessous).

Réglage des index et des requêtes

C'est le domaine le plus impactant pour l'optimisation des performances. Une mauvaise indexation est la cause numéro un des requêtes lentes dans MongoDB.

Créer le bon index

Étant donné la requête orders précédente, créez un index composé :

// Index sur customer_id croissant, status décroissant
db.orders.createIndex({ customer_id: 1, status: -1 }, { name: "idx_customer_status" })

Vérification Réexécutez explain("executionStats") sur la requête. Attendu : winningPlan.stage devient IXSCAN, totalDocsExamined chute considérablement et executionTimeMillis diminue.

Sélectivité et ordre des index

L'ordre compte dans les index composés. Pour les requêtes qui filtrent sur customer_id et status, le champ le plus fréquemment utilisé seul ou ayant une forte sélectivité doit venir en premier. Utilisez db.orders.aggregate([{ $match: { customer_id: 12345, status: "shipped" } }, { $group: { _id: "$status", count: { $sum: 1 } } }]) pour évaluer la sélectivité.

Éviter les erreurs courantes d'indexation

  • Sur-indexation : chaque index ajoute une surcharge d'écriture et consomme de la RAM. Ne créez que des index qui soutiennent les modèles de requêtes réels.
  • Indexer des champs à faible cardinalité : indexer status seul (avec peu de valeurs distinctes) entraîne souvent une faible sélectivité et peut ne pas être utilisé.
  • Ignorer les étapes de tri : si une requête trie par created_at, incluez ce champ dans l'index dans le bon ordre de tri pour éviter le tri en mémoire.

Surveiller l'utilisation des index Utilisez $indexStats pour voir la fréquence d'utilisation de chaque index :

db.orders.aggregate([{ $indexStats: {} }])

Recherchez les index avec accesses.ops à 0 ; ce sont des candidats à la suppression (mais confirmez qu'il n'y a pas d'utilisation cachée).

Réglage des paramètres du serveur

Au-delà des index, la configuration du serveur MongoDB peut être ajustée. Changez toujours un paramètre à la fois et surveillez.

Taille du cache WiredTiger

Pour les serveurs MongoDB dédiés, la taille de cache par défaut est de 50 % de (RAM - 1 Go). Cela peut être augmenté sur les systèmes riches en mémoire. Vous pouvez la définir dans le fichier de configuration :

storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 4

Sur un serveur en cours d'exécution, utilisez db.adminCommand({ setParameter: 1, wiredTigerEngineRuntimeConfig: "cache_size=4GB" }) mais cela ne persiste pas après un redémarrage. Persistez via le fichier de configuration ou le paramètre de démarrage.

Vérification Vérifiez l'utilisation du cache au fil du temps avec db.serverStatus().wiredTiger.cache. Recherchez une diminution de pages read into cache et une augmentation de bytes currently in the cache jusqu'à la nouvelle limite.

Récupération Si vous observez une augmentation du swapping ou des problèmes de mémoire insuffisante, revenez à la valeur de cache précédente.

Taille de l'oplog (ensembles de réplicas)

L'oplog doit être suffisamment grand pour contenir les opérations entre les cycles de synchronisation des secondaires. Si les secondaires prennent du retard, ils peuvent entrer dans l'état RECOVERING. Vérifiez la taille actuelle de l'oplog :

db.printReplicationInfo()
// Exemple de sortie : configured oplog size: 990MB; log length start to end: 2.5hrs

Si la log length est inférieure à votre fenêtre de maintenance, envisagez un redimensionnement. Changer la taille de l'oplog nécessite un redémarrage roulant avec le paramètre --oplogSize ou replSetResizeOplog (MongoDB 4.4+).

Limites du pool de connexions

Les pilotes gèrent généralement les pools de connexions. Assurez-vous que le maxIncomingConnections du serveur est suffisamment élevé :

db.adminCommand({ getParameter: 1, maxIncomingConnections: 1 })

La valeur par défaut est 65536, mais vous devrez peut-être la réduire ou l'augmenter en fonction du matériel. Dans le fichier de configuration :

net:
  maxIncomingConnections: 10000

Surveillance et alertes

La surveillance proactive détecte tôt les régressions de performance. Mettez en place des métriques au niveau de la base de données et au niveau de l'hôte.

Utilisation de mongostat et mongotop

mongostat fournit une vue en temps réel rapide :

mongostat --host <host> --username <user> --password <password> --authenticationDatabase admin

Exemple de colonnes de sortie : insert, query, update, delete, vsize, res, netIn, netOut, conn, time. Surveillez les taux élevés de query ou update et un conn élevé (connexions).

mongotop affiche l'activité de lecture/écriture par collection :

mongotop --host <host> --username <user> --password <password> --authenticationDatabase admin

Cela aide à identifier les collections chaudes.

Intégration avec Prometheus et Grafana

Utilisez l'exportateur mongodb_exporter (Percona ou Bitnami) pour collecter les métriques. Métriques clés sur lesquelles alerter :

  • mongodb_op_counters_total pour les taux d'opérations.
  • mongodb_mongod_connections pour le nombre de connexions.
  • mongodb_mongod_oplog_stats_size pour l'utilisation de l'oplog.
  • mongodb_mongod_wiredtiger_cache_bytes pour l'utilisation du cache.

Exemple de règle d'alerte Prometheus :

groups:
- name: mongodb_alerts
  rules:
  - alert: MongoDBHighConnections
    expr: mongodb_mongod_connections > 5000
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "Connexions élevées sur {{ $labels.instance }}"
  - alert: MongoDBCacheMissRate
    expr: rate(mongodb_mongod_wiredtiger_cache_pages_read_into_cache[5m]) / rate(mongodb_mongod_wiredtiger_cache_pages_requested[5m]) > 0.05
    for: 15m
    labels:
      severity: critical
    annotations:
      summary: "Taux élevé d'échecs de cache sur {{ $labels.instance }}"

Configurez des alertes pour le nombre de requêtes lentes via le profilage : vous pouvez exporter system.profile sous forme de journaux ou utiliser un expéditeur de journaux.

Pièges courants et comment les éviter

Même les ingénieurs expérimentés tombent dans ces pièges. Voici comment les éviter ou s'en remettre.

Piège 1 : Ajouter des index sans vérification

Pourquoi cela arrive : Un développeur voit une requête lente et ajoute aveuglément un index suggéré par un outil ou un article de blog. L'index peut ne pas correspondre au modèle de requête, ou il peut causer une amplification d'écriture.

Comment éviter : Exécutez toujours explain() avant et après. Utilisez la méthode hint() pour forcer l'utilisation de l'index lors des tests et comparer les performances. Vérifiez $indexStats après quelques jours pour voir si l'index est réellement utilisé.

Récupération : Si un index est inutilisé ou nuisible, supprimez-le avec db.collection.dropIndex("index_name"). Mais d'abord, confirmez qu'aucun code d'application ne l'attend ou ne l'utilise sporadiquement.

Piège 2 : Ignorer la contention d'écriture

Pourquoi cela arrive : Les lectures sont optimisées, mais les écritures deviennent lentes en raison d'un trop grand nombre d'index ou de verrous au niveau des documents. Les utilisateurs se plaignent de la latence des mises à jour.

Comment éviter : Surveillez db.serverStatus().wiredTiger.concurrentTransactions et examinez la disponibilité en écriture. Utilisez moins d'index sur les collections à forte écriture. Envisagez le sharding si le volume d'écriture dépasse la capacité d'un seul nœud.

Récupération : Supprimez les index inutiles et, si nécessaire, repensez le schéma pour éviter les documents volumineux qui provoquent des divisions de pages.

Piège 3 : Définir une taille de cache trop élevée

Pourquoi cela arrive : Un opérateur voit une utilisation élevée du cache et augmente cacheSizeGB à 80 % de la RAM, laissant peu de place au système d'exploitation et provoquant du swapping.

Comment éviter : Suivez les directives de la documentation MongoDB : cacheSizeGB doit être défini à 50 % de (RAM - 1 Go) ou au maximum 80 % de la mémoire disponible pour les serveurs dédiés, mais surveillez les métriques de mémoire de l'hôte. Utilisez db.serverStatus().wiredTiger.cache et free -m sur l'hôte pour vous assurer qu'il n'y a pas de swap.

Récupération : Si vous observez une utilisation du swap (vmstat 1 montre si ou so non nul), réduisez immédiatement cacheSizeGB et redémarrez mongod (ou définissez au moment de l'exécution puis persistez plus tard).

Piège 4 : Ne pas surveiller l'oplog

Pourquoi cela arrive : Une petite startup fonctionne bien, puis après une migration de données importante ou une période de forte écriture, les secondaires prennent du retard et ne peuvent pas rattraper car l'oplog a écrasé les entrées nécessaires.

Comment éviter : Configurez une alerte pour la fenêtre de l'oplog. Utilisez db.printReplicationInfo() pour vérifier la fenêtre. La fenêtre doit être au moins le temps nécessaire pour une resynchronisation complète ou une maintenance.

Récupération : Si un secondaire est trop en retard, effectuez une synchronisation initiale à partir d'une sauvegarde récente ou d'un autre membre. Augmentez proactivement la taille de l'oplog.

Piège 5 : Négliger le réglage du pool de connexions dans l'application

Pourquoi cela arrive : Les développeurs utilisent les tailles de pool par défaut des pilotes, qui peuvent être trop faibles pour une forte concurrence ou trop élevées pour des connexions serveur limitées.

Comment éviter : Effectuez des benchmarks avec une concurrence réaliste. Définissez la taille du pool pour gérer les charges de pointe sans submerger le serveur. Dans Node.js avec le pilote natif :

const { MongoClient } = require('mongodb');
const client = new MongoClient(uri, { maxPoolSize: 100, minPoolSize: 10 });

Récupération : Si vous voyez des délais de connexion fréquents, augmentez la taille du pool ; si les connexions serveur sont épuisées, réduisez la taille du pool ou ajoutez une limite de connexion sur le serveur.

Liste de contrôle des opérations

Utilisez cette liste de contrôle avant et après chaque changement de performance. Assignez un responsable à chaque élément et révisez chaque semaine ou après chaque changement important.

ÉlémentResponsableFréquenceVérification
Métriques de base enregistrées (latence, débit, utilisation des ressources)Responsable DBAAvant le changementCapturer la sortie mongostat et le nombre de requêtes lentes pendant 1 heure
Modèles de requêtes et couverture des index analysésIngénieur backendAvant le déploiement du codeexplain() sur les 10 principales requêtes montre IXSCAN, pas de COLLSCAN
Nouveaux index créés en staging et testésIngénieur de base de donnéesAvant la mise en productionComparaison de performance côte à côte sur un clone
Pool de connexions de l'application dimensionné correctementIngénieur backendÀ chaque versionTest de charge avec la concurrence de pointe attendue
Taille du cache et de l'oplog du serveur examinéeResponsable DBAMensueldb.printReplicationInfo() et db.serverStatus().wiredTiger.cache examinés
Alertes de surveillance activées pour les métriques clésIngénieur DevOpsMensuelTester l'alerte en simulant un dépassement de seuil
Plan de retour en arrière documenté pour chaque changementResponsable DBAPar changementCommande de retour ou restauration depuis la sauvegarde vérifiée

Exemples de responsables : Priya Shah, responsable ingénierie (Responsable DBA) ; Alex Chen, ingénieur backend ; Jordan Lee, ingénieur DevOps.

Conclusion

L'optimisation des performances de MongoDB est un processus itératif : observer, formuler des hypothèses, changer une variable, mesurer, puis soit conserver, soit revenir en arrière. Ce guide vous a donné les outils pour inventorier votre environnement, trouver les requêtes lentes, ajouter des index efficaces, ajuster les paramètres du serveur en toute sécurité et surveiller les régressions.

Maintenant, choisissez une action à faible risque de ce guide, comme activer le profileur avec un seuil de 50 ms, et exécutez-la dans votre environnement de développement. Enregistrez la base, effectuez le changement et comparez les résultats après une journée. La confiance que vous gagnerez grâce à cette petite amélioration vérifiée alimentera vos initiatives de performance plus larges.

Rappelez-vous : l'objectif n'est pas d'appliquer chaque conseil d'optimisation, mais de construire une approche systématique qui maintient votre déploiement MongoDB rapide et stable.

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO