Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Pilier d'efficacité des performances
Le pilier de l'efficacité des performances du AWS Well-Architected Framework se concentre sur la manière d'optimiser les performances lors de l'ingestion ou de l'interrogation de données. L'optimisation des performances est un processus progressif et continu comprenant les éléments suivants :
-
Confirmation des exigences commerciales
-
Mesurer les performances de la charge de travail
-
Identification des composants sous-performants
-
Ajustement des composants pour répondre aux besoins de votre entreprise
Le pilier relatif à l'efficacité des performances fournit des directives spécifiques aux cas d'utilisation qui peuvent aider à identifier le modèle de données graphique et les langages de requête appropriés à utiliser. Il inclut également les meilleures pratiques à suivre lors de l'ingestion et de la consommation de données dans Amazon Neptune.
Le pilier de l'efficacité en matière de performance se concentre sur les domaines clés suivants :
-
Modélisation de graphes
-
Optimisation des requêtes
-
Dimensionnement correct du cluster
-
Optimisation de l'écriture
Comprendre la modélisation de graphes
Comprenez la différence entre les modèles Labeled Property Graph (LPG) et Resource Description Framework (RDF). Dans la plupart des cas, c'est une question de préférence. Il existe toutefois plusieurs cas d'utilisation où un modèle est mieux adapté que l'autre. Si vous avez besoin de connaître le chemin reliant deux nœuds de votre graphe, choisissez LPG. Si vous souhaitez fédérer les données entre des clusters Neptune ou d'autres magasins triples de graphes, choisissez RDF.
Si vous créez une application logicielle en tant que service (SaaS) ou une application nécessitant une mutualisation, envisagez d'intégrer la séparation logique des locataires dans votre modèle de données au lieu d'avoir un locataire pour chaque cluster. Pour obtenir ce type de conception, vous pouvez utiliser des graphes nommés et des stratégies d'étiquetage SPARQL, telles que l'ajout d'identifiants clients aux étiquettes ou l'ajout de paires clé-valeur de propriété représentant les identifiants des locataires. Assurez-vous que votre couche client injecte ces valeurs pour conserver cette séparation logique.
Les performances de vos requêtes dépendent du nombre d'objets graphiques (nœuds, arêtes, propriétés) qui doivent être évalués lors du traitement de votre requête. Le modèle graphique peut donc avoir un impact significatif sur les performances de votre application. Utilisez des étiquettes granulaires lorsque cela est possible et ne stockez que les propriétés dont vous avez besoin pour déterminer le chemin ou filtrer. Pour améliorer les performances, pensez à précalculer certaines parties de votre graphe, par exemple en créant des nœuds de synthèse ou des arêtes plus directes reliant des chemins communs.
Essayez d'éviter de naviguer entre des nœuds présentant un nombre anormalement élevé d'arêtes portant la même étiquette. Ces nœuds ont souvent des milliers d'arêtes (alors que le nombre d'arêtes de la plupart des nœuds se chiffre en dizaines). Il en résulte une complexité de calcul et de données beaucoup plus élevée. Ces nœuds peuvent ne pas poser de problème dans certains modèles de requêtes, mais nous vous recommandons de modéliser vos données différemment pour éviter cela, en particulier si vous devez naviguer entre les nœuds comme étape intermédiaire. Vous pouvez utiliser les journaux de requêtes lentes pour identifier les requêtes qui naviguent entre ces nœuds. Vous observerez probablement des indicateurs de latence et d'accès aux données bien supérieurs à vos modèles de requête habituels, en particulier si vous utilisez le mode débogage.
Utilisez un nœud déterministe IDs pour les nœuds et les arêtes si votre cas d'utilisation le permet au lieu d'utiliser Neptune pour attribuer des valeurs GUID aléatoires pour. IDs L'accès aux nœuds par identifiant est la méthode la plus efficace.
Optimisation des requêtes
Les langages OpenCypher et Gremlin peuvent être utilisés de manière interchangeable sur les modèles GPL. Si les performances sont une préoccupation majeure, envisagez d'utiliser les deux langages de manière interchangeable, car l'un peut être plus performant que l'autre pour des modèles de requête spécifiques.
Neptune est en train de passer à son moteur de requête alternatif (DFE). OpenCypher ne fonctionne que sur le DFE, mais les requêtes Gremlin et SPARQL peuvent éventuellement être configurées pour s'exécuter sur le DFE à l'aide d'annotations de requête. Pensez à tester vos requêtes avec le DFE activé et à comparer les performances de votre modèle de requête lorsque vous n'utilisez pas le DFE.
Neptune est optimisé pour les requêtes de type transactionnel qui démarrent sur un seul nœud ou un ensemble de nœuds et se déploient à partir de là, plutôt que pour les requêtes analytiques qui évaluent le graphe dans son intégralité. Pour vos charges de travail de requêtes analytiques, pensez à utiliser le SDK AWS pour Pandas
Pour identifier les inefficiences et les goulots d'étranglement dans vos modèles et requêtes, utilisez le profile
et explain
APIs pour chaque langage de requête afin d'obtenir des explications détaillées sur le plan des requêtes et les métriques des requêtes. Pour plus d'informations, consultez le profil Gremlin, OpenCypher explain et SPARQL explain.
Comprenez vos modèles de requêtes. Si le nombre d'arêtes distinctes dans un graphique devient important, la stratégie d'accès par défaut de Neptune peut devenir inefficace. Les requêtes suivantes peuvent s'avérer peu efficaces :
-
Requêtes qui naviguent vers l'arrière sur les arêtes lorsqu'aucune étiquette de bord n'est spécifiée.
-
Des clauses qui utilisent ce même modèle en interne, comme
.both()
dans Gremlin, ou des clauses qui suppriment des nœuds dans n'importe quelle langue (ce qui nécessite de supprimer les arêtes entrantes sans connaître les étiquettes). -
Requêtes qui accèdent aux valeurs des propriétés sans spécifier d'étiquettes de propriétés. Ces requêtes peuvent devenir très inefficaces. Si cela correspond à votre modèle d'utilisation, pensez à activer l'index OSGP (objet, sujet, graphe, prédicat).
Utilisez la journalisation lente des requêtes pour identifier les requêtes lentes. La lenteur des requêtes peut être due à des plans de requêtes non optimisés ou à un nombre inutilement élevé de recherches d'index, ce qui peut augmenter les coûts d'E/S. Les points de terminaison d'explication et de profilage Neptune pour Gremlin, SPARQL ou OpenCypher peuvent vous aider à comprendre pourquoi ces requêtes sont lentes. Les causes peuvent inclure les suivantes :
-
Les nœuds présentant un nombre anormalement élevé d'arêtes par rapport à la moyenne des nœuds du graphe (par exemple, des milliers au lieu de dizaines) peuvent accroître la complexité du calcul et, par conséquent, prolonger la latence et augmenter la consommation de ressources. Déterminez si ces nœuds sont correctement modélisés ou si les modèles d'accès peuvent être améliorés afin de réduire le nombre de tronçons à franchir.
-
Les requêtes non optimisées contiendront un avertissement indiquant que des étapes spécifiques ne sont pas optimisées. La réécriture de ces requêtes pour utiliser des étapes optimisées peut améliorer les performances.
-
Les filtres redondants peuvent entraîner des recherches d'index inutiles. De même, les modèles redondants peuvent entraîner des recherches d'index dupliquées qui peuvent être optimisées en améliorant la requête (voir
Index Operations - Duplication ratio
dans la sortie du profil). -
Certaines langues, telles que le gremlin, n'utilisent pas de valeurs numériques fortement saisies et utilisent plutôt la promotion de type. Par exemple, si la valeur est 55, Neptune recherche des valeurs entières, longues, flottantes et autres types numériques équivalents à 55. Cela entraîne des opérations supplémentaires. Si vous savez à l'avance que vos types correspondent, vous pouvez éviter cela en utilisant un indice de requête.
-
Votre modèle de graphe peut avoir un impact important sur les performances. Envisagez de réduire le nombre d'objets à évaluer en utilisant des étiquettes plus détaillées ou en précalculant les raccourcis vers des trajectoires linéaires à sauts multiples.
Si l'optimisation des requêtes à elle seule ne vous permet pas d'atteindre vos exigences en matière de performances, envisagez d'utiliser diverses techniques de mise en cache
Clusters de la bonne taille
Dimensionnez votre cluster en fonction de vos exigences en matière de simultanéité et de débit. Le nombre de requêtes simultanées pouvant être traitées par chaque instance du cluster est égal à deux fois le nombre de requêtes virtuelles CPUs (vCPUs) sur cette instance. Les requêtes supplémentaires qui arrivent alors que tous les threads de travail sont occupés sont placées dans une file d'attente côté serveur. Ces requêtes sont traitées sur une base first-in-first-out (FIFO) lorsque les threads de travail sont disponibles. La CloudWatch métrique MainRequestQueuePendingRequests
Amazon indique la profondeur de file d'attente actuelle pour chaque instance. Si cette valeur est souvent supérieure à zéro, envisagez de choisir une instance avec plus de CPUs v. Si la profondeur de la file d'attente dépasse 8 192, Neptune renvoie ThrottlingException
une erreur.
Environ 65 % de la RAM de chaque instance est réservée au cache tampon. Le cache tampon contient l'ensemble de données de travail (pas l'intégralité du graphique, mais uniquement les données demandées). Pour déterminer le pourcentage de données extraites du cache tampon au lieu du stockage, surveillez la CloudWatch métriqueBufferCacheHitRatio
. Si cette métrique tombe souvent en dessous de 99,9 %, pensez à essayer une instance avec plus de mémoire pour déterminer si elle réduit votre latence et vos coûts d'E/S.
Les répliques de lecture ne doivent pas nécessairement avoir la même taille que votre instance Writer. Cependant, des charges de travail d'écriture importantes peuvent entraîner le retard des répliques plus petites et leur redémarrage, car elles ne peuvent pas suivre le rythme de la réplication. Par conséquent, nous recommandons de créer des répliques égales ou supérieures à l'instance du rédacteur.
Lorsque vous utilisez l'auto-scaling pour vos répliques de lecture, n'oubliez pas que la mise en ligne d'une nouvelle réplique de lecture peut prendre jusqu'à 15 minutes. Lorsque le trafic client augmente rapidement mais de manière prévisible, envisagez d'utiliser un dimensionnement planifié pour augmenter le nombre minimum de répliques de lecture afin de tenir compte de ce temps d'initialisation.
Les instances sans serveur prennent en charge différents cas d'utilisation et charges de travail. Envisagez de surprovisionner des instances sans serveur dans les scénarios suivants :
-
Votre charge de travail fluctue souvent au cours de la journée.
-
Vous avez créé une nouvelle application et vous n'êtes pas certain de la taille de la charge de travail.
-
Vous êtes en train de développer et de tester.
Il est important de noter que les instances sans serveur sont plus chères que les instances provisionnées équivalentes sur la base d'un dollar par Go de RAM. Chaque instance sans serveur comprend 2 Go de RAM ainsi que le vCPU et le réseau associés. Effectuez une analyse des coûts entre vos options pour éviter les factures surprises. En général, vous réaliserez des économies avec le mode sans serveur uniquement lorsque votre charge de travail n'est très lourde que quelques heures par jour et presque nulle le reste de la journée ou si votre charge de travail fluctue de manière significative au cours de la journée.
Optimisez les écritures
Pour optimiser les écritures, tenez compte des points suivants :
-
Le Neptune Bulk Loader est le moyen optimal pour charger initialement votre base de données ou pour l'ajouter à des données existantes. Le chargeur Neptune n'est pas transactionnel et ne peut pas supprimer de données. Ne l'utilisez donc pas si vous le souhaitez.
-
Les mises à jour transactionnelles peuvent être effectuées à l'aide des langages de requête pris en charge. Pour optimiser les opérations d'E/S d'écriture, écrivez les données par lots de 50 à 100 objets par validation. Un objet est un nœud, une arête ou une propriété sur un nœud ou une arête dans LPG, ou un triple store ou un quad dans RDF.
-
Toutes les opérations d'écriture de Neptune sont effectuées en un seul thread pour chaque connexion. Lorsque vous envoyez une grande quantité de données à Neptune, envisagez d'avoir plusieurs connexions parallèles qui écrivent chacune des données. Lorsque vous choisissez une instance provisionnée Neptune, la taille de l'instance est associée à un nombre de v. CPUs Neptune crée deux threads de base de données pour chaque vCPU de l'instance. Commencez donc par deux fois le nombre de v CPUs lorsque vous testez une parallélisation optimale. Les instances sans serveur redimensionnent le nombre de v CPUs à un taux d'environ un pour 4 NCUs.
-
Planifiez et gérez efficacement tous ConcurrentModificationExceptionsles processus d'écriture, même si une seule connexion écrit des données à la fois. Concevez vos clients de manière fiable lorsque cela
ConcurrentModificationExceptions
se produit. -
Si vous souhaitez supprimer toutes vos données, pensez à utiliser l'API de réinitialisation rapide au lieu d'émettre des requêtes de suppression simultanées. Ce dernier prendra beaucoup plus de temps et entraînera des coûts d'E/S substantiels par rapport au premier.
-
Si vous souhaitez supprimer la plupart de vos données, pensez à exporter les données que vous souhaitez conserver en utilisant neptune-export
pour les charger dans un nouveau cluster. Supprimez ensuite le cluster d'origine.