V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wonder1z
V2EX  ›  Django

Django ORM 如何实现 bulk_update_or_create

  •  
  •   wonder1z · 2019-12-11 10:05:43 +08:00 · 6788 次点击
    这是一个创建于 1819 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,django 中貌似只有 bulk_update 和 bulk_create,有什么办法可以实现 bulk_update_or_create 吗

    18 条回复    2020-03-12 10:23:50 +08:00
    hmxxmh
        1
    hmxxmh  
       2019-12-11 10:14:34 +08:00
    for 循环 + update_or_create
    wonder1z
        2
    wonder1z  
    OP
       2019-12-11 10:17:26 +08:00
    @hmxxmh 数据量大的话 效率太低了
    est
        3
    est  
       2019-12-11 10:22:41 +08:00
    ORM 再厉害也没法实现 sql 支持不了的事。建议直接撸 insert ... on duplicate update ...
    wonder1z
        4
    wonder1z  
    OP
       2019-12-11 10:27:56 +08:00
    @est ORM 支持 update_or_create 的 只不过没有批量的 bulk_update_or_create。单条撸性能太差了
    hmxxmh
        5
    hmxxmh  
       2019-12-11 10:28:38 +08:00
    @est 同意,orm 就是对 sql 的一层封装,真要追求效率直接撸 sql 比较好
    hmxxmh
        6
    hmxxmh  
       2019-12-11 10:30:43 +08:00
    @wonder1z 平时只用 bulk_create,刚才查了一圈,没有看到 bulk_update_or_create。。。数据量有多大?
    Ehco1996
        7
    Ehco1996  
       2019-12-11 10:40:50 +08:00
    @wonder1z

    bulk_create 的本质其实是 insert many

    而你的需求是 update_or_create 貌似单条 sql 是做不到的 ( 我也不确定

    我觉得比较简单的是分成两步 然后外面套事务
    * bulk_create
    * bulk_update
    wonder1z
        8
    wonder1z  
    OP
       2019-12-11 10:55:45 +08:00
    @hmxxmh 上千条
    ytymf
        9
    ytymf  
       2019-12-11 13:26:13 +08:00
    @wonder1z 貌似只能循环了,with transaction.atomic 包裹一下,性能还有问题么
    wonder1z
        10
    wonder1z  
    OP
       2019-12-11 16:31:46 +08:00
    @ytymf 回头我试试
    wonder1z
        11
    wonder1z  
    OP
       2019-12-11 16:33:04 +08:00
    @Ehco1996 这样更复杂了吧
    hmxxmh
        12
    hmxxmh  
       2019-12-11 16:48:26 +08:00
    @ytymf with transaction.atomic 只是进入事务,异常统一回滚,不能提升性能,其实我觉得一下创建上千条,肯定慢,放到 celery 里面让他慢慢跑吧
    ytymf
        13
    ytymf  
       2019-12-11 16:59:57 +08:00
    @hmxxmh 你说的没错,这个原意只是保证原子性的事务提交。但在 django 实践中,确实比循环中的每次隐式事务提交快非常多,试试就知道了。
    ytymf
        14
    ytymf  
       2019-12-11 17:02:34 +08:00
    @hmxxmh 具体的原因,猜测是是 model.save 应该会每次建立断开数据库连接,显式事务中 commit 后才断开。没有具体求证过
    hmxxmh
        15
    hmxxmh  
       2019-12-11 21:54:22 +08:00 via Android
    @ytymf 这倒是没注意过😄,下次试一下
    encro
        16
    encro  
       2019-12-12 10:47:14 +08:00
    @hmxxmh
    @ytymf
    Mysql 中一次插入大量数据,采用事务能明显提升性能,这个是事实,
    和 model 没有关系,直接用 sql 也是一样性能差距明显,(一次几十万条数据就能测试出来,我们有时候做性能测试需要一次生成大量数据都是采用事务或者 prepare,原来干几十分钟的,几分钟就行了)
    猜测应该日志配置,索引,寻址有关,
    比如每条记录写一次日志然后确认,与一次性写入一批日志,然后确认。
    0kaka
        17
    0kaka  
       2020-03-01 13:24:17 +08:00
    create( )
    bnm965321
        18
    bnm965321  
       2020-03-12 10:23:50 +08:00
    建议拆分成两个数据集合,先用 unique 字段查询哪些需要 update,然后拆分
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1634 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:52 · PVG 00:52 · LAX 08:52 · JFK 11:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.