PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Warum verbraucht das Durchlaufen eines großen Django-Abfragesatzes enorme Mengen an Arbeitsspeicher?

Nate C war nah dran, aber nicht ganz.

Aus der Dokumentation:

Sie können ein QuerySet auf folgende Weise auswerten:

  • Wiederholung. Ein QuerySet ist iterierbar und führt seine Datenbankabfrage aus, wenn Sie es zum ersten Mal durchlaufen. Dies wird zum Beispiel die Überschrift aller Einträge in der Datenbank drucken:

    for e in Entry.objects.all():
        print e.headline
    

Ihre zehn Millionen Zeilen werden also auf einmal abgerufen, wenn Sie zum ersten Mal in diese Schleife eintreten und die iterative Form des Abfragesatzes erhalten. Die Wartezeit, die Sie erleben, besteht darin, dass Django die Datenbankzeilen lädt und Objekte für jede Zeile erstellt, bevor etwas zurückgegeben wird, über das Sie tatsächlich iterieren können. Dann haben Sie alles im Gedächtnis und die Ergebnisse sprudeln heraus.

Aus meiner Lektüre der Dokumentation, iterator() tut nichts anderes, als die internen Caching-Mechanismen von QuerySet zu umgehen. Ich denke, es könnte sinnvoll sein, eins nach dem anderen zu tun, aber das würde umgekehrt zehn Millionen einzelne Treffer in Ihrer Datenbank erfordern. Vielleicht nicht so wünschenswert.

Das effiziente Iterieren über große Datasets ist etwas, das wir noch nicht ganz richtig verstanden haben, aber es gibt einige Snippets, die Sie für Ihre Zwecke nützlich finden könnten:

  • Speichereffizienter Django QuerySet-Iterator
  • Batch-Abfragesätze
  • QuerySet Foreach