Présentation des performances

Les performances de base de données sont une rubrique vaste et complexe, couvrant toute une pile de composants : la base de données, la mise en réseau, le pilote de base de données et les couches d’accès aux données telles que EF Core. Bien que les couches de haut niveau et les machines virtuelles telles que EF Core simplifient considérablement le développement d’applications et améliorent la maintenance, elles peuvent parfois être opaques, en masquant les détails internes critiques des performances tels que SQL en cours d’exécution. Cette section tente de fournir une vue d’ensemble de la façon d’obtenir de bonnes performances avec EF Core et d’éviter les pièges courants qui peuvent dégrader les performances des applications.

Identifier les goulots d’étranglement et mesurer, mesurer, mesurer

Comme toujours avec les performances, il est important de ne pas se précipiter dans l’optimisation sans données montrant un problème; comme l’a dit le grand Donald Knuth une fois, « L’optimisation prématurée est la racine de tous les maux ». La section diagnostic des performances décrit différentes façons de comprendre où votre application passe du temps dans la logique de base de données et comment identifier des zones problématiques spécifiques. Une fois qu’une requête lente a été identifiée, les solutions peuvent être prises en compte : votre base de données manque-t-elle un index ? Devez-vous essayer d’autres modèles d’interrogation ?

Référencez toujours votre code et les alternatives possibles vous-même : la section diagnostic des performances contient un exemple de benchmark avec BenchmarkDotNet, que vous pouvez utiliser comme modèle pour vos propres benchmarks. Ne supposez pas que les critères généraux et publics s’appliquent comme suit à votre cas d’usage spécifique; divers facteurs tels que la latence de la base de données, la complexité des requêtes et les quantités de données réelles dans vos tables peuvent avoir un effet profond sur la solution qui convient le mieux. Par exemple, de nombreux benchmarks publics sont effectués dans des conditions réseau idéales, où la latence vers la base de données est presque nulle et avec des requêtes extrêmement légères qui nécessitent peu de traitement (ou d’E/S de disque) côté base de données. Bien qu’elles soient précieuses pour comparer les surcharges d’exécution de différentes couches d’accès aux données, les différences qu’ils révèlent généralement être négligeables dans une application réelle, où la base de données effectue des travaux réels et la latence vers la base de données est un facteur de performance significatif.

Aspects des performances d’accès aux données

Les performances globales de l’accès aux données peuvent être réparties en catégories générales suivantes :

  • Performances de base de données pures. Avec la base de données relationnelle, EF traduit les requêtes LINQ de l’application dans les instructions SQL qui sont exécutées par la base de données ; ces instructions SQL elles-mêmes peuvent s’exécuter plus ou moins efficacement. L’index approprié au bon endroit peut faire une différence dans les performances SQL, ou réécrire votre requête LINQ peut rendre EF générer une meilleure requête SQL.
  • Transfert de données réseau. Comme pour n’importe quel système de mise en réseau, il est important de limiter la quantité de données en cours de retour et de sortie sur le réseau. Cela permet de s’assurer que vous envoyez et chargez uniquement des données dont vous aurez réellement besoin, mais évitez également l’effet « explosion cartessienne » lors du chargement d’entités associées.
  • Allers-retours réseau. Au-delà de la quantité de données sortantes, les allers-retours réseau, car le temps nécessaire à l’exécution d’une requête dans la base de données peut être nain par le temps que les paquets voyagent de nouveau et vers l’avant entre votre application et votre base de données. La surcharge d’aller-retour dépend fortement de votre environnement; plus votre serveur de base de données est plus loin, plus la latence est élevée et le plus coûteux chaque aller-retour. Avec l’avènement du cloud, les applications se retrouvent de plus en plus loin de la base de données et des applications « chatty » qui effectuent trop d’allers-retours rencontrent des performances dégradées. Par conséquent, il est important de comprendre exactement quand votre application contacte la base de données, le nombre d’allers-retours qu’il effectue et si ce nombre peut être réduit.
  • Surcharge du runtime EF. Enfin, EF ajoute une surcharge d’exécution aux opérations de base de données : EF doit compiler vos requêtes à partir de LINQ to SQL (bien que cela ne doit normalement être effectué qu’une seule fois), le suivi des modifications ajoute une surcharge (mais peut être désactivé), etc. En pratique, la surcharge EF pour les applications réelles est susceptible d’être négligeable dans la plupart des cas, car le temps d’exécution des requêtes dans la base de données et la latence réseau dominent le temps total; mais il est important de comprendre ce que sont vos options et comment éviter certains pièges.

Savoir ce qui se passe sous le capot

EF permet aux développeurs de se concentrer sur la logique métier en générant SQL, en matérialisant des résultats et en effectuant d’autres tâches. Comme n’importe quelle couche ou abstraction, elle a également tendance à masquer ce qui se passe sous le capot, comme les requêtes SQL réelles exécutées. Les performances ne sont pas nécessairement un aspect critique de chaque application là-bas, mais dans les applications où il s’agit, il est essentiel que le développeur comprenne ce qu’EF fait pour eux : inspecter les requêtes SQL sortantes, suivez les allers-retours pour vous assurer que le problème N+1 n’est pas survenu, etc.

Cache en dehors de la base de données

Enfin, le moyen le plus efficace d’interagir avec une base de données, c’est de ne pas interagir avec lui. En d’autres termes, si l’accès à la base de données apparaît comme goulot d’étranglement des performances dans votre application, il peut être utile de mettre en cache certains résultats en dehors de la base de données, afin de réduire les demandes. Bien que la mise en cache ajoute une complexité, il s’agit d’une partie particulièrement cruciale de n’importe quelle application évolutive : tandis que le niveau application peut être facilement mis à l’échelle en ajoutant des serveurs supplémentaires pour gérer une charge accrue, la mise à l’échelle du niveau de base de données est généralement beaucoup plus compliquée.