Zde je verze SQLAlchemy vašeho skriptu MySQL, která se provede za čtyři sekundy, v porovnání se třemi u 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
runtime:
total time: 0:00:04.706010
Zde je skript, který používá ORM k úplnému načtení řádků objektů; tím, že se vyhnete vytváření pevného seznamu se všemi 1 milionem objektů najednou pomocí výnosu za, proběhne to za 13 sekund s SQLAlchemy master (18 sekund s 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))
Pak můžeme rozdělit rozdíl mezi těmito dvěma přístupy a načíst pouze jednotlivé sloupce pomocí ORM:
for obj in sess.query(Foo.id, Foo.a, Foo.b, Foo.c).yield_per(100).limit(1000000):
pass
Výše uvedené se znovu spustí za 4 sekundy .
Srovnání SQLAlchemy Core je výstižnější srovnání s nezpracovaným kurzorem MySQLdb. Pokud používáte ORM, ale dotazujete se na jednotlivé sloupce, jsou to v nejnovějších verzích asi čtyři sekundy.
Na úrovni ORM jsou problémy s rychlostí způsobeny tím, že vytváření objektů v Pythonu je pomalé a SQLAlchemy ORM na tyto objekty aplikuje velké množství účetnictví, když je načítá, což je nezbytné k tomu, aby splnil svou smlouvu o používání, včetně jednotky. práce, mapa identity, dychtivé načítání, sbírky atd.
Chcete-li dotaz výrazně urychlit, načtěte místo celých objektů jednotlivé sloupce. Podívejte se na techniky na adresehttp://docs .sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm které to popisují.
Pro vaše srovnání s PeeWee je PW mnohem jednodušší systém s mnohem méně funkcemi, včetně toho, že nedělá nic s mapami identity. I s PeeWee, přibližně tak jednoduchým ORM, jak je to proveditelné, to stále trvá 15 sekund , což je důkaz, že cPython je opravdu opravdu pomalý ve srovnání s nezpracovaným načítáním MySQLdb, které je v přímém C.
Pro srovnání s Javou je Java VM rychlejší než cPython . Hibernace je směšná komplikovaný, ale Java VM je extrémně rychlý díky JIT a dokonce i veškerá tato složitost nakonec běží rychleji. Pokud chcete porovnat Python s Javou, použijte Pypy.