2010-11-23 6 views
1

Ich habe eine Django App, die Django-Kolben verwendet, um XML-Feeds an interne Clients zu senden. Im Allgemeinen funktionieren diese ziemlich gut, aber wir haben einige XML-Feeds, die derzeit über 15 Minuten lang laufen. Dies verursacht Timeouts und die Feeds werden unzuverlässig.Django ORM: Organisieren große Mengen von Daten, der richtige Weg

Ich versuche zu überlegen, wie ich dieses Setup verbessern kann. Wenn es eine Umstrukturierung der Daten erfordert, könnte das auch möglich sein.

Hier ist, wie die Datensammlung zur Zeit aussieht:

class Data(models.Model) 
    # fields 

class MetadataItem(models.Model) 
    data = models.ForeignKey(Data) 

# handlers.py 
data = Data.objects.filter(**kwargs) 

for d in data: 
    for metaitem in d.metadataitem_set.all(): 
     # There is usually anywhere between 55 - 95 entries in this loop 
     label = metaitem.get_label() # does some formatting here 
     data_metadata[label] = metaitem.body 

Offensichtlich ist der Kern des Programms viel mehr tut, aber ich bin nur darauf hin, wo das Problem liegt. Wenn wir eine data Liste von 300 haben, wird es einfach unzuverlässig und überschreitet die Zeit.

Was ich versucht habe:

  • Immer eine Sammlung aller Daten-IDs, dann eine einzige große Abfrage tun, um die s MetadataItem‘alles zu bekommen. Schließlich filtere ich diese in meiner Schleife. Dies war, um einige Abfragen zu erhalten, die es reduziert hat.
  • Verwenden Sie .values(), um den Modellinstanz-Overhead zu reduzieren, der die Geschwindigkeit jedoch nicht wesentlich erhöht hat.

Eine Idee ich eine einfachere Lösung für dieses Problem zu denken ist an einen Cache in Schritten zu schreiben. Also um die Zeit zu verkürzen; Ich würde die ersten 50 Datensätze schreiben, im Cache speichern, einen Zähler einstellen, die nächsten 50 schreiben, usw. Muss noch darüber nachdenken.

Ich hoffe, jemand kann helfen, mich in die richtige Richtung zu führen.

+0

haben Sie die Möglichkeit, Ihre Daten neu zu strukturieren, sodass Sie keine Unterabfragen ausführen müssen? – Evgeny

Antwort

2

Das Problem in dem Codeabschnitt, den Sie gepostet haben, ist, dass Django keine Objekte enthält, die über eine umgekehrte Beziehung automatisch verbunden sind. Daher müssen Sie für jedes Objekt eine Abfrage erstellen. Es gibt einen schönen Weg, wie Daniel Roseman points out in his blog!

Wenn dies nicht Ihr Problem auch nicht löst, können Sie auch einen Blick auf die versuchen, alles in einer rohen SQL-Abfrage zu bekommen ...

+0

Das ist, was ich gesucht habe. Reduziert meine Anfragen von n + 1 auf ... 3 :) Danke – Bartek

1

Sie könnten die Anzahl der Abfragen möglicherweise weiter reduzieren, indem Sie zuerst alle Daten-IDs abrufen und dann select_related verwenden, um die Daten und ihre Metadaten in einer einzigen großen Abfrage abzurufen. Dies würde die Anzahl der Abfragen stark reduzieren, aber die Größe der Abfragen könnte unpraktisch/zu groß sein. Etwas wie:

Allerdings würde ich vorschlagen, wenn möglich, die Feeds von irgendwo außerhalb des Webservers vorberechnen. Vielleicht könnten Sie das Ergebnis in Memcache speichern, wenn es kleiner als 1 MB ist. Oder Sie könnten einer der coolen neuen Kids im Block sein und das Ergebnis in einer "NoSQL" -Datenbank wie Redis speichern. Oder Sie könnten es einfach in eine Datei auf der Festplatte schreiben.

+0

Danke für die Antwort .. leider habe ich versucht mit 'select_related' in genau der gleichen Weise wie Sie beschrieben mit nicht viel Änderung der Geschwindigkeit. Es gab einige Verbesserungen, aber immer noch eine Katastrophe. – Bartek

+0

Ok. Wie wäre es mit dem Precomputing-Ansatz? Wäre das möglich angesichts Ihrer Einschränkungen? – knutin

+0

Das ist eine Sache, an die ich dachte. z.B. Sellerie aufstellen, um geänderte Futtermittel anzustellen (sie ändern sich täglich leider) und verarbeiten sie. Ich werde das wahrscheinlich sowieso machen, aber wenn Feeds über 30 Minuten laufen und sie mehrmals am Tag gewechselt werden, befürchte ich eine Warteschlangensicherung. – Bartek

0

Wenn Sie die Struktur der Daten ändern können, können Sie vielleicht auch den Datenspeicher ändern?

Die "NoSQL" -Datenbanken, die eine Struktur erlauben, wie CouchDB oder MongoDB, könnten hier nützlich sein.

Sagen wir, für jedes Datenelement haben Sie ein Dokument. Das Dokument würde Ihre normalen Felder haben. Sie würden auch ein "Metadaten" -Feld hinzufügen, das eine Liste von Metadaten ist. Was ist mit der folgenden Datenstruktur:

{ 
    'id': 'someid', 
    'field': 'value', 
    'metadata': [ 
     { 'key': 'value' }, 
     { 'key': 'value' } 
    ] 
} 

Sie wären dann in der Lage, leicht zu einem Datensatz zu gelangen und alle seine Metadaten zu bekommen. Fügen Sie für die Suche den Feldern im Dokument 'data' Indizes hinzu.

Ich habe an einem System in Erlang/OTP gearbeitet, das Mnesia verwendet, das im Grunde eine Schlüssel-Wert-Datenbank mit etwas Indexierung und Helfern ist. Wir haben verschachtelte Datensätze sehr erfolgreich eingesetzt.

Ich fügte dies als eine separate Antwort hinzu, da es völlig anders ist als die anderen.

0

Eine weitere Idee ist Sellerie zu verwenden (www.celeryproject.com) Das ist ein Task-Management-System für Python und Django. Sie können damit lang andauernde Aufgaben asynchron ausführen, ohne den Haupt-App-Server zu blockieren.

Verwandte Themen