Maison > développement back-end > Tutoriel Python > Rechercher et corriger les nueries dans Django à l'aide d'AppSignal

Rechercher et corriger les nueries dans Django à l'aide d'AppSignal

DDD
Libérer: 2024-12-22 21:10:39
original
782 Les gens l'ont consulté

Dans cet article, vous découvrirez les requêtes N 1, comment les détecter avec AppSignal et comment les corriger pour accélérer considérablement vos applications Django.

Nous commencerons par les aspects théoriques puis passerons aux exemples pratiques. Les exemples pratiques refléteront des scénarios que vous pourriez rencontrer dans un environnement de production.

Commençons !

Que sont les requêtes N 1 ?

Le problème de requête N 1 est un problème de performances répandu dans les applications Web qui interagissent avec une base de données. Ces requêtes peuvent provoquer des goulots d'étranglement importants, qui s'intensifient à mesure que votre base de données se développe.

Le problème se produit lorsque vous récupérez une collection d'objets, puis accédez aux objets associés pour chaque élément de la collection. Par exemple, récupérer une liste de livres nécessite une seule requête (1 requête), mais accéder à l'auteur pour chaque livre déclenche une requête supplémentaire pour chaque élément (N requêtes).

Les problèmes N 1 peuvent également survenir lors de la création ou de la mise à jour de données dans une base de données. Par exemple, parcourir une boucle pour créer ou mettre à jour des objets individuellement, plutôt que d'utiliser des méthodes telles que Bulk_create() ou Bulk_update(), peut entraîner des requêtes excessives.

Les requêtes N 1 sont très inefficaces, car l'exécution de nombreuses petites requêtes est nettement plus lente et plus gourmande en ressources que la consolidation des opérations en moins de requêtes plus volumineuses.

Le comportement QuerySet par défaut de Django peut entraîner par inadvertance des problèmes N 1, surtout si vous ne savez pas comment fonctionnent les QuerySets. Les ensembles de requêtes dans Django sont paresseux, ce qui signifie qu'aucune requête de base de données n'est exécutée tant que le QuerySet n'est pas évalué.

Conditions préalables

Assurez-vous d'avoir :

  • Python 3.9 et Git installés sur votre machine locale
  • Un système d'exploitation pris en charge par AppSignal
  • Un compte AppSignal

Remarque : Le code source de ce projet se trouve dans le référentiel GitHub appsignal-django-n-plus-one.

Configuration du projet

Nous travaillerons avec une application Web de gestion de livres. L'application Web est conçue pour démontrer le problème de requête N 1 et comment le résoudre.

Commencez par cloner la branche de base du dépôt GitHub :

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ensuite, créez et activez un environnement virtuel :

$ python3 -m venv venv && source venv/bin/activate
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Installez la configuration requise :

(venv)$ pip install -r requirements.txt
Copier après la connexion
Copier après la connexion
Copier après la connexion

Migrer et remplir la base de données :

(venv)$ python manage.py migrate
(venv)$ python manage.py populate_db
Copier après la connexion
Copier après la connexion

Enfin, démarrez le serveur de développement :

(venv)$ python manage.py runserver
Copier après la connexion

Ouvrez votre navigateur Web préféré et accédez à http://localhost:8000/books. L'application Web doit renvoyer une liste JSON de 500 livres de la base de données.

Le site d'administration de Django est accessible à http://localhost:8000/admin. Les informations d'identification de l'administrateur sont :

user: username
pass: password
Copier après la connexion

Installer AppSignal pour Django

Pour installer AppSignal sur votre projet Django, suivez la documentation officielle :

  • Installation d'AppSignal Python
  • Instrumentation AppSignal Django
  • Instrumentation AppSignal SQLite

Assurez-vous que tout fonctionne en redémarrant le serveur de développement :

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Votre application devrait automatiquement envoyer une erreur de démonstration à AppSignal. À partir de ce moment, toutes vos erreurs seront envoyées à AppSignal. De plus, AppSignal surveillera les performances de votre application et détectera tout problème.

Logique d'application Web

La condition préalable à la résolution des requêtes N 1 est de comprendre le schéma de base de données de votre application. Portez une attention particulière aux relations de vos modèles : ils peuvent vous aider à identifier les problèmes potentiels N1.

Modèles

L'application Web comporte deux modèles : Auteur et Livre - qui partagent une relation un-à-plusieurs (1:M). Cela signifie que chaque livre est associé à un seul auteur, tandis qu'un auteur peut être lié à plusieurs livres.

Les deux modèles ont une méthode to_dict() pour sérialiser les instances de modèle en JSON. De plus, le modèle Book utilise une sérialisation approfondie (sérialisant le livre ainsi que l'auteur du livre).

Les modèles sont définis dans books/models.py :

$ python3 -m venv venv && source venv/bin/activate
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ils sont ensuite inscrits sur le site d'administration de Django dans books/admin.py, comme ceci :

(venv)$ pip install -r requirements.txt
Copier après la connexion
Copier après la connexion
Copier après la connexion

Notez qu'AuthorAdmin utilise BookInline pour afficher les livres de l'auteur dans la page d'administration de l'auteur.

Vues

L'application Web fournit les points de terminaison suivants :

  1. /books/ renvoie la liste des livres
  2. /books// renvoie un livre spécifique
  3. /books/by-authors/ renvoie une liste de livres regroupés par auteurs
  4. /books/authors/ renvoie la liste des auteurs
  5. /books/authors// renvoie un auteur spécifique

Les liens ci-dessus sont cliquables si le serveur Web de développement est en cours d'exécution.

Et ils sont définis dans books/views.py comme ceci :

(venv)$ python manage.py migrate
(venv)$ python manage.py populate_db
Copier après la connexion
Copier après la connexion

Super, vous savez maintenant comment fonctionne l'application web !

Dans la section suivante, nous comparerons notre application pour détecter les requêtes N 1 avec AppSignal, puis modifierons le code pour les éliminer.

Détectez les requêtes N 1 dans votre application Django avec AppSignal

La détection des problèmes de performances avec AppSignal est simple. Tout ce que vous avez à faire est d'utiliser/tester l'application comme vous le feriez normalement (par exemple, effectuer des tests auprès des utilisateurs finaux en visitant tous les points de terminaison et en validant les réponses).

Lorsqu'un point de terminaison est atteint, AppSignal crée un rapport de performances pour celui-ci et regroupe toutes les visites associées. Chaque visite sera enregistrée sous forme d'échantillon dans le rapport du point final.

Détecter les requêtes N 1 dans les vues

Tout d'abord, visitez tous les points de terminaison de votre application pour générer les rapports de performances :

  1. /livres/
  2. /books//
  3. /livres/par-auteurs/
  4. /livres/auteurs/
  5. /books/authors//

Ensuite, utilisons le tableau de bord AppSignal pour analyser les points de terminaison lents.

Exemple 1 : relation un-à-un (select_rated())

Accédez à votre application AppSignal et sélectionnez Performances > Liste des problèmes dans la barre latérale. Cliquez ensuite sur Moyen pour trier les problèmes par temps de réponse moyen décroissant.

Find and Fix N ueries in Django Using AppSignal

Cliquez sur le point de terminaison le plus lent (books/) pour afficher ses détails.

Find and Fix N ueries in Django Using AppSignal

En regardant le dernier échantillon, nous pouvons voir que ce point de terminaison renvoie une réponse en 1 090 millisecondes. La répartition des groupes montre que SQLite prend 651 millisecondes tandis que Django en prend 439.

Cela indique un problème car un point de terminaison aussi simple que celui-ci ne devrait pas prendre autant de temps.

Pour obtenir plus de détails sur ce qui s'est passé, sélectionnez Échantillons dans la barre latérale, puis le dernier échantillon.

Find and Fix N ueries in Django Using AppSignal

Faites défiler jusqu'à la Chronologie des événements pour voir quelles requêtes SQL ont été exécutées.

Find and Fix N ueries in Django Using AppSignal

Le survol du texte query.sql affiche la requête SQL réelle.

Plus de 1000 requêtes ont été exécutées :

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

C'est un signe clair des requêtes N 1. La première requête a récupéré un livre (1), et chaque requête suivante a récupéré les détails de l'auteur du livre (N).

Pour résoudre ce problème, accédez à books/views.py et modifiez book_list_view() comme ceci :

$ python3 -m venv venv && source venv/bin/activate
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

En utilisant la méthode select_rated() de Django, nous sélectionnons les données d'objet associées supplémentaires (c'est-à-dire l'auteur) dans la requête initiale. L'ORM exploitera désormais une jointure SQL et la requête finale ressemblera à ceci :

(venv)$ pip install -r requirements.txt
Copier après la connexion
Copier après la connexion
Copier après la connexion

Attendez que le serveur de développement redémarre et testez à nouveau le point de terminaison concerné.

Find and Fix N ueries in Django Using AppSignal

Après une nouvelle analyse comparative, le temps de réponse passe de 1090 à 45 et le nombre de requêtes diminue de 1024 à 2. Il s'agit d'une amélioration de 24x et 512x, respectivement.

Exemple 2 : relation plusieurs-à-un (prefetch_rated())

Ensuite, regardons le deuxième point de terminaison le plus lent (livres/par-auteurs/).

Utilisez le tableau de bord comme nous l'avons fait à l'étape précédente pour inspecter les requêtes SQL du point de terminaison. Vous remarquerez un modèle N 1 similaire mais moins sévère avec ce point final.

Les performances de ce point de terminaison sont moins sévères car Django est suffisamment intelligent pour mettre en cache les requêtes SQL fréquemment exécutées, c'est-à-dire récupérer à plusieurs reprises l'auteur d'un livre. Consultez la documentation officielle pour en savoir plus sur la mise en cache Django.

Utilisons prefetch_rated() dans books/views.py pour accélérer le point de terminaison :

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans la section précédente, nous avons utilisé la méthode select_rated() pour gérer une relation un-à-un (chaque livre a un seul auteur). Cependant, dans ce cas, nous gérons une relation un-à-plusieurs (un auteur peut avoir plusieurs livres), nous devons donc utiliser prefetch_rated().

La différence entre ces deux méthodes est que select_rated() fonctionne au niveau SQL, tandis que prefetch_rated() optimise au niveau Python. Cette dernière méthode peut également être utilisée pour les relations plusieurs-à-plusieurs.

Pour plus d'informations, consultez la documentation officielle de Django sur prefetch_rated().

Après benchmarking, le temps de réponse passe de 90 à 44 millisecondes, et le nombre de requêtes diminue de 32 à 4.

Détecter les requêtes N 1 dans Django Admin

La découverte des requêtes N 1 dans le site d'administration de Django fonctionne de la même manière.

Tout d'abord, connectez-vous à votre site d'administration et générez des rapports de performances (par exemple, créez quelques auteurs ou livres, mettez-les à jour et supprimez-les).

Ensuite, accédez au tableau de bord de votre application AppSignal, en filtrant cette fois les problèmes par administrateur :

Find and Fix N ueries in Django Using AppSignal

Dans mon cas, les deux points de terminaison les plus lents sont :

  1. /admin/connexion
  2. /admin/books/author/

Nous ne pouvons pas faire grand-chose avec /admin/login, puisqu'il est entièrement géré par Django, alors concentrons-nous sur le deuxième point de terminaison le plus lent. L'inspecter révélera un problème de requête N 1. L'auteur est récupéré séparément pour chaque livre.

Pour résoudre ce problème, remplacez get_queryset() dans BookInline pour récupérer les détails de l'auteur dans la requête initiale :

$ python3 -m venv venv && source venv/bin/activate
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Analysez à nouveau et vérifiez que le nombre de requêtes a diminué.

Conclusion

Dans cet article, nous avons discuté de la détection et de la correction des requêtes N 1 dans Django à l'aide d'AppSignal.

Tirer parti de ce que vous avez appris ici peut vous aider à accélérer considérablement vos applications Web Django.

Les deux méthodes les plus essentielles à garder à l'esprit sont select_rated() et prefetch_rated(). Le premier est utilisé pour les relations un-à-un, et le second pour les relations un-à-plusieurs et plusieurs-à-plusieurs.

Bon codage !

P.S. Si vous souhaitez lire les articles Python dès leur sortie de presse, abonnez-vous à notre newsletter Python Wizardry et ne manquez jamais un seul article !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal