Ich starte eine neue Anwendung und möchte ein ORM verwenden - insbesondere SQLAlchemy.
Angenommen, ich habe eine Spalte 'foo' in meiner Datenbank und möchte sie erhöhen. In Straight SQLite ist dies einfach:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
Ich habe das SQLAlchemy SQL-Builder-Äquivalent herausgefunden:
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)
Das ist etwas langsamer, aber es ist nicht viel drin.
Hier ist meine beste Vermutung für einen 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()
Dies macht das Richtige, aber es dauert knapp fünfzig Mal so lange wie die beiden anderen Ansätze. Ich nehme an, das liegt daran, dass alle Daten gespeichert werden müssen, bevor sie damit arbeiten können.
Gibt es eine Möglichkeit, das effiziente SQL mit dem ORM von SQLAlchemy zu generieren? Oder mit einem anderen Python-ORM? Oder sollte ich einfach wieder das SQL von Hand schreiben?
quelle
Antworten:
Das ORM von SQLAlchemy soll zusammen mit der SQL-Schicht verwendet und nicht ausgeblendet werden. Sie müssen jedoch ein oder zwei Dinge beachten, wenn Sie ORM und einfaches SQL in derselben Transaktion verwenden. Grundsätzlich wirken sich ORM-Datenänderungen von einer Seite nur dann auf die Datenbank aus, wenn Sie die Änderungen aus Ihrer Sitzung löschen. Auf der anderen Seite wirken sich SQL-Datenmanipulationsanweisungen nicht auf die Objekte in Ihrer Sitzung aus.
Also wenn du sagst
Es wird das tun, was es sagt, alle Objekte aus der Datenbank abrufen, alle Objekte ändern und dann, wenn es Zeit ist, die Änderungen in der Datenbank zu löschen, die Zeilen einzeln aktualisieren.
Stattdessen sollten Sie Folgendes tun:
Dies wird wie erwartet als eine Abfrage ausgeführt. Da mindestens die Standard-Sitzungskonfiguration alle Daten in der Sitzung beim Festschreiben abläuft, treten keine veralteten Datenprobleme auf.
In der fast veröffentlichten 0.5-Serie können Sie diese Methode auch zum Aktualisieren verwenden:
Dadurch wird im Grunde dieselbe SQL-Anweisung wie im vorherigen Snippet ausgeführt, es werden jedoch auch die geänderten Zeilen ausgewählt und veraltete Daten in der Sitzung verfallen. Wenn Sie wissen, dass Sie nach dem Update keine Sitzungsdaten verwenden, können Sie diese auch
synchronize_session=False
zur Update-Anweisung hinzufügen und diese Auswahl entfernen.quelle
Versuchen Sie dies =)
quelle
json
Spalte zu aktualisierenEs gibt verschiedene Möglichkeiten, mit sqlalchemy ein UPDATE durchzuführen
quelle
Hier ist ein Beispiel, wie Sie dasselbe Problem lösen können, ohne die Felder manuell zuordnen zu müssen:
Um eine Medieninstanz zu aktualisieren, können Sie Folgendes tun:
quelle
Ohne Tests würde ich versuchen:
(IIRC, commit () funktioniert ohne flush ()).
Ich habe festgestellt, dass das Ausführen einer großen Abfrage und das anschließende Iterieren in Python manchmal bis zu 2 Größenordnungen schneller sein kann als viele Abfragen. Ich gehe davon aus, dass das Iterieren über das Abfrageobjekt weniger effizient ist als das Iterieren über eine Liste, die mit der all () -Methode des Abfrageobjekts generiert wurde.
[Bitte beachten Sie den Kommentar unten - dies hat die Dinge überhaupt nicht beschleunigt].
quelle
Wenn dies auf den Overhead beim Erstellen von Objekten zurückzuführen ist, kann es mit SA wahrscheinlich überhaupt nicht beschleunigt werden.
Wenn es daran liegt, dass verwandte Objekte geladen werden, können Sie möglicherweise etwas mit verzögertem Laden tun. Werden aufgrund von Referenzen viele Objekte erstellt? (Wenn Sie ein Unternehmensobjekt abrufen, werden auch alle zugehörigen Personenobjekte abgerufen.)
quelle