SQLAlchemy 比 Django 自带的 ORM 好在哪里?

2017-02-08 04:33:02 +08:00
 eyp82

最近看了一下 SQLAlchemy 的文档, 感觉大致的使用方式跟 Django ORM 很像(包括 Peewee 之类都很像), 就是细节上感觉有点拧巴, 不如 Django 的 ORM 那么自然. 那 SQLAlchemy 相比有哪些优势呢? 谢谢大家.

16642 次点击
所在节点    Python
54 条回复
vicalloy
2017-02-08 14:03:23 +08:00
@chaleaoch
你可以再测试一下,<model>.objects.all().values() 绝对花不了 1 秒。
Django 的 QuerySet 是 Lazy 的,只有在你用的时候才会发生查询。
单纯执行上面的语句不会执行 SQL 。
如果你的写法是
>>> qs = <model>.objects.all().values()
>>> list(qs)
超过 1s 是很正常的,因为你要把所有数据一次性取出来。你可以用调试工具看一下,生成的 SQL 就是`select * from <table name>`,查询速度本身是非常快的,但单 2w 条数据,别的不说,单网络传输都要费不少时间。

使用 Django 的 ORM ,如果慢的不正常,用调试工具看一下生成的 SQL ,通常都可以解决。所谓必须写 SQL 的地方极少。注:
- 部分复杂报表,查询速度慢,用 ORM 性能优化有些难做。
- 需要用到数据库专有特性, Django 不支持,需要用 extra 内嵌少量 SQL 。
Jordan
2017-02-08 14:03:36 +08:00
SA 不适合初学者,以及一直用一种数据库的开发者。要驾驭好必须对 rmdb 有一定程度的认识,为了在不同数据库间充分利用他们的特性,并提供一致的接口, SA 没少下功夫,所以代码比其他 ORM 难读。 SA 不仅仅是 ORM 。
wangfengmadking
2017-02-08 14:35:01 +08:00
我只想说 SQLAlchemy 生成真正的 SQL 语句那就是灾难,性能的坑太多了。。。我觉得还是自己撸个简单的 ORM 比较好,我最新的项目就是这么干的, sql 执行效率杠杠的
t0p10
2017-02-08 15:04:16 +08:00
直接手写 SQL 运行速度比 ORM 快很多
ManjusakaL
2017-02-08 15:16:41 +08:00
Django 的 ORM 事务和多库支持简直鸡肋。。。
chaleaoch
2017-02-08 15:20:55 +08:00
@vicalloy
对,是我没说清楚.
我就是这个意思
>>> qs = <model>.objects.all().values()
>>> list(qs)
超过 1s 是很正常的,因为你要把所有数据一次性取出来。你可以用调试工具看一下,生成的 SQL 就是`select * from <table name>`,查询速度本身是非常快的,但单 2w 条数据,别的不说,单网络传输都要费不少时间。

你的意思是说,(超过 1s 是很正常的)这一秒钟时间并不是 orm 引起的?
chaleaoch
2017-02-08 15:23:52 +08:00
@ManjusakaL 多库还行啊...用 db_router...
chaleaoch
2017-02-08 15:24:58 +08:00
@wangfengmadking 要么是因为你水平到位了.要么是因为项目刚开始没多长时间.等将来业务变动自己撸的就扛不住了.
我为什么这么说?
以为我这么干过.(逃.
vicalloy
2017-02-08 15:30:04 +08:00
@chaleaoch
对 1s 很正常,和 ORM 没关系。
如果有 100w 条数据,你 list(qs)就不是慢的问题,内存会直接爆掉。
你执行 SQL ,实际上只是拿到一个游标,并没有立即将所有数据全部取出来。
你的 list(qs)实际上是一次性将数据全部取出丢到 list 里,不慢才怪。
wizardforcel
2017-02-08 15:35:45 +08:00
我觉得任何 orm 都很拧巴。。

本来把多维数据放进二维的表就够受得了,完了之后各种 sql 查询特性还支持不齐。遇到一种新的子句就要看看文档怎么实现,不同框架还不一样,难受死了。
est
2017-02-08 16:00:19 +08:00
@sagaxu

pep 没问题,但是你写 orm 语句就蛋痛了。

还是 django 或者 peewee 那种链式调用写起来舒服。

sqlalchemy 的 .option() 各种复杂结构,各种 func 太复杂了。不值得花那么多精力去抽象。 orm 本来就一种 dsl 了, sqlalchemy 是 dsl 里再发明一个 dsl 。
比如 primaryjoin="and_(xxx=yyy)" 这种简直丑得不要不要的。
chaleaoch
2017-02-08 16:14:54 +08:00
@vicalloy
部分认同你的观点:
import MySQLdb

# Open database connection
db = MySQLdb.connect(<略>)

import time
starttime = time.time()
sql0 = "select * from <略>"
cursor = db.cursor(MySQLdb.cursors.DictCursor)
cursor.execute(sql0)
custom_html_data = cursor.fetchall()
print time.time() - starttime
cursor.close()

我这边输出的结果在 1.6 ~ 1.7 秒之间.
吃掉的那 1.3 秒就是 orm 的损耗.

这里有一个不严谨的地方就是,我没有测试当前时间点 django orm 的效率.

最后还有一个问题,如果这种时间的损耗都可以忽略的话,大家所说的 ORM 影响效率的点在哪里呢?
sagaxu
2017-02-08 20:04:52 +08:00
@est 那是因为 SA 支持的 DB 种类更多,而且把 ORM 和 Expression 分别抽象再组合,有时可以只用 Expression ,能力上 SA 比 Django 更为全面和强大
lightening
2017-02-08 20:10:20 +08:00
看了以上评论觉得果然还是 ruby 的 ActiveRecord 好用啊!
ashin
2017-02-08 20:45:35 +08:00
肤浅的认为 sqlalchemy 并没有 django 的 orm 好,是真的好难用啊,文档也乱七八糟的感觉,每次都得去看源码,有人用估计也是在不用 django 的时候 orm 方案上早期没有太多的选择,看了 peewee 的文档后觉得 peewee 的文档结构够清楚,明确的要求 connect 和 close ,很方便就实现了自动 reconnect ,轻松两行代码就可以做到主从的读写分离,用 pwiz 还可以把已有的表自省生成 model ,感觉使用 peewee 才是 python orm 正确的选择,还有 records 也不错的样子,暂时还没有在项目里用过,说的是 SQL for Humans :)
param
2017-02-08 22:23:24 +08:00
有没有人告诉我,什么是拧巴
eyp82
2017-02-08 22:32:22 +08:00
看到楼上有人说 SQLAlchemy 支持的 DB 更多, 先假定这是对的. 但感觉并没什么用啊. 一般应用数据库选型定了一种后很少会换, 支持主流的 MySQL, PostgreSQL, Oracle 就可以了吧, 再多也没什么用.
zeroten
2017-02-08 22:39:13 +08:00
哈,原来 peewee 用户挺多的
PythonAnswer
2017-02-08 22:41:42 +08:00
records 是基于 sqlalchemy 的
Gem
2017-02-08 22:59:54 +08:00
Python 里的 AR 实现: https://orator-orm.com/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/338916

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX