Effiziente Aktualisierung der Datenbank mit SQLAlchemy ORM
Fange ich eine neue Anwendung und suchen bei Verwendung eines ORM-insbesondere, SQLAlchemy.
Sagen, ich habe eine Spalte 'foo' in meiner Datenbank und ich möchte zu erhöhen. In geraden sqlite, das ist einfach:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
Ich herausgefunden, das SQLAlchemy SQL-builder äquivalent:
engine = sqlalchemy.create_engine('sqlite:///mydata.sqlitedb')
md = sqlalchemy.MetaData(engine)
table = sqlalchemy.Table('stuff', md, autoload=True)
upd = table.update(values={table.c.foo:table.c.foo+1})
engine.execute(upd)
Dieser ist etwas langsamer, aber es gibt nicht viel in ihm.
Hier ist meine beste Vermutung für eine SQLAlchemy ORM-Ansatz:
# snip definition of Stuff class made using declarative_base
# snip creation of session object
for c in session.query(Stuff):
c.foo = c.foo + 1
session.flush()
session.commit()
Dieser macht das richtige, aber es dauert nur weniger als fünfzig mal so lange wie die anderen beiden Ansätze. Ich vermute, dass es ist, weil es hat um die Daten in den Speicher, bevor Sie mit Ihr arbeiten können.
Gibt es eine Möglichkeit zu erzeugen, die effiziente SQL-Verwendung von SQLAlchemy ist ORM? Oder mit einer anderen python ORM? Oder sollte ich gehen Sie einfach zurück zu dem schreiben der SQL von hand?
Es wurden einige Experimente laufen auf verschiedenen ORMs und wie Sie durchführen unter Last und Zwang. Nicht über einen link griffbereit, aber lesenswert.
Ein weiteres problem mit dem letzten (ORM) Beispiel ist, dass es nicht atomic.
InformationsquelleAutor John Fouhy | 2008-11-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
SQLAlchemy ist ORM sollte verwendet werden, zusammen mit der SQL-Schicht, nicht verbergen. Aber Sie haben zu halten, ein oder zwei Dinge Bedenken, wenn Sie mit dem ORM und plain-SQL in der gleichen Transaktion. Im Grunde genommen, von einer Seite, ORM-Daten, werden die änderungen nur Treffer auf die Datenbank, wenn Sie Spülen Sie die änderungen aus Ihrer Sitzung. Von der anderen Seite, (SQL data manipulation statements-keine Auswirkungen auf die Objekte in Ihrer session.
Also, wenn Sie sagen,
wird es tun, was es sagt, geh und hol alle Objekte aus der Datenbank ändern, werden alle Objekte und dann, wenn es ist Zeit, Spülen Sie die änderungen an der Datenbank, aktualisieren Sie die Zeilen eins nach dem anderen.
Stattdessen sollten Sie tun:
Dies wird ausgeführt, wie eine Abfrage wie man es erwarten würde, und weil wenigstens die default-session-Konfiguration abläuft, werden alle Daten der Sitzung auf Begehen Sie keine veralteten Daten Fragen.
In der fast-veröffentlicht 0.5-Reihe konnte man auch mit dieser Methode für die Aktualisierung:
Wird im Grunde führen die gleiche SQL-Anweisung wie das Vorherige snippet, sondern auch wählen Sie die geänderten Zeilen und verfallen alle veralteten Daten in der session. Wenn Sie wissen, dass Sie nicht mit jedem session-Daten nach dem update könnte man auch hinzufügen, synchronize_session=False in der update-Anweisung und loszuwerden, die Sie wählen.
InformationsquelleAutor Ants Aasma
Versuchen =)
Vielen Dank, dieser Ansatz für mich gearbeitet. Es ist wirklich schlimm, dass sqlachemy nicht einen kürzeren Weg zum aktualisieren der
json
SpalteFür diejenigen, die noch mit performance-Problemen wenn Sie diese Methode verwenden: standardmäßig ist diese tun könnten, ein WÄHLEN Sie für jeden Datensatz zuerst, und erst danach UPDATE. Vorbei synchronize_session=False in der update () - Methode verhindert, dass dies geschieht, aber stellen Sie sicher, tun Sie dies nur, wenn Sie nicht verwenden Sie die Objekte aus, die Sie aktualisieren, erneut, bevor Sie die commit().
InformationsquelleAutor Vin
Es gibt mehrere Möglichkeiten, das UPDATE mit sqlalchemy
InformationsquelleAutor Nima Soroush
Hier ist ein Beispiel, wie man dasselbe problem zu lösen, ohne zu müssen, ordnen Sie die Felder manuell:
So ein update-Media-Instanz, die Sie tun können, so etwas wie dieses:
InformationsquelleAutor plowman
Withough testen, ich würde versuchen:
(IIRC, commit() funktioniert das auch ohne flush()).
Habe ich gefunden, dass manchmal eine große Abfrage und dann die Iteration in python kann bis zu 2 Größenordnungen schneller als viele Anfragen. Ich gehe davon aus, dass die Iteration über den query-Objekt ist weniger effizient als die der Iteration über eine Liste generiert, die alle () - Methode des query-Objekts.
[Bitte beachten Sie Kommentar unten - dies nicht Geschwindigkeit Dinge bis in alle].
InformationsquelleAutor Matthew Schinckel
Wenn es ist, weil der Mehraufwand in Bezug auf die Erstellung von Objekten, dann ist es wahrscheinlich nicht beschleunigt werden überhaupt mit SA.
Wenn es ist, weil es be-up im Zusammenhang Objekte, dann könnten Sie in der Lage sein, etwas zu tun mit lazy loading. Sind es zu viele Objekte erstellt werden durch Verweise? (IE, Unternehmen Objekt bekommt auch alle verwandten Menschen-Objekte).
Es ist ein overhead durch das erstellen von Objekten, ist aber meiner Meinung nach lohnt sich die Strafe - in der Lage zu persistieren von Objekten in einer Datenbank ist genial.
InformationsquelleAutor Matthew Schinckel