Berikut adalah versi SQLAlchemy dari skrip MySQL Anda yang bekerja dalam empat detik, dibandingkan dengan tiga detik untuk MySQLdb:
from sqlalchemy import Integer, Column, create_engine, MetaData, Table
import datetime
metadata = MetaData()
foo = Table(
'foo', metadata,
Column('id', Integer, primary_key=True),
Column('a', Integer(), nullable=False),
Column('b', Integer(), nullable=False),
Column('c', Integer(), nullable=False),
)
class Foo(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
engine = create_engine('mysql+mysqldb://scott:[email protected]/test', echo=True)
start = datetime.datetime.now()
with engine.connect() as conn:
foos = [
Foo(row['a'], row['b'], row['c'])
for row in
conn.execute(foo.select().limit(1000000)).fetchall()
]
print "total time: ", datetime.datetime.now() - start
waktu proses:
total time: 0:00:04.706010
Berikut adalah skrip yang menggunakan ORM untuk memuat baris objek sepenuhnya; dengan menghindari pembuatan daftar tetap dengan semua 1 juta objek sekaligus menggunakan hasil per, ini berjalan dalam 13 detik dengan SQLAlchemy master (18 detik dengan rel 0.9):
import time
from sqlalchemy import Integer, Column, create_engine, Table
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Foo(Base):
__table__ = Table(
'foo', Base.metadata,
Column('id', Integer, primary_key=True),
Column('a', Integer(), nullable=False),
Column('b', Integer(), nullable=False),
Column('c', Integer(), nullable=False),
)
engine = create_engine('mysql+mysqldb://scott:[email protected]/test', echo=True)
sess = Session(engine)
now = time.time()
# avoid using all() so that we don't have the overhead of building
# a large list of full objects in memory
for obj in sess.query(Foo).yield_per(100).limit(1000000):
pass
print("Total time: %d" % (time.time() - now))
Kami kemudian dapat membagi perbedaan antara dua pendekatan ini, dan memuat kolom individual saja dengan ORM:
for obj in sess.query(Foo.id, Foo.a, Foo.b, Foo.c).yield_per(100).limit(1000000):
pass
Di atas kembali berjalan dalam 4 detik .
Perbandingan SQLAlchemy Core adalah perbandingan yang lebih tepat dengan kursor MySQLdb mentah. Jika Anda menggunakan ORM tetapi melakukan kueri untuk masing-masing kolom, itu sekitar empat detik di versi terbaru.
Pada tingkat ORM, masalah kecepatan adalah karena pembuatan objek dengan Python lambat, dan SQLAlchemy ORM menerapkan sejumlah besar pembukuan ke objek ini saat mengambilnya, yang diperlukan untuk memenuhi kontrak penggunaannya, termasuk unit pekerjaan, peta identitas, pemuatan yang bersemangat, koleksi, dll.
Untuk mempercepat kueri secara dramatis, ambil kolom individual alih-alih objek penuh. Lihat tekniknya dihttp://docs .sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm yang menggambarkan ini.
Sebagai perbandingan Anda dengan PeeWee, PW adalah sistem yang jauh lebih sederhana dengan fitur yang jauh lebih sedikit, termasuk tidak melakukan apa pun dengan peta identitas. Bahkan dengan PeeWee, ORM sesederhana mungkin, masih membutuhkan waktu 15 detik , yang merupakan bukti bahwa cPython sangat lambat dibandingkan dengan pengambilan MySQLdb mentah yang ada di C.
Sebagai perbandingan dengan Java, Java VM jauh lebih cepat daripada cPython . Hibernasi konyolnya rumit, namun Java VM sangat cepat karena JIT dan bahkan semua kerumitan itu akhirnya berjalan lebih cepat. Jika Anda ingin membandingkan Python dengan Java, gunakan Pypy.