Saya memulai aplikasi baru dan melihat menggunakan ORM - khususnya, SQLAlchemy.
Katakanlah saya punya kolom 'foo' di database saya dan saya ingin menambahnya. Di sqlite lurus, ini mudah:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
Saya menemukan persamaan SQLAlchemy SQL-builder:
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)
Ini sedikit lebih lambat, tapi tidak banyak di dalamnya.
Inilah tebakan terbaik saya untuk pendekatan SQLAlchemy ORM:
# 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()
Ini melakukan hal yang benar, tetapi itu membutuhkan waktu kurang dari lima puluh kali selama dua pendekatan lainnya. Saya kira itu karena harus membawa semua data ke dalam memori sebelum dapat bekerja dengannya.
Apakah ada cara untuk menghasilkan SQL yang efisien menggunakan ORM SQLAlchemy? Atau menggunakan ORM python lainnya? Atau haruskah saya kembali menulis SQL dengan tangan?
python
orm
sqlalchemy
John Fouhy
sumber
sumber
Jawaban:
ORM SQLAlchemy dimaksudkan untuk digunakan bersama dengan lapisan SQL, bukan menyembunyikannya. Tetapi Anda harus selalu mengingat satu atau dua hal saat menggunakan ORM dan SQL biasa dalam transaksi yang sama. Pada dasarnya, dari satu sisi, modifikasi data ORM hanya akan masuk ke database saat Anda menghapus perubahan dari sesi Anda. Dari sisi lain, pernyataan manipulasi data SQL tidak memengaruhi objek yang ada di sesi Anda.
Jadi jika Anda berkata
itu akan melakukan apa yang dikatakannya, mengambil semua objek dari database, memodifikasi semua objek dan kemudian ketika saatnya untuk menghapus perubahan ke database, perbarui baris satu per satu.
Sebaliknya Anda harus melakukan ini:
Ini akan dijalankan sebagai satu kueri seperti yang Anda harapkan, dan karena setidaknya konfigurasi sesi default kedaluwarsa semua data dalam sesi saat komit, Anda tidak memiliki masalah data lama.
Dalam seri 0.5 yang hampir dirilis, Anda juga dapat menggunakan metode ini untuk memperbarui:
Itu pada dasarnya akan menjalankan pernyataan SQL yang sama seperti cuplikan sebelumnya, tetapi juga memilih baris yang diubah dan menghentikan data usang apa pun dalam sesi tersebut. Jika Anda tahu Anda tidak menggunakan data sesi apa pun setelah pembaruan, Anda juga dapat menambahkan
synchronize_session=False
ke pernyataan pembaruan dan menghilangkan pilihan itu.sumber
Coba ini =)
sumber
json
kolomAda beberapa cara untuk MEMPERBARUI menggunakan sqlalchemy
sumber
Berikut adalah contoh cara menyelesaikan masalah yang sama tanpa harus memetakan bidang secara manual:
Jadi untuk memperbarui instance Media, Anda dapat melakukan sesuatu seperti ini:
sumber
Dengan pengujian yang cukup, saya akan mencoba:
(IIRC, commit () bekerja tanpa flush ()).
Saya telah menemukan bahwa terkadang melakukan kueri besar dan kemudian melakukan iterasi dengan python bisa mencapai 2 kali lipat lebih cepat daripada banyak kueri. Saya berasumsi bahwa iterasi pada objek query kurang efisien daripada iterasi pada daftar yang dihasilkan oleh metode all () dari objek query.
[Harap perhatikan komentar di bawah - ini tidak mempercepat sama sekali].
sumber
Jika itu karena overhead dalam hal membuat objek, maka itu mungkin tidak bisa dipercepat sama sekali dengan SA.
Jika itu karena memuat objek terkait, maka Anda mungkin dapat melakukan sesuatu dengan pemuatan lambat. Apakah ada banyak objek yang dibuat karena referensi? (Yaitu, mendapatkan objek Perusahaan juga mendapatkan semua objek Orang terkait).
sumber