最近看了一下 SQLAlchemy 的文档, 感觉大致的使用方式跟 Django ORM 很像(包括 Peewee 之类都很像), 就是细节上感觉有点拧巴, 不如 Django 的 ORM 那么自然. 那 SQLAlchemy 相比有哪些优势呢? 谢谢大家.
![]() | 1 changwei 2017-02-08 06:29:20 +08:00 via Android ![]() 我用过 php 下各种框架得 orm 之后觉得 python 下的 orm 都很拧巴。。。 |
![]() | 2 bigzhu 2017-02-08 08:19:17 +08:00 via Android 早年没靠谱 orm 的时候(暴露年龄了),点了太多技能点在写 sql 上,之后觉得所有的 orm 都很拧巴。。。 |
![]() | 3 chaleaoch 2017-02-08 08:40:11 +08:00 说几个 django orm 坑爹的地方。 1. 有些 group by 无法用 orm 实现。 2. 有些连表查询,用 djanog orm 写出来的 sql 是子查询。 3. 速度感人,一个两万条记录的查询,用时三秒。 sql<100ms 1 和 2sqlalchemy 有很好的解决方案。 3 我不确定 sqlalchemy 是更快还是更慢。 |
![]() | 4 chaleaoch 2017-02-08 08:41:31 +08:00 还有 django orm 如法实现分表。至少原生不支持。只能分区。 sqlalchemy 支持。 |
![]() | 7 chaleaoch 2017-02-08 08:54:45 +08:00 @XhstormR 该用 orm 还是得用 orm 毕竟方便。一直都用 sql 有两个问题,一个是预防 sql 注入,另一个是代码不易读。 |
![]() | 8 precisi0nux 2017-02-08 09:25:35 +08:00 via iPhone @changwei 毕竟是世界上最好的语言。 |
![]() | 9 est 2017-02-08 09:27:14 +08:00 ![]() sqlalchemy 怎么评价呢,首先说,功能完善整齐 然后就是 1 楼所说的,拧巴!没错!有的时候真行想自己去撸 sql 。。 orm 是一种思维和开发的负担。难写难维护难调试 sqlalchemy 的问题,用一句话表示: from sqlalchemy.orm import joinedload, Load, load_only 你看,这里面包含了不含下划线全小写风格,驼峰风格,下划线风格三种 style 。真是玩死你系列。 |
![]() | 10 TangMonk 2017-02-08 09:30:42 +08:00 ActiveRecord 路过。。 |
![]() | 11 vicalloy 2017-02-08 09:52:17 +08:00 没用过 SQLAlchemy ,不是很了解。 很早之前简单的了解过 SQLAlchemy ,从 API 的友好度上看 Django 的 ORM 比 SQLAlchemy 好很多(个人看法)。 Django 的 ORM 调优其实并不是很难,很多时候慢是因为用的不对(糟糕的 SQL 一样慢)。 当然,在极少数情况下还是会出现 ORM 无能为力的情况,这时候可以直接写 SQL 。 ORM 和 SQL 并不冲突。为了这 0.x%的情况而放弃使用 ORM 很没必要。 @chaleaoch 1. Django 的查询可以嵌入 SQL ,也可以把自己手写的 SQL 绑定到对象上。 不知道你遇到的具体情况是怎么样的,不过在我看来第一条应当是可以实现。 2. 有些表连接写出来是子查询,这个需要结合具体案例,不是很确定是否是写法问题。 3. 2w 条数据查询用时 3 秒,这个非常不正常,需要结合具体代码进行分析。从我主观角度看是代码写的有问题。 |
![]() | 12 zhouquanbest 2017-02-08 10:04:40 +08:00 以前只用 SQLAlchemy 现在用 Peewee 感觉 API 更友好 |
![]() | 13 xiaket 2017-02-08 10:16:32 +08:00 我和你的感觉是一样的, Django 的 ORM 的易读性比 peewee 好一圈, peewee 的易读性比 SA 好两圈或更多... |
![]() | 14 est 2017-02-08 12:17:57 +08:00 @zhouquanbest peewee 坑多。主要与原因是 too young @xiaket 赞同。 django 的 orm 其实挺好的。应付 90% 的逻辑没问题,读起来改起来都比 sql 容易太多。 |
![]() | 15 anjianshi 2017-02-08 12:23:50 +08:00 sqlalchemy 硬着头皮用了一段时间,实在研究不下去,改用 peewee 了。 用 peewee ,哪里碰到了问题直接去查源码,主体就一个 python 文件,感觉代码思路很清晰,碰到的大部分问题都得以解决了。 用 sqlalchemy 的时候想查源码都查不出个头绪来 |
![]() | 16 xiaket 2017-02-08 12:30:10 +08:00 @est 个人曾经想过把 Django 的 ORM 完全剥离出来,这样就可以脱离 Django 使用,后来看到 peewee 就放弃了... 不是说它做得有多好,不过至少是存在了. |
![]() | 17 loading 2017-02-08 12:37:02 +08:00 via Android sqlalchemy 很多语言都有实现,换语言,换库都能直接上手。 |
![]() | 19 chaleaoch 2017-02-08 13:15:09 +08:00 @vicalloy @chaleaoch 1. Django 的查询可以嵌入 SQL ,也可以把自己手写的 SQL 绑定到对象上。 不知道你遇到的具体情况是怎么样的,不过在我看来第一条应当是可以实现。 ==== django orm 是有 extra 的写法,不过我把这种写法归于直接 sql 一类。(也是我个人观点) 2. 有些表连接写出来是子查询,这个需要结合具体案例,不是很确定是否是写法问题。 3. 2w 条数据查询用时 3 秒,这个非常不正常,需要结合具体代码进行分析。从我主观角度看是代码写的有问题。 ==== 非常简单 <model>.objects.all().values() 三秒 <model>.objects.filter(<这里假设出 10000 条数据>).values() 一秒 直接用客户端查询 select * from <table name> <100ms 我的理解问题出在 django orm 在生成映射结构的时候多处使用 for 循环导致的这个问题。 |
![]() | 21 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 。 |
22 Jordan 2017-02-08 14:03:36 +08:00 via Android SA 不适合初学者,以及一直用一种数据库的开发者。要驾驭好必须对 rmdb 有一定程度的认识,为了在不同数据库间充分利用他们的特性,并提供一致的接口, SA 没少下功夫,所以代码比其他 ORM 难读。 SA 不仅仅是 ORM 。 |
![]() | 23 wangfengmadking 2017-02-08 14:35:01 +08:00 我只想说 SQLAlchemy 生成真正的 SQL 语句那就是灾难,性能的坑太多了。。。我觉得还是自己撸个简单的 ORM 比较好,我最新的项目就是这么干的, sql 执行效率杠杠的 |
![]() | 24 t0p10 2017-02-08 15:04:16 +08:00 直接手写 SQL 运行速度比 ORM 快很多 |
25 ManjusakaL 2017-02-08 15:16:41 +08:00 Django 的 ORM 事务和多库支持简直鸡肋。。。 |
![]() | 26 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 引起的? |
![]() | 27 chaleaoch 2017-02-08 15:23:52 +08:00 @ManjusakaL 多库还行啊...用 db_router... |
![]() | 28 chaleaoch 2017-02-08 15:24:58 +08:00 |
![]() | 29 vicalloy 2017-02-08 15:30:04 +08:00 @chaleaoch 对 1s 很正常,和 ORM 没关系。 如果有 100w 条数据,你 list(qs)就不是慢的问题,内存会直接爆掉。 你执行 SQL ,实际上只是拿到一个游标,并没有立即将所有数据全部取出来。 你的 list(qs)实际上是一次性将数据全部取出丢到 list 里,不慢才怪。 |
![]() | 30 wizardforcel 2017-02-08 15:35:45 +08:00 我觉得任何 orm 都很拧巴。。 本来把多维数据放进二维的表就够受得了,完了之后各种 sql 查询特性还支持不齐。遇到一种新的子句就要看看文档怎么实现,不同框架还不一样,难受死了。 |
![]() | 31 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)" 这种简直丑得不要不要的。 |
![]() | 32 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 影响效率的点在哪里呢? |
![]() | 33 sagaxu 2017-02-08 20:04:52 +08:00 @est 那是因为 SA 支持的 DB 种类更多,而且把 ORM 和 Expression 分别抽象再组合,有时可以只用 Expression ,能力上 SA 比 Django 更为全面和强大 |
![]() | 34 lightening 2017-02-08 20:10:20 +08:00 via iPhone 看了以上评论觉得果然还是 ruby 的 ActiveRecord 好用啊! |
![]() | 35 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 :) |
![]() | 36 param 2017-02-08 22:23:24 +08:00 via Android 有没有人告诉我,什么是拧巴 |
37 eyp82 OP 看到楼上有人说 SQLAlchemy 支持的 DB 更多, 先假定这是对的. 但感觉并没什么用啊. 一般应用数据库选型定了一种后很少会换, 支持主流的 MySQL, PostgreSQL, Oracle 就可以了吧, 再多也没什么用. |
![]() | 38 zeroten 2017-02-08 22:39:13 +08:00 哈,原来 peewee 用户挺多的 |
39 PythonAnswer 2017-02-08 22:41:42 +08:00 via Android records 是基于 sqlalchemy 的 |
40 Gem 2017-02-08 22:59:54 +08:00 Python 里的 AR 实现: https://orator-orm.com/ |
![]() | 41 ratazzi 2017-02-09 09:01:28 +08:00 还是 SQLAlchemy 功能完善,即使只是拼 SQL ,比如 sa.func.date(Model.c.created_at.op('AT TIME ZONE')(tz)) 一些较新的特性,比如 hstore 、 json 之类也是 SQLAlchemy 支持好 |
![]() | 42 Panmax 2017-02-09 09:03:46 +08:00 |
![]() | 43 chaleaoch 2017-02-09 09:24:48 +08:00 @Panmax 我也不会,只是又一次参加 pycon 年会的时候 达达的 rest api 负责人在做分享的时候讲到过. 你可以搜搜 2016 python 上海 网上能找到视频和 ppt 以及 github. |
44 findex 2017-02-09 17:37:34 +08:00 @bigzhu 我自己写了 ORM 后,觉得不如 SQLAlchemy 功能多,于是我就用 sqla 了。但是 sqla 比我自己写的 orm 臃肿。谁让它功能多呢? 还有我要说说,很多游戏开发里面都用到了类似于 SQL ORM 的思想。什么 post connect, reconnect, 之类的都有。 我觉得, ORM 在于思想问题。 django 自带的 ORM 跟 django 本身镶嵌太密切了,定制性能不好。当然如果你是 rich 的人,全上 django ,多花钱整机器也行。可以参考 instagram 。 sqla 的案例就更多了,什么 reddit , yelp 等等。 要记得,优化好了的 ORM 总是不如优化好了的 SQL 纯净语句。我曾经为了这个动了些脑筋。 |
45 findex 2017-02-09 17:40:41 +08:00 @est Python 就应该统一起来。驼峰风格学习下 Java 什么的语言。这样大家都能迅速读懂。 可惜 python 的很多库写手,也许喝了瓶酒,写库的时候,命名非常不规范,反正发布了,能 work 就行。但是如果是大公司发布标准库的话,应该注意很多。 当然当年的 MS 的很多库命名也十分令人蛋疼。 |
![]() | 47 wizardforcel 2017-02-09 22:45:30 +08:00 via Android 你们好像忽略了 java 上的 orm 。。基本都得手写 sql ,也就是查询结果能映射一下。 优点是数据库特性支持的很好(废话),缺点是需要较高的 sql 功底。 |
48 songdezu 2017-02-14 00:25:59 +08:00 我有个问题 大家看看对不对: 用 orm 的主要优势是能保证各中平台 python Javascript 的语法一致性, 不用学习不同 lib 比如 pymongo mongoose 的不同 api |
![]() | 49 param 2018-05-19 10:36:05 +08:00 peewee 最大的问题在于没有好的 migration |
![]() | 51 param 2018-05-19 10:43:34 +08:00 咦。。。发现自己一年多之前居然回复过这个帖。。 |
![]() | 54 thinker3 2018-09-15 09:26:49 +08:00 @firejoke 我写过,settings.py 只需要 DATABASES、INSTALLED_APPS 等关键的定义就可以了 |