<p>下面是您的MySQL脚本的SQLAlchemy版本,与MySQLdb的三个版本相比,它在四秒钟内执行:</p>
<pre><code>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:tiger@localhost/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
</code></pre>
<p>运行时:</p>
<pre><code>total time: 0:00:04.706010
</code></pre>
<p>下面是一个使用ORM完全加载对象行的脚本;通过避免使用yield per一次创建包含所有1M对象的固定列表,这将在SQLAlchemy master(rel 0.9为18秒)中运行<strong>13秒</strong>:</p>
<pre><code>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:tiger@localhost/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))
</code></pre>
<p>然后,我们可以分割这两种方法之间的差异,并使用ORM只加载单个列:</p>
<pre><code>for obj in sess.query(Foo.id, Foo.a, Foo.b, Foo.c).yield_per(100).limit(1000000):
pass
</code></pre>
<p>上述操作将在4秒内再次运行。</p>
<p>与原始MySQLdb游标相比,SQLAlchemy Core的比较更为贴切。如果对单个列使用ORM but查询,在最新版本中大约需要4秒。</p>
<p>在ORM级别,速度问题是因为在Python中创建对象很慢,SQLAlchemy ORM在获取对象时对这些对象应用大量的簿记,这是它履行其使用契约所必需的,包括工作单元、标识映射、紧急加载、集合等</p>
<p>要显著加快查询速度,请获取单个列而不是完整对象。请参见
<a href="http://docs.sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm" rel="noreferrer">http://docs.sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm</a>描述了这一点。</p>
<p>与PeeWee相比,PW是一个简单得多的系统,功能更少,包括它与身份映射没有任何关系。即使使用PeeWee,只要是一个简单的ORM,它仍然需要<strong>15秒</strong>,这就证明了与使用纯C的原始MySQLdb fetch相比,<strong>cPython确实非常慢</strong></p>
<p>与Java相比,Java VM要比cPython快得多。Hibernate异常复杂,但是Java VM由于JIT而非常快,甚至所有的复杂性都以更快的速度结束。如果要将Python与Java进行比较,请使用Pypy。</p>