Apprendre MongoDB nécessite beaucoup de réflexion précise. Souvent, peu d'attention est accordée aux entreprises essentielles qui pourraient autrement compromettre les performances de la base de données en mode production.
MongoDB est un SGBD NoSQL qui suit littéralement un modèle différent des bases de données SQL, notamment en termes de sécurité et de structure. Bien que certaines des fonctionnalités intégrées favorisent ses performances et en font l'une des meilleures de ces derniers temps, certaines fonctionnalités présentent par conséquent des menaces potentielles qui peuvent ruiner ses performances si elles ne sont pas prises en compte.
Dans une récente expérience du "pire cas", j'essayais d'interroger une collection avec des documents qui avaient de grands tableaux et il m'a fallu des années pour obtenir les résultats. J'ai décidé d'écrire ce blog car je savais que si quelqu'un rencontrait ces mêmes problèmes, ce blog serait d'une grande aide.
Considérations clés pour MongoDB en production
- Sécurité et authentification.
- Indexation de vos documents
- Utiliser un schéma dans vos collections
- Collection plafonnée
- Taille du document
- Taille du tableau pour les documents intégrés
- Étapes du pipeline d'agrégation
- Ordre des clés dans l'objet de hachage
- 'undefined' et 'null' dans MongoDB
- Opération d'écriture
Sécurité et authentification MongoDB
Les données varient à bien des égards et vous devrez évidemment garder certaines informations confidentielles. Par défaut, les installations de MongoDB ne définissent pas l'exigence d'authentification comme une obligation, mais cela ne vous donne pas la possibilité de l'utiliser, en particulier lorsque des données confidentielles telles que des dossiers financiers et médicaux sont impliquées. Sur un poste de développement, ce n'est pas grave mais du fait de l'implication du multi-utilisateur en mode production, il est de bon ton de paramétrer les certificats d'authentification. La méthode la plus courante et la plus facile à utiliser est le nom d'utilisateur et le mot de passe MongoDB par défaut.
Les données sont écrites dans des fichiers accessibles via un outil tiers, d'autant plus s'ils ne sont pas cryptés. Les données peuvent être modifiées à votre insu si une personne anonyme accède aux fichiers système. L'hébergement de la base de données sur un serveur dédié et l'affectation d'un seul utilisateur qui aura un accès complet aux fichiers de données vous évitera l'astuce.
Protéger les données des attaques par injection externe est également une entreprise essentielle. Certains opérateurs tels que $group, $whereby et les opérations mapReduce sont développés en javascript (js) et donc sujets à la manipulation de js. Pour éviter toute instance d'intégrité des données, vous pouvez désactiver les paramètres JS arbitraires en configurant le paramètre javascriptEnabled:false dans le fichier de configuration si vous n'avez utilisé aucun des opérateurs mentionnés. De plus, vous pouvez réduire le risque d'accès aux données via des failles de réseau en utilisant certaines des procédures décrites dans la liste de contrôle de sécurité MongoDB.
Indexation de vos documents
L'indexation consiste généralement à attribuer une valeur d'identification unique à chaque document d'une collection MongoDB. L'indexation entraîne une amélioration des performances dans les opérations de lecture et d'écriture. Par défaut, il est activé et vous devez toujours conserver ce paramètre. Sans indexation, la base de données doit vérifier plusieurs documents du début à la fin et, malheureusement, l'opération sera coûteuse en temps pour les documents qui sont vers la fin, ce qui rend la latence médiocre pour la requête. À un moment donné, du côté de l'application, les utilisateurs peuvent rencontrer un décalage et penser que l'application ne fonctionne pas. L'indexation est utile dans les opérations de requête de tri et de recherche sans omettre l'opération de recherche elle-même. Le tri est une opération courante pour de nombreux documents retournés. Il s'agit souvent de l'étape finale après le filtrage des documents, de sorte qu'une petite quantité de données doit être triée. Dans ce cas, un index aidera à trier les données par nature d'entrée et à limiter les données renvoyées à une limite de 32 Mo. S'il n'y a pas d'indexation, les chances que la limite de mémoire de 32 sur la taille combinée des documents renvoyés soient dépassées et chaque fois que la base de données atteint cette limite, elle génère une erreur en plus de renvoyer un jeu d'enregistrements vide.
L'opération $lookup est également prise en charge avec l'indexation en place. Un index sur la valeur de clé utilisée comme clé étrangère est indispensable pour le traitement des étapes précédentes.
Utiliser un schéma dans vos collections
MongoDB n'en a pas besoin pour définir les champs (colonnes) comme il peut vous être demandé de le faire pour les bases de données SQL. Même si vous n'aurez pas besoin de définir les champs, pour éviter l'incohérence des données et certains revers qui peuvent survenir, la définition d'un schéma est toujours une bonne pratique. La conception de schéma vous permet de déterminer quel type de données va dans un certain champ, quel champ doit être fourni avec une valeur et améliore généralement la validation des données avant la saisie ou la mise à jour, favorisant ainsi l'intégrité et la cohérence des données. Une conception de schéma vous indiquera également si vous souhaitez référencer ou intégrer des données. En tant que débutant, vous pensez peut-être que le seul modèle sera "Un vers N" qui facilitera l'accès aux entrées de tableau de sous-documents, mais ce n'est pas le cas.
Vous devez comprendre la relation de cardinalité entre les documents avant de créer votre modèle. Certaines des règles qui vous aideront à avoir un schéma optimal sont :
- Pour réduire le nombre de requêtes que vous devrez exécuter avant d'accéder à certaines données et si peu de champs ou d'éléments de tableau sont impliqués, vous pouvez intégrer des sous-documents. Prenons un exemple du modèle ci-dessous :
-
{ Name: ‘John Doh’, Age:20 Addresses:[ {street: ‘Moi Avenue’, city:’Nairobi’, countryCode: ‘KE’}, {street: ‘Kenyatta Avenue’, city:’Nairobi’, countryCode: ‘KE’}, ] }
-
- Pour les documents fréquemment mis à jour, utilisez la dénormalisation . Si un champ doit être fréquemment mis à jour, la tâche consistera à rechercher toutes les instances qui doivent être mises à jour. Cela entraînera un traitement lent des requêtes, écrasant ainsi même les mérites associés à la dénormalisation.
- L'exécution de requêtes complexes telles que le pipelining agrégé prend plus de temps lorsque de nombreux sous-documents sont impliqués et qu'il est nécessaire de récupérer un document séparément.
- Les éléments de tableau contenant un grand nombre de données d'objet ne doivent pas être intégrés, car ils peuvent grossir et par conséquent dépasser la taille du document.
La modélisation d'un schéma est souvent déterminée par le modèle d'accès à l'application. Vous pouvez trouver plus de procédures qui peuvent aider à la conception de votre modèle dans le blog 6 Rules of Thumb for MongoDB Schema Design
Utiliser une collection limitée pour la priorité des documents récents
MongoDB fournit de nombreuses ressources telles que la collection plafonnée. Malheureusement, certains finissent par ne pas être utilisés. Une collection limitée a une taille fixe et est connue pour prendre en charge les opérations à haut débit qui insèrent et récupèrent des documents en fonction de l'ordre d'insertion. Lorsque son espace est rempli, les anciens documents sont supprimés pour faire place aux nouveaux.
Exemple de cas d'utilisation de collecte plafonnée :
- Mettre en cache les données fréquemment consultées, car la collection elle-même est lourde en lecture plutôt qu'en écriture. Vous devez vous assurer que la collection est toujours performante.
- Informations de journal pour les systèmes à volume élevé. La collection plafonnée n'utilise souvent pas d'index, ce qui est avantageux dans la mesure où la vitesse d'enregistrement est assez rapide, tout comme l'écriture dans un fichier.
Faites attention à la taille du document MongoDB
Chaque document MongoDB est limité à une taille de 16 mégaoctets. Cependant, il est optimal que le document atteigne ou s'approche de cette limite, car cela posera d'atroces problèmes de performances. MongoDB lui-même fonctionne mieux lorsque la taille des documents est de quelques kilo-octets. Si le document est suffisamment volumineux, une demande de projection complexe prendra beaucoup de temps et la requête risque d'expirer.
Faites attention à la taille du tableau des documents intégrés
On peut pousser des sous-documents vers un champ dans un document créant ainsi une valeur de tableau sur ce champ. Comme mentionné précédemment, vous devez limiter la taille des sous-documents. Il est tout aussi important de s'assurer que le nombre d'éléments du tableau est inférieur à quatre chiffres. Sinon, le document dépassera sa taille et devra être déplacé sur le disque. Un autre problème associé à une telle opération est que chaque document devra être réindexé. De plus, chaque sous-document devra également être réindexé. Cela signifie qu'il y aura beaucoup d'écritures d'index qui entraîneront des opérations lentes. Pour les sous-documents de grande taille, il est plutôt important de conserver les enregistrements dans une nouvelle collection plutôt que de les incorporer.
Étapes du pipeline d'agrégation
Outre les opérations de requête MongoDB normales, il existe un cadre d'agrégation utilisé pour manipuler et renvoyer des données conformément à certaines spécifications telles que l'ordre et le regroupement. MongoDB n'a pas d'optimiseur de requêtes, il en faut donc un pour ordonner les requêtes de manière appropriée. Avec le cadre d'agrégation, assurez-vous que les étapes du pipeline sont bien ordonnées. Commencez par réduire la quantité de données que vous traitez en utilisant l'opérateur $match et éventuellement $sort à la fin si vous avez besoin de trier. Vous pouvez utiliser des outils tiers tels que Studio 3T pour optimiser votre requête d'agrégation avant de l'intégrer dans votre code. L'outil vous permet de voir les entrées et les sorties de données à n'importe quelle étape, ce qui vous permet de savoir à quoi vous avez affaire.
L'utilisation de $limit et $sort devrait toujours donner les mêmes résultats à chaque fois que la requête est exécutée. Si vous utilisez $limit, les données renvoyées ne seront pas déterministes et peuvent rendre certains problèmes difficiles à suivre.
Vérifier l'ordre des clés dans les objets de hachage
Envisagez d'avoir deux documents volumineux avec des exemples de données
{
FirstName: ‘John’,
LastName: ‘Doh’
}
Si vous effectuez une opération de recherche avec la requête {FirstName :'John', LastName :'Doh'}, l'opération ne correspond pas à la requête {LastName :'Doh' FirstName :'John' }. Vous devez donc respecter l'ordre des paires nom et valeur dans vos documents.
Évitez 'undefined' et 'null' dans MongoDB
MongoDB utilise le format BSON pour ses documents. Avec la validation JSON, "undefined" n'est pas pris en charge et vous devez éviter de l'utiliser. $null est une solution, mais vous devriez également l'éviter.
Envisager des opérations d'écriture
Vous pouvez définir MongoDB pour les écritures à grande vitesse, mais cela pose un problème dans la mesure où une réponse est renvoyée avant même que les données ne soient écrites. La journalisation doit être activée pour éviter ce scénario. De plus, en cas de panne de la base de données, les données seront toujours disponibles et cela créera un point de contrôle qui pourra être utilisé dans le processus de récupération. La configuration de la durée des écritures dans le journal peut être définie à l'aide du paramètre commitIntervalMs.
Conclusion
Le système de base de données doit garantir l'intégrité et la cohérence des données en plus d'être résistant aux pannes et à la malveillance. Cependant, pour arriver à ces facteurs, il faut comprendre la base de données elle-même et les données qu'elle contient. MongoDB fonctionnera bien lorsque les facteurs mentionnés ci-dessus sont pris en compte. Le plus important étant d'utiliser un schéma. Un schéma vous permet de valider vos données avant saisie ou mise à jour et comment vous allez modéliser ces données. La modélisation des données est souvent pilotée par le modèle d'accessibilité de l'application. Toutes ces additions offriront une meilleure performance de la base de données.