schnelle Suche nach dem letzten Element in einem Django QuerySet?

8

Ich habe ein Modell namens Valor. Valor hat einen Roboter. Ich frage so:

%Vor%

um die letzte Valor der r Roboter zu bekommen. Valor.objects.filter (roboter = r) .count () ist etwa 200000 und das Abrufen der letzten Elemente dauert etwa 4 Sekunden in meinem PC.

Wie kann ich es beschleunigen? Ich frage den falschen Weg?

    
Juanjo Conti 05.12.2009, 17:00
quelle

9 Antworten

3

Es klingt, als wäre Ihr Datensatz groß genug, um die Dinge ein wenig zu denormalisieren. Haben Sie versucht, das letzte Valor-Objekt im Robot-Objekt zu verfolgen?

%Vor%

Und dann verwenden Sie eine post_save Signal , um das Update zu machen.

%Vor%

Sie zahlen die Kosten für eine zusätzliche Datenbanktransaktion, wenn Sie die Valor-Objekte erstellen, aber die last_valor-Suche wird blitzschnell ausgeführt. Spielen Sie damit und sehen Sie, ob sich der Kompromiss für Ihre App lohnt.

    
istruble 05.12.2009, 18:01
quelle
7

Wenn keiner der früheren Vorschläge funktioniert, würde ich vorschlagen, Django aus der Gleichung zu nehmen und diesen rohen SQL gegen Ihre Datenbank laufen zu lassen. Ich schätze Ihre Tabellennamen, also müssen Sie möglicherweise entsprechend anpassen:

%Vor%

Ist das langsam? Wenn ja, lassen Sie Ihr RDBMS (MySQL?) Den Abfrageplan für Sie erklären. Dies wird Ihnen sagen, ob es vollständige Tabellen-Scans macht, die Sie offensichtlich nicht mit einer so großen Tabelle wollen. Sie können Ihre Frage auch bearbeiten und das Schema für die Tabelle valor für uns einfügen.

Sie können auch die SQL sehen, die Django auf diese Weise erzeugt (unter Verwendung der von Peter Rowell bereitgestellten Abfrage):

%Vor%

Stellen Sie sicher, dass SQL der oben angegebenen "rohen" Abfrage ähnelt. Sie können Ihrem RDBMS auch diesen Abfrageplan erläutern.

    
Joe Holloway 05.12.2009 17:26
quelle
7

Die optimale mysql-Syntax für dieses Problem wäre etwa wie folgt:

%Vor%

Das Django-Äquivalent wäre:

%Vor%

Beachten Sie, dass diese Lösung die Methode slicing von django verwendet, um das Abfrage-Set zu begrenzen vor Kompilieren der Liste der Objekte.

    
Aaron 30.11.2011 15:15
quelle
3

Nun, es gibt keine order_by-Klausel, also frage ich mich, was Sie mit "last" meinen. Angenommen du meintest 'zuletzt hinzugefügt',

%Vor%

könnte die Arbeit für Sie erledigen.

    
Peter Rowell 05.12.2009 17:08
quelle
2

django 1.6 führt .first () und .last () ein:

Ссылка

So könntest du einfach tun:

%Vor%     
Ollie Cook 16.07.2014 12:00
quelle
1

Ganz schnell sollte auch sein:

%Vor%

In der Praxis führen Sie also nur 2 SQL-Abfragen aus;)

    
JNLK 19.05.2012 08:58
quelle
0

Gibt es eine Limit-Klausel in Django? Auf diese Weise können Sie die db haben, einfach einen einzelnen Datensatz zurückgeben.

mysql

%Vor%

SQL Server

%Vor%

oracle

%Vor%

Ich weiß, dass dies nicht in Django übersetzt wird, aber jemand kann zurückkommen und das aufräumen.

    
Nathan Feger 05.12.2009 17:13
quelle
0

Der richtige Weg, dies zu tun, besteht darin, die eingebaute Methode QuerySet neustart () zu verwenden und sie mit der Spalte (Feldname) zu füllen, nach der sie sortieren soll. Der Nachteil ist, dass es nur nach einer einzelnen db-Spalte sortieren kann.

Die aktuelle Implementierung sieht so aus und ist im selben Sinne optimiert wie @ Aarons Vorschlag.

%Vor%     
benjaoming 12.03.2014 21:56
quelle
0
%Vor%

// Für das erste Element

%Vor%

// Für get last ()

ist in meinem Fall das letzte nicht, weil es nur eine Zeile in der Datenbank gibt kann auch für dich voll sein:)

    
GrvTyagi 09.02.2015 15:00
quelle