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

Django ORM 如何实现 bulk_update_or_create

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

    如题,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     Solana     923 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 21:57 PVG 05:57 LAX 13:57 JFK 16:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86