Dépannage des performances pour Databases for MongoDB

Utilisez ce guide pour vous aider à identifier et à résoudre les problèmes de performance dans votre déploiement Databases for MongoDB fonctionnant sur IBM Cloud et alimenté par MongoDB.

Vous trouverez également plus d'informations sur la résolution des problèmes de performance dans les rubriques suivantes :

Si vos applications présentent des réponses lentes, des délais d'attente ou des performances de base de données incohérentes, prenez en compte les étapes et les informations suivantes.

Symptômes de problèmes de performance

Vous pouvez observer certains des symptômes suivants qui indiquent des problèmes de performance :

  • Augmentation de la latence des applications
  • Entrées du journal des requêtes lentes
  • Utilisation élevée de l'unité centrale ou de la mémoire
  • Augmentation de la latence du disque
  • Décalage de réplication
  • Délais d'attente de connexion

Suivez les étapes suivantes pour déterminer la cause des problèmes :

Étape 1 : Vérifier l'utilisation des ressources

  1. Connectez-vous à la console IBM Cloud et accédez à votre déploiement MongoDB.

  2. Examinez la section relative à la surveillance:

    • Utilisation de l'UC
    • Utilisation de la mémoire
    • IOPS et latence des disques
    • Connexions actives

Ce qu'il faut rechercher :

  • CPU constamment supérieur à 75 %
  • Mémoire constamment supérieure à 80
  • La latence du disque augmente avec le temps
  • Connexions proches des limites du régime

Actions recommandées :

  • Augmenter le stockage ou les IOPS si la latence du disque est élevée.
  • Examinez les pics de charge de travail dans votre application.

Si l'utilisation des ressources reste élevée pendant des périodes prolongées, il est recommandé de procéder à une mise à l'échelle.

Étape 2 : Identifier les requêtes lentes

Les requêtes lentes sont l'une des causes les plus courantes de la dégradation des performances.

  1. Activer le profilage :

    db.setProfilingLevel(1, { slowms: 100 })
    
  2. Examiner les récentes opérations de ralentissement :

    db.system.profile.find().sort({ ts: -1 }).limit(20)
    
  3. Analyser l'exécution de la requête :

    db.collection.find({ ... }).explain("executionStats")
    

Ce qu'il faut rechercher :

  • COLLSCAN (analyse de la collection au lieu de l'utilisation de l'index)
  • totalDocsExamined élevé par rapport à nReturned

Actions recommandées :

  • Créer les index appropriés.
  • Utiliser des index composés pour les requêtes portant sur plusieurs champs.
  • S'assurer que les pipelines d'agrégation commencent par $match.
  • Évitez les grandes paginations skip().

Étape 3 : Examen de l'utilisation des connexions

Des connexions élevées ou mal gérées peuvent avoir un impact sur les performances.

Vérifier les statistiques de connexion :

db.serverStatus().connections

Actions recommandées :

  • Utilisez la mise en commun des connexions dans votre application.
  • Évitez d'ouvrir une nouvelle connexion pour chaque demande.
  • Fermer les curseurs inutilisés.

Les limites de connexion sont déterminées par votre plan de déploiement.

Étape 4 : Vérifier l'état de la réplication

Le décalage de la réplication peut affecter les performances de lecture et la fraîcheur des données.

Vérifier l'état de la réplication :

rs.printSecondaryReplicationInfo()

Causes courantes de décalage :

  • Débit d'écriture élevé
  • Goulets d'étranglement des disques
  • Temps d'attente du réseau

Actions recommandées :

  • Augmenter les performances de stockage.
  • Examiner les paramètres des préoccupations d'écriture.
  • Passer à un plan supérieur si le décalage persiste.

Étape 5 : Considérations relatives aux clusters partagés (le cas échéant)

Vous pouvez avoir besoin du sharding dans les situations suivantes :

  • L'ensemble de travail est supérieur à la RAM
  • L'IOPS d'un nœud unique plafonne même après la mise à l'échelle
  • Une mise à l'échelle horizontale de l'écriture est nécessaire
  • Les collections dépassent 1 à 2 To

Pour plus d'informations, voir l'optimisation des performances et le sharding.

Si votre déploiement utilise le sharding, exécutez :

sh.status()

Vérifier pour :

  • Répartition inégale des morceaux
  • Morceaux géants
  • Le trafic est concentré sur un seul écran de fumée

Actions recommandées :

  • Revoir la sélection des clés de tesson.
  • Évitez d'augmenter de façon monotone les clés de la chambre.
  • Envisager des clés de tesson hachées.

Une mauvaise sélection des clés de la grappe peut affecter de manière significative les performances à l'échelle.

Étape 6 : Après la suppression de grandes quantités de données

La suppression d'un pourcentage important de données ne réduit pas immédiatement l'utilisation du disque au niveau du système d'exploitation.

Impacts possibles :

  • Fragmentation interne
  • Utilisation élevée du disque
  • Performances réduites

Actions recommandées :

  • Planifiez soigneusement les opérations de compactage.
  • En cas de fragmentation importante, il convient d'envisager une opération de vidage et de restauration.
  • Maintenir l'utilisation du disque en dessous de 80-85%.

Programmer les activités de maintenance de manière appropriée.

Étape 7 : Vérification de la contention du verrou

La contention des verrous peut avoir un impact important sur les opérations simultanées et le débit global.

  • Vérifier les statistiques globales de verrouillage :

    db.serverStatus().locks
    
  • Vérifier les opérations en cours pour les verrous :

    db.currentOp({
      $or: [
        { waitingForLock: true },
        { "locks.Global": "w" }
      ]
    })
    
  • Analyser le temps d'attente des verrous :

    db.serverStatus().globalLock
    

Ce qu'il faut rechercher :

  • Valeurs élevées currentQueue (lecteurs ou écrivains).
  • Opérations avec waitingForLock: true.
  • Les opérations de longue durée bloquent les verrous.
  • Les constructions d'index qui bloquent les opérations.

Causes courantes :

  • Requêtes à long terme sans index appropriés.
  • Opérations d'écriture de grande envergure.
  • L'indexation des grandes collections.
  • Commandes administratives (compact, repairDatabase ).

Actions recommandées :

  • Interrompre les opérations de longue durée si nécessaire :
    db.killOp(opid)
    
  • Construire des index en arrière-plan :
    db.collection.createIndex({ field: 1 }, { background: true })
    
  • Diviser les opérations importantes en lots plus petits.
  • Programmer les opérations d'entretien pendant les périodes de faible trafic.
  • Utiliser de manière appropriée les termes "read concern" et "write concern".

Étape 8 : Analyser les modèles de charge de travail

La compréhension des modèles de charge de travail permet d'identifier les possibilités d'optimisation.

  • Vérifier les compteurs d'opérations :

    db.serverStatus().opcounters
    
  • Analyser les opérations dans le temps :

    db.serverStatus().opcountersRepl
    
  • Identifier les collections les plus intéressantes :

    db.adminCommand({ top: 1 })
    
  • Vérifier le rapport de lecture par rapport au rapport d'écriture :

    var stats = db.serverStatus().opcounters;
    print("Read ratio: " + (stats.query + stats.getmore) / (stats.query + stats.getmore + stats.insert + stats.update + stats.delete));
    

Ce qu'il faut rechercher :

  • Opérations disproportionnées sur des collections spécifiques
  • Taux élevés de lecture/écriture ou d'écriture/lecture
  • Pics soudains du nombre d'opérations
  • Modèles temporels (heures de pointe)

Actions recommandées :

  • Optimisez d'abord les collections fréquemment consultées.
  • Envisagez des répliques en lecture pour les charges de travail à forte intensité de lecture.
  • Utiliser les préférences de lecture appropriées.
  • Mettre en place un système de cache pour les données fréquemment lues.
  • Revoir la stratégie d'indexation des collections chaudes.
  • Envisagez la mise en commun des données pour les collections à forte densité d'écriture.

Étape 9 : Étudier la pression de la mémoire et l'efficacité de la mémoire cache

MongoDB's WiredTiger s'appuie fortement sur l'efficacité de la mémoire cache.

  • Vérifier les statistiques du cache de WiredTiger:

    db.serverStatus().wiredTiger.cache
    
  • Examiner les indicateurs clés :

    var cache = db.serverStatus().wiredTiger.cache;
    print("Cache size: " + cache["bytes currently in the cache"]);
    print("Max cache size: " + cache["maximum bytes configured"]);
    print("Pages read into cache: " + cache["pages read into cache"]);
    print("Pages written from cache: " + cache["pages written from cache"]);
    print("Cache hit ratio: " + (1 - cache["pages read into cache"] / (cache["pages read into cache"] + cache["pages requested from the cache"])));
    
  • Vérifier la pression d'éviction :

    db.serverStatus().wiredTiger.cache["pages evicted by application threads"]
    

Ce qu'il faut rechercher :

  • Taux de réussite de la mémoire cache inférieur à 95
  • Taux d'expulsion élevés
  • Taille du cache constamment au maximum
  • Threads d'application effectuant des évictions

Estimer la taille de l'ensemble de travail :

db.serverStatus().wiredTiger.cache["tracked dirty bytes in the cache"]

Actions recommandées :

  • Passer à un plan avec plus de mémoire si le cache est constamment plein.
  • Révision et optimisation des index (suppression des index inutilisés).
  • Limiter la taille des ensembles de résultats dans les requêtes.
  • Utiliser les projections pour réduire la taille du document.
  • Pensez à archiver les anciennes données.
  • Suivre l'évolution de la taille des ensembles de travail.

Meilleures pratiques en matière d'allocation de mémoire

  • Le cache WiredTiger doit représenter 50 % de la RAM disponible (par défaut).
  • Laissez suffisamment de mémoire pour les autres processus.
  • Surveiller l'utilisation des swaps, qui doit être minimale.

Étape 10 : Examiner les paramètres de préoccupation en matière d'écriture et de préférence en matière de lecture

Les préférences en matière d'écriture et de lecture ont un impact significatif sur les performances et la cohérence.

  • Vérifier la préoccupation actuelle en matière d'écriture :

    db.getWriteConcern()
    
  • Vérifier la configuration de l'ensemble de répliques :

    rs.conf()
    
  • Écrire les options de préoccupation :

    Options d'écriture des préoccupations
    Ecriture d'une préoccupation Durabilité Performances Cas d'utilisation
    w: 1 Faible Elevé Données non critiques, haut débit
    w: "majority" Elevé Moyen Approche équilibrée par défaut
    w: <number> Moyenne-élevée Moyenne-Faible Nombre de répliques spécifiques
    j: true Maximale Le plus faible Données critiques nécessitant une synchronisation du journal
  • Lire les options de préférence :

    Lire les options de préférence
    Lire la préférence Cohérence Performances Cas d'utilisation
    primary Maximale Moyen Défaut, forte cohérence
    primaryPreferred Elevé Moyenne-élevée Repli sur le secondaire
    secondary Finale Elevé Analyses, rapports
    secondaryPreferred Finale Elevé Lire l'échelle
    nearest Finale Maximale Temps de latence le plus faible
  • Cochez la case "préférence de lecture" dans votre demande :

    // Example in Node.js driver
    db.collection('users').find({}).readPreference('secondary')
    

Ce qu'il faut rechercher :

  • Préoccupations trop strictes en matière d'écriture pour les données non critiques
  • Utilisation de primary pour la préférence de lecture lorsque la cohérence éventuelle est acceptable
  • Ne pas tirer parti des systèmes secondaires pour les charges de travail à forte densité de lecture

Actions recommandées :

  • Utilisez w: 1 pour les écritures non critiques à haut débit.
  • Utiliser w: "majority" pour les données importantes (par défaut).
  • Utilisez secondary ou secondaryPreferred pour les requêtes analytiques.
  • Envisager nearest pour les applications distribuées géographiquement.
  • Trouver un équilibre entre les exigences de cohérence et les besoins de performance.
  • Tester différentes configurations sous charge.

Étape 11 : Contrôler l'impact de la sauvegarde et de la maintenance

Les opérations de sauvegarde et les tâches de maintenance peuvent affecter temporairement les performances.

IBM Cloud calendrier de sauvegarde

Databases for MongoDB effectue automatiquement une sauvegarde. Vérifiez votre calendrier de sauvegarde dans la console IBM Cloud sous Sauvegardes.

Vérifier les opérations de sauvegarde en cours :

db.currentOp({
  $or: [
    { op: "command", "command.backup": { $exists: true } },
    { desc: /^conn/ }
  ]
})

Ce qu'il faut rechercher :

  • Dégradation des performances pendant les fenêtres de sauvegarde
  • Augmentation des E/S de disque lors des sauvegardes
  • Délai de réplication lors des sauvegardes

Actions recommandées :

  • Surveiller les mesures de performance pendant les périodes de sauvegarde.
  • Envisagez une mise à l'échelle si les sauvegardes ont un impact constant sur les performances.
  • Examiner les politiques de conservation des sauvegardes.
  • Prévoir une utilisation accrue des ressources pendant les opérations de restauration.

Meilleures pratiques en matière d'opérations de maintenance

  • Programmer les constructions d'indices pendant les périodes de faible trafic.
  • Utiliser, dans la mesure du possible, des index d'arrière-plan.
  • Surveiller le décalage de la réplication pendant la maintenance.
  • Tester d'abord les opérations de maintenance en dehors de la production.
  • Coordonner avec IBM Cloud les fenêtres de maintenance.