Question

J'ai construit des applications django pour un certain temps maintenant, et boire la fraîcheur secours et tous: en utilisant uniquement les ORM et ne jamais écrire SQL personnalisée

.

La page principale du site (la principale interface où les utilisateurs passent 80% - 90% de leur temps) a été obtenir lent une fois que vous avez une grande quantité de contenu spécifique de l'utilisateur (à savoir des photos, des amis, d'autres données, etc.)

Je sauté dans l'enregistreur sql (était pré-installé avec pinax, je ne l'active dans les paramètres) et imaginez ma surprise quand il a rapporté plus de 500 requêtes de base de données !! Avec sql code à la main, je presque jamais couru plus de 50 pages les plus complexes.

Avec le recul, il est pas tout ensemble surprenant, mais il semble que cela ne peut pas être bon.

... même si seulement une douzaine de requêtes prennent 1ms +

Je me demande, combien les frais généraux est là sur un aller-retour à mysql ? django et MySQL sont en cours d'exécution sur le même serveur donc il ne devrait pas y avoir de frais généraux liés à la mise en réseau.

Était-ce utile?

La solution

Il y a des façons de réduire le volume de requêtes.

  1. Utilisez .filter() et .all() pour obtenir un tas de choses; choisir dans la fonction d'affichage (ou modèle via {%if%}). Python peut traiter un lot de lignes plus rapide que MySQL.

    « Mais je pourrais envoyer trop au modèle ». Certes, mais vous exécutez moins de requêtes SQL. Mesurer pour voir ce qui est mieux.

    est ce que vous avez utilisé pour faire lorsque vous avez écrit SQL. Ce n'est pas mal - il ne casse pas la ORM -. Mais il optimise le travail de base de données sous-jacente et met le traitement dans la fonction d'affichage et le modèle

  2. Contournez la navigation de requête dans le modèle. Lorsque vous faites {{foo.bar.baz.quux}}, SQL est utilisé pour obtenir le bar associé à foo, le baz associé au bar, le quux associé à baz. Vous pourriez être en mesure de réduire cette activité de recherche avec quelques .filter() soin et de traitement Python pour assembler un tuple utile dans la fonction de la vue.

    Encore une fois, ce fut quelque chose que vous l'habitude de faire quand vous réalisé à la main SQL. Dans ce cas, vous recueillez plus gros lots d'objets gérés ORM-dans la fonction de vue et de faire votre filtrage en Python plutôt que par un grand nombre de demandes individuelles ORM.

    Cela ne rompt pas l'ORM. Il change le profil d'utilisation de beaucoup de petites requêtes à quelques grandes requêtes.

Autres conseils

Juste parce que vous utilisez un ORM ne signifie pas que vous ne devriez pas faire l'optimisation des performances.

J'ai eu - comme vous - une page d'accueil d'un de mes applications qui ont eu un faible rendement. J'ai vu que je faisais des centaines de requêtes pour afficher cette page. Je suis allé chercher mon code et réalisé que, avec une utilisation prudente des select_related() mes requêtes apporteraient plus des données que je avais besoin -. Je suis passé de centaines de requêtes à des dizaines

Vous pouvez également exécuter un profileur SQL et voir s'il n'y a pas d'indices qui pourraient aider vos requêtes les plus courantes - vous le savez, des trucs de base de données standard

.

est aussi votre Caching ami, je pense. Si beaucoup d'une page ne change pas, avez-vous besoin d'interroger chaque fois que la base de données?

Si tout le reste échoue, rappelez-vous: l'ORM est grande, et oui - vous devriez essayer de l'utiliser car il est la philosophie Django; mais vous n'êtes pas marié à elle .

Si vous avez vraiment un usecase où l'étude et la mise au point de navigation ORM n'a pas aidé, si vous êtes sûr que vous pourriez faire beaucoup mieux avec une requête standard. Utiliser sql brut pour ce cas

Les frais généraux de chaque requêtes est seulement une partie de l'image. Le temps de retour réelle entre vos serveurs Django et Mysql est probablement très faible, car la plupart de vos questions reviennent en moins d'une milliseconde. Le plus gros problème est que le nombre de requêtes envoyées à votre base de données peut submerger rapidement. 500 requêtes pour une page est bien trop cher, même 50 semble beaucoup pour moi. Si dix utilisateurs d'afficher des pages complexes, vous êtes maintenant jusqu'à 5000 requêtes.

Le temps de retour au serveur de base de données est plus un facteur lorsque l'appelant accède à la base de données à partir d'un réseau étendu, où les allers-retours peuvent être facilement entre 20ms et 100ms.

Je regarderais certainement en utilisant une sorte de mise en cache.

Il y a toujours en tête dans les appels de base de données, dans votre cas les frais généraux ne sont pas mauvais parce que l'application et la base de données sont sur la même machine donc il n'y a pas de temps de latence du réseau, mais il y a encore un coût important .

Lorsque vous effectuez une requête à la base de données, il doit se préparer à servir cette demande en faisant un certain nombre de choses, y compris:

  • Allouer des ressources (tampons de mémoire, tables temporaires, etc.) à la connexion au serveur de base de données / thread qui traitera la demande,
  • De-sérialisation sql et les paramètres (cela est nécessaire, même sur une machine, car cela est une demande inter-processus, sauf si vous utilisez une base de données embeded)
  • Vérifier si la requête existe dans le cache de requête si ce ne l'optimiser et de le mettre dans le cache.
    • Notez également que si vos requêtes ne sont pas paramétrées (ce sont les valeurs ne sont pas séparées de SQL), cela peut entraîner des erreurs de cache pour les déclarations qui devraient être le même sens que chaque demande résulte de la requête en cours d'analyse et d'optimiser chaque temps.
  • Processus de la requête.
  • Préparer et retourner les résultats au client.

Ceci est juste un aperçu des types de choses les plus systèmes de gestion de bases de données font pour traiter une requête SQL. Vous encourez cette 500 fois en tête même si la requête elle-même est relativement rapide. interactions de base de données de ligne de fond, même à la base de données locale ne sont pas aussi pas cher que vous pourriez vous attendre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top