paint-brush
Backend efficace, performances supérieures : une plongée approfondie dans l'optimisation des services Webpar@sergeidzeboev
930 lectures
930 lectures

Backend efficace, performances supérieures : une plongée approfondie dans l'optimisation des services Web

par Sergei Dzeboev8m2023/11/21
Read on Terminal Reader

Trop long; Pour lire

L'optimisation du backend d'un service Web va au-delà de la simple amélioration du code et des algorithmes. La clé pour améliorer l’efficacité des services consiste à optimiser les interactions avec les bases de données. Cela peut être réalisé en affinant les requêtes ORM, en utilisant des classes de données plates, en catégorisant correctement les données comme chaudes, tièdes ou froides et en employant des stratégies de mise en cache efficaces. Ces étapes conduisent à un service Web plus efficace, plus réactif et plus performant.
featured image - Backend efficace, performances supérieures : une plongée approfondie dans l'optimisation des services Web
Sergei Dzeboev HackerNoon profile picture
0-item


L’optimisation du backend d’un service web vise toujours à augmenter ses performances, dont un aspect clé est l’accélération du traitement des données. Ce processus englobe de nombreuses améliorations importantes visant à utiliser plus efficacement les ressources et à minimiser le temps de réponse du système aux demandes. Dans cet article, je partagerai plusieurs techniques éprouvées qui peuvent accélérer considérablement votre service Web.


Sur quoi se concentrer pour s’améliorer ?

De nombreux programmeurs, dans leur quête de rendre une application plus rapide, se concentrent sur l'optimisation du code et des algorithmes, en choisissant des structures de données appropriées et des opérations optimales. Cela conduit généralement à une amélioration des performances, améliorant souvent la vitesse du code optimisé, mais pas de manière substantielle.


Cette modeste augmentation est due à la vitesse inhérente des opérations de mémoire, et des améliorations significatives ne devraient pas être attendues à moins que le code original ne soit très inefficace. Cependant, certaines opérations chronophages doivent être priorisées pour l’optimisation, notamment les opérations d’entrées-sorties.


Qu'il s'agisse de travailler avec des fichiers ou d'interagir avec une base de données, le temps d'exécution de ces tâches est toujours remarquable par rapport aux opérations en mémoire. Vous ne pouvez pas influencer de manière significative le processus de lecture des données d'un fichier, mais l'utilisation de la base de données est sous votre contrôle direct. En tant que développeur, vous disposez de toutes les capacités pour améliorer considérablement cette interaction.


Explorons les stratégies suivantes pour rendre le travail avec votre base de données plus efficace, augmentant ainsi considérablement les performances de votre service backend


Optimiser les requêtes

Aujourd'hui, il est rare de trouver un service Web back-end qui n'utilise pas de système de mappage objet-relationnel (ORM) pour les interactions avec les bases de données. Si vous recherchez des résultats de premier ordre, pensez à personnaliser l'ORM. Bien que les ORM soient efficaces et sans erreurs, ils sont conçus pour un usage général. Cette large applicabilité se fait souvent au détriment des hautes performances.


N'oubliez pas que les ORM sont créés pour être compatibles avec diverses bases de données, ce qui peut signifier passer à côté d'avantages spécifiques de la base de données que vous avez sélectionnée pour votre projet. Par exemple, comme illustré ici, l’exploitation de fonctionnalités uniques de base de données peut considérablement améliorer la vitesse des interactions avec la base de données, jusqu’à 30 fois.


Au lieu de dépendre uniquement des requêtes par défaut fournies par un ORM, il vaut la peine de créer vos propres requêtes optimisées. Les requêtes personnalisées fonctionnent souvent mieux, en particulier dans les scénarios impliquant plusieurs jointures.


Vous trouverez ci-dessous un exemple simple dans Spring JPA de la façon dont vous pouvez améliorer les performances à l'aide d'une requête de jointure :

 @Transactional @Lock(LockModeType.PESSIMISTIC_READ) @Query(value = """ SELECT e FROM EmployeeRecord e LEFT JOIN DepartmentRecord d ON e.departmentId = d.id WHERE e.departmentId = :departmentId; """) List<EmployeeRecord> findEmployeesByDepartmentId(Integer departmentId);


Utiliser des classes plates

L'utilisation de classes complexes avec des objets imbriqués et un système hiérarchique profond peut entraîner une perte significative des performances du système. Il est souvent inutile d'interroger la base de données sur l'intégralité de la structure imbriquée, en particulier lorsque toutes les classes de la structure ne sont pas pleinement utilisées.


Bien que l'initialisation paresseuse permette d'atténuer les requêtes inutiles sur les objets imbriqués, des défis surviennent lorsqu'un objet imbriqué est nécessaire, mais que toutes ses données ne sont pas requises. La solution à ce dilemme consiste à utiliser des classes de données plates.


Vous devez créer une classe conçue pour collecter uniquement les données de champ nécessaires à partir de la base de données. Ensuite, avec une requête de base de données personnalisée intégrant toutes les jointures nécessaires, sélectionnez uniquement les champs réellement nécessaires.


Cette approche améliorera non seulement la vitesse des requêtes, mais réduira également le trafic de données de la base de données vers votre service.


Par exemple, en utilisant NamedParameterJdbcTemplate de Spring JPA, une classe plate avec les champs nécessaires peut être créée :

 public record EmployeeDepartment(Integer employeeId, String employeeName, String departmentName) { }


Ensuite, à l'aide d'un script simple, seuls les champs nécessaires sont collectés à partir des tables principales et jointes :

 public List<EmployeeDepartment> employeeDepartments() { return template.query(""" SELECT employees.employee_id, employees.employee_name, departments.department_name FROM employees LEFT JOIN departments ON employees.department_id = departments.department_id; """, new MapSqlParameterSource(), employeeDepartmentMapper); }


Cette approche réduira considérablement la charge et rendra le travail avec les données beaucoup plus efficace.


Définir les données chaudes

La prochaine étape importante dans le travail avec les données consiste à définir les types de données, le type principal étant Hot Data.


Les Hot Data sont les données que le service traite en temps réel. Ces données ne peuvent pas être mises en cache car la pertinence de la réponse du service web dépend de sa réactivité immédiate. Ces données doivent donc toujours être à jour. Le service fonctionne systématiquement avec Hot Data, enregistrant continuellement de nouvelles valeurs et extrayant des informations pour des mises à jour opportunes.


Pour travailler avec les Hot Data le plus efficacement possible, il est crucial de veiller à ce que la table dans laquelle elles sont stockées reste aussi compacte que possible.


  • Gardez le moins de colonnes possible

    Votre table doit contenir uniquement les champs activement utilisés et stocker toutes les autres données dans une table séparée, en conservant uniquement l'ID de la ligne concernée. Cette approche vous permet d'accéder à tous les champs inutilisés en cas de besoin, par exemple à des fins de reporting, sans surcharger la table principale avec ces données.


  • Gardez le moins de lignes possible

    Ne stockez pas les lignes dont vous n'avez plus besoin. Au lieu de cela, déplacez-les vers la table d'archive. Cette approche permet à vos requêtes de trouver plus rapidement les lignes requises tout en préservant toutes les données historiques dans une archive. L'automatisation de ce processus avec un travail simple minimise votre implication dans l'archivage des données.


  • Gardez les index à jour

    N'oubliez pas de créer des index. Les index sont cruciaux pour les recherches rapides de données et sont souvent négligés par les programmeurs. Une indexation appropriée peut réduire considérablement les temps de recherche et la consommation de mémoire de votre base de données. Assurez-vous de créer des index pour les conditions et les colonnes impliquées dans les jointures, y compris les index composites.


  • Abandonnez l'utilisation de clés étrangères

    L'utilisation de clés étrangères impose une charge supplémentaire à la base de données pour garantir que la clé existe dans la table associée, ce qui ralentit les opérations sur les données, notamment lors de l'écriture des données. Ne vous méprenez pas ; stocker une clé étrangère dans une telle table est possible et parfois même nécessaire, mais il est préférable de stocker la clé simplement sous forme de valeur simple.


Ces méthodes simples vous permettront de maximiser l’efficacité et l’utilité de votre table.


Définir des données chaudes

Les Warm Data sont des données utilisées pour préparer une réponse, même si leur pertinence n’a pas d’impact critique. Les exemples incluent des descriptions de produits ou une liste d’accessoires disponibles. Lors du stockage de ces données, il n'est plus nécessaire de surveiller de près la taille de la table. Il ne faut cependant pas négliger la création d’index sur ces tables, car ils sont fréquemment utilisés pour les jointures.


  • Mettre en cache les données chaudes

    Un avantage clé de Warm Data est sa possibilité de mise en cache. Une fois la demande effectuée, vous pouvez stocker les données en mémoire, réduisant ainsi le nombre d'appels à la base de données et accélérant les calculs. N’oubliez cependant pas que le cache nécessite des mises à jour régulières.


  • Définir un TTL (Time To Live) raisonnable

    Réglez la durée de vie (TTL) correcte pour un fonctionnement correct. Habituellement, un TTL d’environ 90 secondes est suffisant, ce qui correspond au temps moyen nécessaire à un utilisateur pour prendre une décision et passer une commande sur un site Web. Ajustez toujours la durée de vie en fonction des exigences de votre service.


  • Utilisez des classes plus petites pour stocker les données chaudes

    Pour la mise en cache, utilisez des classes compactes. Même lorsque des requêtes complètes sont effectuées et que toutes les données des tables sont collectées, évitez de tout stocker dans le cache. Stockez uniquement les données nécessaires. Cette approche réduit considérablement la consommation de mémoire de votre service backend.


La configuration de Warm Data ne prendra pas beaucoup de temps et, à terme, vous obtiendrez des résultats tangibles.


Définir les données froides

Les données froides font référence à des données qui changent rarement mais qui sont nécessaires pour une réponse. Des exemples de telles données incluent le nom ou l’adresse d’un magasin. Ces données évoluent très rarement et ont un impact minime sur la pertinence de la réponse.


  • Mettre en cache les données froides ou les stocker dans un fichier

    Ce type de données doit toujours être mis en cache. S'il n'est pas possible de mettre ces données en mémoire en raison de leur grande taille, envisagez de les décharger de la base de données et de les stocker dans des fichiers dans un format prêt à l'emploi. Le diviser en catégories et sélectionner uniquement les plus fréquemment utilisées contribuera à réduire l’utilisation de la mémoire. De plus, cette approche améliore sensiblement la vitesse par rapport à la récupération des données de la base de données, car elle élimine le besoin de travailler sur le réseau.


  • Mettre à jour le cache lors du déclenchement

    La durée de vie (TTL) d'un tel cache est généralement fixée à 24 heures. Pour maintenir le cache à jour, vous devez planifier une tâche ou créer un déclencheur qui surveille les modifications apportées à ces données et lance une mise à jour du cache. Par exemple, si un point de terminaison est appelé pour publier ou mettre à jour des données froides, un déclencheur doit être activé pour mettre à jour le cache.


La gestion efficace des données froides constitue également un élément important de l’optimisation de l’efficacité des réponses, améliorant ainsi les performances globales du système.


Conclusion

En conclusion, l’optimisation du backend d’un service web ne repose pas uniquement sur l’optimisation du code et des algorithmes. L'amélioration des interactions avec les bases de données entraînera une plus grande efficacité et des performances globales du service. La mise en œuvre de techniques telles que le réglage fin des requêtes ORM (Object-Relational Mapping), l'utilisation de classes de données plates, la définition précise des types de données et l'adoption de stratégies de mise en cache peuvent améliorer considérablement les performances du service. Grâce à ces mesures, le service Web obtiendra à terme une efficacité, une réactivité et une fonctionnalité globale améliorées.


Étapes clés :

  1. Optimisez les requêtes de base de données et évitez de vous fier uniquement aux implémentations ORM.
  2. Utilisez des classes plates pour réduire l’utilisation de la mémoire et augmenter la vitesse des réponses.
  3. Définissez les types de données en les classant comme chaudes, tièdes ou froides.
  4. Utilisez des stratégies spécifiques adaptées à chaque type de données défini.