Mysql
 sql >> Datenbank >  >> RDS >> Mysql

speichereffizienter integrierter SqlAlchemy-Iterator/Generator?

Die meisten DBAPI-Implementierungen puffern Zeilen vollständig, wenn sie abgerufen werden. Daher befindet sich normalerweise die gesamte Ergebnismenge im Speicher, bevor das SQLAlchemy-ORM überhaupt ein Ergebnis erhält.

Aber dann der Weg Query funktioniert ist, dass es die angegebene Ergebnismenge standardmäßig vollständig lädt, bevor es Ihnen Ihre Objekte zurückgibt. Die Begründung bezieht sich hier auf Abfragen, die mehr als einfache SELECT-Anweisungen sind. Beispielsweise muss bei Verknüpfungen mit anderen Tabellen, die möglicherweise dieselbe Objektidentität mehrmals in einem Ergebnissatz zurückgeben (häufig bei eifrigem Laden), der vollständige Satz von Zeilen im Arbeitsspeicher vorhanden sein, damit die richtigen Ergebnisse zurückgegeben werden können, andernfalls Sammlungen und dergleichen möglicherweise nur teilweise ausgefüllt.

Also Query bietet eine Option, dieses Verhalten durch yield_per() . Dieser Aufruf löst die Query aus Zeilen in Stapeln zu liefern, wobei Sie ihm die Stapelgröße geben. Wie in der Dokumentation angegeben, ist dies nur angemessen, wenn Sie keine Sammlungen eifrig laden, also im Grunde, wenn Sie wirklich wissen, was Sie tun. Auch wenn die zugrunde liegende DBAPI Zeilen vorpuffert, gibt es immer noch diesen Speicher-Overhead, sodass der Ansatz nur geringfügig besser skaliert, als ihn nicht zu verwenden.

Ich verwende yield_per() kaum; Stattdessen verwende ich eine bessere Version des oben vorgeschlagenen LIMIT-Ansatzes mit Fensterfunktionen. LIMIT und OFFSET haben ein riesiges Problem, dass sehr große OFFSET-Werte dazu führen, dass die Abfrage immer langsamer wird, da ein OFFSET von N dazu führt, dass sie durch N Zeilen blättert - es ist, als würde man dieselbe Abfrage fünfzig Mal statt einmal machen, jedes Mal, wenn a gelesen wird immer mehr Reihen. Mit einem Fensterfunktionsansatz rufe ich vorab eine Reihe von "Fenster"-Werten ab, die sich auf Teile der Tabelle beziehen, die ich auswählen möchte. Ich gebe dann einzelne SELECT-Anweisungen aus, die jeweils aus einem dieser Fenster gleichzeitig abgerufen werden.

Der Fensterfunktionsansatz ist im Wiki und ich verwende es mit großem Erfolg.

Beachten Sie außerdem:Nicht alle Datenbanken unterstützen Fensterfunktionen; Sie benötigen Postgresql, Oracle oder SQL Server. Meiner Meinung nach lohnt es sich auf jeden Fall, mindestens Postgresql zu verwenden - wenn Sie eine relationale Datenbank verwenden, können Sie genauso gut die beste verwenden.