2015-06-30 18 views
5

Ich habe ein Leistungsproblem beim Rendern einer Django-Vorlage mit einem Prefetch-Abfrage-Set, das nicht wirklich groß ist (~ 1000 Objekte in der Produktionsumgebung/~ 200 Objekte in der Entwicklungsumgebung), hat aber mehrere Verschachtelungsebenen. HierDjango Vorlage Rendering-Geschwindigkeit

ist die Prefetch:

stories = Story.objects.select_related(
      'commande', 
      'commande__societe', 
      'commande__plateforme', 
      'client',).prefetch_related(
      Prefetch('crm_message_related', 
        queryset=Message.objects.select_related(
         'societe', 
         'plateforme', 
         'type_message').order_by('-date_received')), 
      Prefetch('commande__crm_feedback_related'), 
      Prefetch('commande__crm_guarantee_related'), 
      Prefetch('commande__soyouz_item_related', 
        queryset=Item.objects.select_related(
         'etat', 'produit', 'produit__produit_enhanced',)), 
      Prefetch('commande__tagged_items__tag'), 
      Prefetch('commande__soyouz_item_related__tagged_items__tag'), 
      Prefetch('commande__soyouz_item_related__soyouz_annulationclient_related'), 
      Prefetch('commande__soyouz_item_related__soyouz_achat_related'), 
      Prefetch('commande__soyouz_item_related__soyouz_achat_related__soyouz_receptionachat_related'), 
      Prefetch('commande__soyouz_item_related__soyouz_achat_related__soyouz_annulationachat_related'), 
      Prefetch('soyouz_action_related'), 
      Prefetch('soyouz_action_related__receptionmessage__message', 
        to_attr='receptionmessages', 
        queryset=Message.objects.order_by(
         '-date_received').select_related(
         'societe', 'type_message', 'plateforme')) 
     ).order_by(
      '-commande__date_commande', 
      '-date_created' 
     ).all().distinct() 

Die SQL laufen reibungslos, das ist nicht das Problem.

Das Problem ist, wenn ich versuche, meine Vorlage Hexe

{% for story in stories %} 
    {% with items=story.commande.soyouz_item_related.all %} 
    {% for item in items %} 
     {% for tag in item.tagged_items.all %} 
      <button>{{ tag.tag }}</button> 
     {% endfor %} 
     {{ item.titre|safe|truncatechars:50 }} 
    {% endfor %} 
{% endfor %} 

Es dauert etwa 10 Sekunden ist basicaly zu machen, die Seite in der Produktionsumgebung angezeigt werden soll.

ich profilierte es in meiner Entwicklungsumgebung mit django-template-Timing (https://github.com/orf/django-debug-toolbar-template-timings) und in der Tat:

name   Times Tot Time Queries Queries Time 
stories.html 1  2814,1 ms 0   0 ms 

3 Sekunden 3 Schleifen mit 200 Daten (in Entwicklungsumgebung)? Es scheint viel zu sein.

Irgendwelche Ideen, um die Geschwindigkeit des Vorlagen-Renderings zu verbessern?

Vielen Dank!

+0

Haben Sie versucht mit 'DEBUG = False'? Djangos Template-Sprache ist nicht für ihre Geschwindigkeit bekannt, aber das scheint übertrieben, und ich glaube nicht, dass For-Loops besonders langsam sind.Nur um sicher zu sein: Redest du über 200 Geschichten, Tags, Gesamtgegenstände? – knbk

+0

in Entwicklung: 200 Geschichten - 1 Artikel pro Geschichte - 0 Tag pro Artikel in prod: 1000 Geschichten - 1 oder 2 Artikel pro Geschichte - 1 Tag pro Artikel – Tigrou

+0

DEBUG = False ist bereits in der Produktionsumgebung – Tigrou

Antwort

0

Verwenden Sie ein benutzerdefiniertes Tag und generieren Sie die Ausgabe außerhalb der Vorlage. Das wird helfen, den Overhead des Django-Templates zu vermeiden.

5

Obwohl django-template-timing die Renderzeit mit 2,8s angibt, vermute ich, dass die meiste Zeit beim Ausführen der komplexen SQL-Abfrage verbraucht wird.

In Django, QuerySets are evaluated lazily. Das heißt, die von Ihnen gepostete Anweisung Story.objects.select_related(...).distinct() führt die Abfrage NICHT in der Datenbank aus. Die SQL wird later ausgeführt. Da Sie vor dem Rendern der Vorlage nicht den gesamten Code gepostet haben, bin ich mir nicht sicher, ob das QuerySet vor dem Rendern ausgewertet wird. Wenn nicht, kann es ausgeführt werden, wenn stories in der Vorlage Iterieren:

{% for story in stories %} 

Wenn dies der Fall ist, dann vielleicht Ihre SQL Verbesserung der Zeit reduzieren kann.

können Sie überprüfen, ob SQL-Ausführung der Schuldige ist dies durch das Einfügen vor der Vorlage Rendering:

stories = [story for story in stories] 

Diese Iteration wird die ausgeführten SQL vor dem Rendern. Wenn django-template-timing eine viel kürzere Renderzeit meldet, wissen Sie, dass SQL das Problem ist.

Wenn es sich tatsächlich um eine schablonen Rendering-Performance-Problem, gibt es einige Alternativen:

  1. Verwenden Sie eine leistungsfähigere Template-Engine, wie Jinja2.
  2. Möglicherweise gibt es Raum für die Verbesserung der Renderleistung mit Django Vorlage: https://stackoverflow.com/a/26592207/954376.
+0

Wir haben die beste Lösung gefunden : jinja + paginieren wenn möglich – chocobn69