Comment la projection mongoDB affecte les performances?


10

D'après la MongoDBdocumentation, il est mentionné que:

Lorsque vous n'avez besoin que d'un sous-ensemble de champs de documents, vous pouvez obtenir de meilleures performances en renvoyant uniquement les champs dont vous avez besoin

Comment les champs de filtrage affectent les performances? Les performances sont-elles liées à la taille des données transmises sur le réseau? ou la taille des données qui seront conservées en mémoire? Comment exactement cette performance est-elle améliorée? Quelle est cette performance mentionnée dans la documentation?

J'ai des requêtes MongoDB lentes. Le renvoi d'un sous-ensemble affecte-t-il ma requête lente (j'ai un index composé sur le terrain)?


Sans le code, il n'est pas possible de vous suggérer. ce qui va réellement affecter les performances de la requête de projection "MongoDB". C'est toujours mieux au moins de mentionner le code.
Md Haidar Ali Khan

@MdHaidarAliKhan il ne s'agit pas du code et de ma charge utile. Je veux juste savoir pourquoi mongoDB dit que le filtrage affecte les performances? De quel point de vue cette performance a été mesurée? Par exemple, cela aide-t-il à l'utilisation de la mémoire de Mongo en raison de moins de données ou moins d'E / S disque (par exemple) et ainsi de suite.
ALH

Je veux juste savoir pourquoi mongoDB dit que le filtrage affecte les performances? eh bien, utilisez les projections pour renvoyer uniquement les données nécessaires, je veux dire que vous pouvez obtenir de meilleures performances en renvoyant uniquement les champs dont vous avez besoin. Par exemple, db.posts.find ({}, {}). Sort ({}).
Md Haidar Ali Khan

Par exemple, cela aide-t-il l'utilisation de la mémoire de Mongo en raison de moins de données ou moins d'E / S disque (par exemple), etc.
Md Haidar Ali Khan

@MdHaidarAliKhan OS est Debian 8,MongoDB 3.6.2
ALH

Réponses:


15

Par défaut, les requêtes renvoient tous les champs des documents correspondants. Si vous avez besoin de tous les champs, le retour de documents complets sera plus efficace que le fait que le serveur manipule l'ensemble de résultats avec des critères de projection.

Cependant, l'utilisation de la projection pour limiter les champs à renvoyer des résultats de requête peut améliorer les performances en:

  • suppression des champs inutiles des résultats de la requête (économie de bande passante réseau)
  • limitation des champs de résultat pour obtenir une requête couverte (retour des résultats de requête indexée sans récupérer les documents complets)

Lors de l'utilisation de la projection pour supprimer les champs inutilisés, le serveur MongoDB devra récupérer chaque document complet en mémoire (s'il n'est pas déjà là) et filtrer les résultats pour revenir. Cette utilisation de la projection ne réduit pas l'utilisation de la mémoire ou l'ensemble de travail sur le serveur MongoDB, mais peut économiser une bande passante réseau importante pour les résultats de la requête en fonction de votre modèle de données et des champs projetés.

Une requête couverte est un cas spécial où tous les champs demandés dans un résultat de requête sont inclus dans l'index utilisé, de sorte que le serveur n'a pas à extraire le document complet. Les requêtes couvertes peuvent améliorer les performances (en évitant d'aller chercher des documents) et l'utilisation de la mémoire (si d'autres requêtes ne nécessitent pas d'aller chercher le même document).

Exemples

À des fins de démonstration via le mongoshell, imaginez que vous avez un document qui ressemble à ceci:

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

Le champ bpeut représenter une sélection de valeurs (ou dans ce cas une chaîne très longue).

Ensuite, créez un index sur {a:1}lequel se trouve un champ couramment utilisé interrogé par votre cas d'utilisation:

db.data.createIndex({a:1})

Un simple findOne()sans critère de projection renvoie un résultat de requête d'environ 10 Mo:

> bsonsize(db.data.findOne({}))
10485805

L'ajout de la projection {a:1}limitera la sortie au champ aet au document _id(qui est inclus par défaut). Le serveur MongoDB manipule toujours un document de 10 Mo pour sélectionner deux champs, mais le résultat de la requête n'est plus que de 33 octets:

> bsonsize(db.data.findOne({}, {a:1}))
33

Cette requête n'est pas couverte car le document complet doit être récupéré pour découvrir la _idvaleur. Le _idchamp est inclus par défaut dans les résultats de la requête car il s'agit de l'identifiant unique d'un document, mais _idil ne sera pas inclus dans un index secondaire sauf s'il est explicitement ajouté.

Les mesures totalDocsExaminedet totalKeysExamineddans les explain()résultats montreront combien de documents et de clés d'index ont été examinés:

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

Cette requête peut être améliorée en utilisant la projection pour exclure le _idchamp et obtenir une requête couverte en utilisant uniquement l' {a:1}index. La requête couverte n'a plus besoin de récupérer un document de ~ 10 Mo en mémoire, elle sera donc efficace à la fois dans l'utilisation du réseau et de la mémoire:

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

J'ai des requêtes MongoDB lentes. Le renvoi d'un sous-ensemble affecte-t-il ma requête lente (j'ai un index composé sur le terrain)?

Ce n'est pas possible sans le contexte d'une requête spécifique, un exemple de document et la sortie d'explication complète. Cependant, vous pouvez exécuter des tests de performance dans votre propre environnement pour la même requête avec et sans projection pour comparer le résultat. Si votre projection ajoute une surcharge importante au temps d'exécution global des requêtes (traitement et transfert des résultats), cela peut être un indice fort que votre modèle de données pourrait être amélioré.

S'il n'est pas clair pourquoi une requête est lente, il serait préférable de poster une nouvelle question avec des détails spécifiques à étudier.


1
J'apprécie vraiment pour l'explication approfondie du problème. Il semble qu'il ne soit pas possible d'avoir des requêtes couvertes car ma réponse contient beaucoup plus de données qu'à l'intérieur de l'index. Ma principale question est ici, je serais heureux si vous pouviez jeter un œil: dba.stackexchange.com/questions/195065/…
ALH

1

Avec une projection, vous pouvez obtenir une situation où l'ensemble de résultats provient directement de l'index.

Si vous avez un index composé {x:1, y:1, z:1}où aucun de x, y, z n'est _id, vous devez projeter {_id:0, x:1, y:1, z:1}car il _idest toujours renvoyé dans le jeu de résultats (lorsqu'il n'est pas projeté) et le moteur doit lire les fichiers de données pour l'obtenir. En effet, l'index n'a pas la valeur de _id, uniquement le pointeur sur le document où la valeur est stockée.


Donc, si je retire _idde la réponse retournée, cela tient-il dans la RAM? Est ce que ça aide?
ALH

1
MongoD (essaie) de conserver au moins les index en mémoire (et autant de données que ce qui convient). Si votre requête peut être remplie directement à partir de l'index et que vous projetez, _id:0le résultat est entièrement renvoyé de la RAM, sans lire les données du disque.
JJussi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.