V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
eyp82
V2EX  ›  Python

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

  •  
  •   eyp82 · 2017-02-08 04:33:02 +08:00 · 17020 次点击
    这是一个创建于 2879 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    54 条回复    2018-09-15 09:26:49 +08:00
    changwei
        1
    changwei  
       2017-02-08 06:29:20 +08:00 via Android   ❤️ 2
    我用过 php 下各种框架得 orm 之后觉得 python 下的 orm 都很拧巴。。。
    bigzhu
        2
    bigzhu  
       2017-02-08 08:19:17 +08:00 via Android
    早年没靠谱 orm 的时候(暴露年龄了),点了太多技能点在写 sql 上,之后觉得所有的 orm 都很拧巴。。。
    chaleaoch
        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 是更快还是更慢。
    chaleaoch
        4
    chaleaoch  
       2017-02-08 08:41:31 +08:00
    还有 django orm 如法实现分表。至少原生不支持。只能分区。
    sqlalchemy 支持。
    eyp82
        5
    eyp82  
    OP
       2017-02-08 08:42:53 +08:00 via iPhone
    @chaleaoch 感谢具体的体验和回复
    XhstormR
        6
    XhstormR  
       2017-02-08 08:47:07 +08:00 via Android
    @chaleaoch 所以推荐原生 SQL ,还是 ORM 呢?
    chaleaoch
        7
    chaleaoch  
       2017-02-08 08:54:45 +08:00
    @XhstormR 该用 orm 还是得用 orm 毕竟方便。一直都用 sql 有两个问题,一个是预防 sql 注入,另一个是代码不易读。
    precisi0nux
        8
    precisi0nux  
       2017-02-08 09:25:35 +08:00 via iPhone
    @changwei 毕竟是世界上最好的语言。
    est
        9
    est  
       2017-02-08 09:27:14 +08:00   ❤️ 2
    sqlalchemy 怎么评价呢,首先说,功能完善整齐

    然后就是 1 楼所说的,拧巴!没错!有的时候真行想自己去撸 sql 。。 orm 是一种思维和开发的负担。难写难维护难调试


    sqlalchemy 的问题,用一句话表示:

    from sqlalchemy.orm import joinedload, Load, load_only

    你看,这里面包含了不含下划线全小写风格,驼峰风格,下划线风格三种 style 。真是玩死你系列。
    TangMonk
        10
    TangMonk  
       2017-02-08 09:30:42 +08:00
    ActiveRecord 路过。。
    vicalloy
        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 秒,这个非常不正常,需要结合具体代码进行分析。从我主观角度看是代码写的有问题。
    zhouquanbest
        12
    zhouquanbest  
       2017-02-08 10:04:40 +08:00
    以前只用 SQLAlchemy 现在用 Peewee 感觉 API 更友好
    xiaket
        13
    xiaket  
       2017-02-08 10:16:32 +08:00
    我和你的感觉是一样的, Django 的 ORM 的易读性比 peewee 好一圈, peewee 的易读性比 SA 好两圈或更多...
    est
        14
    est  
       2017-02-08 12:17:57 +08:00
    @zhouquanbest peewee 坑多。主要与原因是 too young

    @xiaket 赞同。

    django 的 orm 其实挺好的。应付 90% 的逻辑没问题,读起来改起来都比 sql 容易太多。
    anjianshi
        15
    anjianshi  
       2017-02-08 12:23:50 +08:00
    sqlalchemy 硬着头皮用了一段时间,实在研究不下去,改用 peewee 了。
    用 peewee ,哪里碰到了问题直接去查源码,主体就一个 python 文件,感觉代码思路很清晰,碰到的大部分问题都得以解决了。
    用 sqlalchemy 的时候想查源码都查不出个头绪来
    xiaket
        16
    xiaket  
       2017-02-08 12:30:10 +08:00
    @est 个人曾经想过把 Django 的 ORM 完全剥离出来,这样就可以脱离 Django 使用,后来看到 peewee 就放弃了... 不是说它做得有多好,不过至少是存在了.
    loading
        17
    loading  
       2017-02-08 12:37:02 +08:00 via Android
    sqlalchemy 很多语言都有实现,换语言,换库都能直接上手。
    sagaxu
        18
    sagaxu  
       2017-02-08 13:04:56 +08:00
    @est 那是 PEP8 规定的命名方式
    chaleaoch
        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 循环导致的这个问题。
    xiaket
        20
    xiaket  
       2017-02-08 13:35:46 +08:00
    @chaleaoch 不给 ORM 翻译出来的 SQL 就和裸 SQL 比较性能并猜测原因略有些耍流氓...
    vicalloy
        21
    vicalloy  
       2017-02-08 14:03:23 +08:00   ❤️ 2
    @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
        22
    Jordan  
       2017-02-08 14:03:36 +08:00 via Android
    SA 不适合初学者,以及一直用一种数据库的开发者。要驾驭好必须对 rmdb 有一定程度的认识,为了在不同数据库间充分利用他们的特性,并提供一致的接口, SA 没少下功夫,所以代码比其他 ORM 难读。 SA 不仅仅是 ORM 。
    wangfengmadking
        23
    wangfengmadking  
       2017-02-08 14:35:01 +08:00
    我只想说 SQLAlchemy 生成真正的 SQL 语句那就是灾难,性能的坑太多了。。。我觉得还是自己撸个简单的 ORM 比较好,我最新的项目就是这么干的, sql 执行效率杠杠的
    t0p10
        24
    t0p10  
       2017-02-08 15:04:16 +08:00
    直接手写 SQL 运行速度比 ORM 快很多
    ManjusakaL
        25
    ManjusakaL  
       2017-02-08 15:16:41 +08:00
    Django 的 ORM 事务和多库支持简直鸡肋。。。
    chaleaoch
        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 引起的?
    chaleaoch
        27
    chaleaoch  
       2017-02-08 15:23:52 +08:00
    @ManjusakaL 多库还行啊...用 db_router...
    chaleaoch
        28
    chaleaoch  
       2017-02-08 15:24:58 +08:00
    @wangfengmadking 要么是因为你水平到位了.要么是因为项目刚开始没多长时间.等将来业务变动自己撸的就扛不住了.
    我为什么这么说?
    以为我这么干过.(逃.
    vicalloy
        29
    vicalloy  
       2017-02-08 15:30:04 +08:00
    @chaleaoch
    对 1s 很正常,和 ORM 没关系。
    如果有 100w 条数据,你 list(qs)就不是慢的问题,内存会直接爆掉。
    你执行 SQL ,实际上只是拿到一个游标,并没有立即将所有数据全部取出来。
    你的 list(qs)实际上是一次性将数据全部取出丢到 list 里,不慢才怪。
    wizardforcel
        30
    wizardforcel  
       2017-02-08 15:35:45 +08:00
    我觉得任何 orm 都很拧巴。。

    本来把多维数据放进二维的表就够受得了,完了之后各种 sql 查询特性还支持不齐。遇到一种新的子句就要看看文档怎么实现,不同框架还不一样,难受死了。
    est
        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)" 这种简直丑得不要不要的。
    chaleaoch
        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 影响效率的点在哪里呢?
    sagaxu
        33
    sagaxu  
       2017-02-08 20:04:52 +08:00
    @est 那是因为 SA 支持的 DB 种类更多,而且把 ORM 和 Expression 分别抽象再组合,有时可以只用 Expression ,能力上 SA 比 Django 更为全面和强大
    lightening
        34
    lightening  
       2017-02-08 20:10:20 +08:00 via iPhone
    看了以上评论觉得果然还是 ruby 的 ActiveRecord 好用啊!
    ashin
        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 :)
    param
        36
    param  
       2017-02-08 22:23:24 +08:00 via Android
    有没有人告诉我,什么是拧巴
    eyp82
        37
    eyp82  
    OP
       2017-02-08 22:32:22 +08:00
    看到楼上有人说 SQLAlchemy 支持的 DB 更多, 先假定这是对的. 但感觉并没什么用啊. 一般应用数据库选型定了一种后很少会换, 支持主流的 MySQL, PostgreSQL, Oracle 就可以了吧, 再多也没什么用.
    zeroten
        38
    zeroten  
       2017-02-08 22:39:13 +08:00
    哈,原来 peewee 用户挺多的
    PythonAnswer
        39
    PythonAnswer  
       2017-02-08 22:41:42 +08:00 via Android
    records 是基于 sqlalchemy 的
    Gem
        40
    Gem  
       2017-02-08 22:59:54 +08:00
    Python 里的 AR 实现: https://orator-orm.com/
    ratazzi
        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 支持好
    Panmax
        42
    Panmax  
       2017-02-09 09:03:46 +08:00
    @chaleaoch 你好,想请教下 SqlAlchemy 的分表实现方法。

    我现在是用 automap_base 来反向映射的表结构。
    chaleaoch
        43
    chaleaoch  
       2017-02-09 09:24:48 +08:00
    @Panmax 我也不会,只是又一次参加 pycon 年会的时候 达达的 rest api 负责人在做分享的时候讲到过.
    你可以搜搜 2016 python 上海 网上能找到视频和 ppt 以及 github.
    findex
        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 纯净语句。我曾经为了这个动了些脑筋。
    findex
        45
    findex  
       2017-02-09 17:40:41 +08:00
    @est Python 就应该统一起来。驼峰风格学习下 Java 什么的语言。这样大家都能迅速读懂。
    可惜 python 的很多库写手,也许喝了瓶酒,写库的时候,命名非常不规范,反正发布了,能 work 就行。但是如果是大公司发布标准库的话,应该注意很多。
    当然当年的 MS 的很多库命名也十分令人蛋疼。
    est
        46
    est  
       2017-02-09 19:18:23 +08:00
    @findex 2333 其实质量比较差的是标准库。。
    wizardforcel
        47
    wizardforcel  
       2017-02-09 22:45:30 +08:00 via Android
    你们好像忽略了 java 上的 orm 。。基本都得手写 sql ,也就是查询结果能映射一下。

    优点是数据库特性支持的很好(废话),缺点是需要较高的 sql 功底。
    songdezu
        48
    songdezu  
       2017-02-14 00:25:59 +08:00
    我有个问题 大家看看对不对:
    用 orm 的主要优势是能保证各中平台 python javascript 的语法一致性, 不用学习不同 lib 比如 pymongo mongoose 的不同 api
    param
        49
    param  
       2018-05-19 10:36:05 +08:00
    peewee 最大的问题在于没有好的 migration
    param
        50
    param  
       2018-05-19 10:37:20 +08:00
    @xiaket 我有一个项目就是单独使用 Django ORM
    param
        51
    param  
       2018-05-19 10:43:34 +08:00
    咦。。。发现自己一年多之前居然回复过这个帖。。
    xiaket
        52
    xiaket  
       2018-05-19 11:01:41 +08:00
    @param lol, 这算是自己挖自己的坟? txtx
    firejoke
        53
    firejoke  
       2018-07-05 15:37:49 +08:00
    @param 你好,有关于你的单独剥离 Django ORM 的相关笔记吗? (星星眼)~
    thinker3
        54
    thinker3  
       2018-09-15 09:26:49 +08:00
    @firejoke 我写过,settings.py 只需要 DATABASES、INSTALLED_APPS 等关键的定义就可以了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5507 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 08:55 · PVG 16:55 · LAX 00:55 · JFK 03:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.