Optimiser les performances des requêtes
Pour résoudre les problèmes liés aux requêtes lentes, utilisez Query Explain afin d'obtenir le plan d'exécution de la requête et le profil d'exécution au moment de l'exécution. La section suivante décrit les étapes à suivre pour optimiser les performances des requêtes en fonction du profil d'exécution :
Limiter le nombre de résultats
Utilisez le champ "records returned" (enregistrements renvoyés) dans l'arborescence d'exécution pour déterminer si la requête renvoie de nombreux documents. Envisagez de limiter le nombre de documents renvoyés à l'aide de la clause $limit. Cela réduit la taille des octets sérialisés des résultats lorsqu'ils sont renvoyés aux clients sur le réseau. Dans les cas où le nœud Limit est précédé d'un nœud MajorSort, le moteur de requêtes peut fusionner les nœuds Limit et MajorSort, et remplacer une matérialisation et un tri complets en mémoire par un tri TopN, ce qui réduit les besoins en mémoire de la requête.
Limiter la taille du document de résultat
Envisagez de limiter la taille du
document renvoyé à l'aide de la
$project clause pour éviter de récupérer
des champs inutiles. Cela permet de réduire le coût de calcul et de mémoire lié au traitement des résultats intermédiaires, ainsi que la taille des octets sérialisés des résultats lorsqu'ils sont renvoyés aux clients sur le réseau. Dans les cas où tous les champs référencés dans la requête sont couverts par un index régulier (et non multiclés), cela permet également à la requête d'être entièrement couverte par l'analyse d'index, ce qui évite d'avoir à récupérer des documents à partir du stockage principal.
Utiliser des index
Suivez les instructions ci-dessous pour configurer et optimiser les index.
Déterminer si la requête utilise un index
Vous pouvez déterminer si la requête utilise un index en vérifiant les nœuds feuilles dans l'arborescence d'exécution. Si le nœud feuille de l'arborescence d'exécution est un nœud TableScan, cela signifie que la requête n'utilise pas d'index et qu'elle analyse les documents à partir du stockage principal. Si un index est utilisé, le nœud feuille de l'arborescence d'exécution affiche l'ID de l'index et les champs d'index de l'index.
Déterminer si l'index utilisé peut être optimisé
Un index est utile pour une requête s'il peut réduire le nombre de documents que le moteur de requêtes doit récupérer à partir du stockage principal ou si son ordre de champ peut répondre aux exigences de tri de la requête.
Si un index est utilisé pour une requête, mais que le moteur de requêtes récupère et supprime toujours de nombreux documents, comme l'indique un nœud Scan qui renvoie de nombreux enregistrements suivi d'un nœud Filter qui renvoie peu d'enregistrements, cela signifie que le prédicat de requête satisfait à l'aide de l'index n'est pas sélectif. Pour créer un index plus adapté, consultez Créer des index.
Si un index non multiclés est utilisé pour une requête, mais que le moteur de requêtes effectue toujours un réordonnancement en mémoire de l'ensemble de résultats, comme l'indique un nœud MajorSort dans l'arborescence d'exécution de la requête, cela signifie que l'index utilisé ne peut pas être utilisé pour répondre aux exigences de tri de la requête. Pour créer un index plus adapté, consultez la section suivante.
Optimiser les requêtes $lookup
Vous pouvez optimiser les requêtes $lookup en ajoutant des index à la collection from, ce qui permet à l'opération de trouver efficacement les documents correspondants sans analyser l'ensemble de la collection.
$lookup avec localField et foreignField
Si vous utilisez les options localField et foreignField dans l'étape $lookup, créez un index sur le foreignField dans la collection from.
$lookup avec des pipelines imbriqués
Si vous utilisez l'option pipeline dans l'étape $lookup avec des étapes $match, créez un index sur les champs impliqués dans la collection étrangère pour éviter une analyse complète de la table :
- Pour les étapes
$matchavec une sémantique de filtre (par exemple{$match: {a: true}}), créez un index sur les champs impliqués dans la collection étrangère (a). - Pour les étapes
$matchavec une sémantique d'agrégation qui compare un champ à une valeur constante (par exemple{$match: {$expr: {$gt: [a, 10]}}}) ou avec des comparaisons d'égalité (eqouin) entre des champs et des variables définies danslet(par exemple{$match: {$expr: {$eq: [a, "$$a"]}}}), créez un index sur les champs impliqués dans la collection étrangère. Notez que l'index multiclés ne sera pas utilisé dans la planification.
Créer des index
Suivez la documentation sur la gestion des index pour créer des index. Pour vous assurer que votre requête peut utiliser des index, créez des index réguliers (et non multiclés) avec des champs dans l'ordre suivant :
- Tous les champs qui seront utilisés dans les opérateurs d'égalité. Pour maximiser les chances de réutilisation entre les requêtes, ordonnez les champs par ordre décroissant d'occurrence des champs dans les opérateurs d'égalité entre les requêtes.
- Tous les champs sur lesquels le tri sera effectué (dans le même ordre).
- Champs qui seront utilisés dans les opérateurs de plage ou d'inégalité par ordre décroissant de sélectivité des contraintes de requête.
- Champs qui seront renvoyés dans le cadre d'une requête dans l'index : l'inclusion de ces champs dans l'index permet à l'index de couvrir la requête et d'éviter d'avoir à récupérer le document à partir du stockage principal.
Pour les requêtes qui impliquent le filtrage et le tri des champs de tableau, envisagez de créer des index multiclés.
Utiliser un indice de requête
Si vous avez créé un index plus adapté à la requête, mais que le moteur de requêtes ne l'utilise pas, vous pouvez remplacer la préférence d'index du moteur de requêtes à l'aide d'un indice de requête.