Python nd不是PostgreSQL。这花了大约25秒。假设从2014年的常识来看,MySQL也应该在100万条记录的结果上表现良好。但是,我只想读取数据,不想更新它。未来的用例只需要插入,在极少数情况下可能需要更新,但在这种情况下,删除和插入就可以了。您已经提到
Python nd不是PostgreSQL。这花了大约25秒。假设从2014年的常识来看,MySQL也应该在100万条记录的结果上表现良好。但是,我只想读取数据,不想更新它。未来的用例只需要插入,在极少数情况下可能需要更新,但在这种情况下,删除和插入就可以了。您已经提到,python,mysql,performance,orm,sqlalchemy,Python,Mysql,Performance,Orm,Sqlalchemy,nd不是PostgreSQL。这花了大约25秒。假设从2014年的常识来看,MySQL也应该在100万条记录的结果上表现良好。但是,我只想读取数据,不想更新它。未来的用例只需要插入,在极少数情况下可能需要更新,但在这种情况下,删除和插入就可以了。您已经提到了chunks/yield\u per(),这通常会对查询进行重大改进:通读一遍,听起来像是您在Python中重新发明了hash join(即“在内存中创建Python dicts”)为了克服MySQL只支持嵌套循环联接的事实(至少过去是这样)
nd不是PostgreSQL。这花了大约25秒。假设从2014年的常识来看,MySQL也应该在100万条记录的结果上表现良好。但是,我只想读取数据,不想更新它。未来的用例只需要插入,在极少数情况下可能需要更新,但在这种情况下,删除和插入就可以了。您已经提到了chunks/
yield\u per()
,这通常会对查询进行重大改进:通读一遍,听起来像是您在Python中重新发明了hash join(即“在内存中创建Python dicts”)为了克服MySQL只支持嵌套循环联接的事实(至少过去是这样)。其他DBMS很长一段时间以来都支持哈希连接和其他策略。我的简单SQL示例还需要将INT(11)转换为python整数,我假设MySQLdb会这样做。此外,SQLAlchemy计算继承和连接所需的时间不应与结果数成线性比例(100k需要2秒,1M需要24秒)。就我个人而言,我不愿意为继承付出代价。如您所见,我还尝试了java中的示例,这需要8-10秒。如果可以的话,你的回答是“不,SQLAlchemy不快,如果你想提高速度,你需要自己创建object/sql代码。”我喜欢你的反馈,但当SQLAlchemy声称“成熟、高性能的架构”时,这并不是很令人满意,因为如果它比纯sql+简单oo慢10倍,那么它的性能就不高。我猜不创建模式和不合成python代码的设计决策是公平的,但由于固有的性能下降,我认为将SQLAlchemy称为“高性能”是不公平的。不过,如果有人反驳我,我会非常高兴的!;)关于类型转换,peewee也一样,相关代码:问题是,您是否需要SQLAlchemy的ORM足够快的速度来(共同)资助为其开发Python代码合成器?到目前为止,显然还没有人这样做。我的观点是SQLAlchemy不是“高性能”,在特性页面中应该更注意这种速度权衡。不这样做会诱使人们用SQLAlchemy编写对象模型,这可能根本不是最好的解决方案。我试图编写一个小框架,将其编译为cpp,但这似乎只比使用python字典稍微快一点。我的方法是:连接所有需要的表,为所有字段和主键创建itemgetter,为每个连接创建dict PK->object,使用这些dict“relate”对象。我还不确定这会有多快。谢谢你对每个领域的建议和解释!然而,我的一般问题是1M记录的数据不多,事实上,考虑到我们所说的大约4*(11位)*1M=5.5兆字节,这是一个非常小的数据量。把这些东西加载到内存中通常是很快的,例如在Matlab中的IMADER()中,考虑到图像的大小,需要0.058425秒。然而,您的观点是“逻辑”使用时间,但是我的BareORM示例表明,简单逻辑也应该是快速的。您的评论是不合理的,因为您期望Python的执行速度与直接的C代码一样快。将其与Matlab、Java等进行比较是完全不公平的,但这与SQLAlchemy没有什么关系。炼金术是非常非常快的。只是用户往往不知道交付了多少功能,并且混淆了ORM结果集和原始数据库游标的结果集。它们是完全不同的,SQLAlchemy提供了许多选项来控制“原始”与“自动”的混合。SQLAlchemy是Python世界中我所熟悉的唯一一个提供这类模式的ORM,主要是b.c。我们是唯一一个持久存储集合而不是每次访问时加载的ORM。如果您正在寻找一个在Python中的ORM,但在很大程度上使用c,请参阅。它没有提供SQLAlchemy的任何急切的加载特性,但从实现的角度来看,它的速度与您将获得的速度一样快——它和PeeWee一样简约,但它的整个持久化引擎提供了一个基于C的后端。根据这一点运行您的基准测试,这是您将要做的最好的事情。或者只使用Pypy。因此,您的声明是,需要应用单个指令“yield_per(100)”,这将使查询速度加倍,这是不合理的。我期待您的Python ORM实现以更好的方式解决这些问题!祝你好运。
mysql> use foo
mysql> describe Foo;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| A | int(11) | NO | | NULL | |
| B | int(11) | NO | | NULL | |
| C | int(11) | NO | | NULL | |
+-------+---------+------+-----+---------+-------+
mysql> SELECT COUNT(*) FROM Foo;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
mysql>
herbert@dev0 ~ $ date; echo 'use foo; select * from Foo;' | mysql -uroot -pxxx > /dev/null; date
zo apr 20 18:48:49 CEST 2014
zo apr 20 18:48:51 CEST 2014
herbert@dev0 ~ $ python BareORM.py
query execution time: 0:00:02.198986
total time: 0:00:03.403084
herbert@dev0 ~ $ python AlchemyORM.py
total time: 0:00:24.649279
from peewee import *
import datetime;
database = MySQLDatabase("foo", host="localhost", port=3306, user="root", passwd="xxx")
class Foo(Model):
id = IntegerField()
A = IntegerField()
B = IntegerField()
C = IntegerField()
class Meta:
db_table = 'Foo'
database = database
start = datetime.datetime.now()
foos = Foo.select()
cnt=0;
for i in foos: cnt=cnt+1
print "total time: ", datetime.datetime.now() - start
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>herbert</groupId>
<artifactId>hibernateORM</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernateORM</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>unknown-jars-temp-repo</id>
<name>A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.</name>
<url>file:${project.basedir}/lib</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>nz.ac.waikato.cms.weka</groupId>
<artifactId>weka-dev</artifactId>
<version>3.7.10</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.1</version>
<classifier>examples</classifier>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>maven</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>1.1</version>
<type>plugin</type>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.kenai.nbpwr</groupId>
<artifactId>org-slf4j-jdk14</artifactId>
<version>1.6.1-201106101300</version>
<type>nbm</type>
</dependency>
</dependencies>
</project>
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
total time: 0:00:04.706010
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))
for obj in sess.query(Foo.id, Foo.a, Foo.b, Foo.c).yield_per(100).limit(1000000):
pass