Django bulk_create()、update()与数据库事务的效率对比分析


Posted in Python onMay 15, 2020

下面以创建10000个对象为例进行测试:

# 用for循环挨个创建,共花费37秒
  for i in range(10000):
    name="String number %s"%i
    Record.objects.create(name=name)
 
# 用django事务只提交一次,共花费2.65秒
@transaction.commit_manually
def manual_transaction():
  for i in range(10000):
    name="String number %s"%i
    Record.objects.create(name=name)
  transaction.commit()
 
# 用bulk_create创建,共花费0.47秒
def builtin():
  insert_list =[]
  for i in range(10000):
    name="String number %s"%i
    insert_list.append(Record(name=name))
  Record.objects.bulk_create(insert_list)
 
# 用for循环挨个更新,共花费72秒:
def auto_transaction():
  for record inRecord.objects.all():
    record.name ="String without number"
    record.save()
 
# 用django事务只提交一次,共花费17秒
@transaction.commit_manually
def manual_transaction():
  for record inRecord.objects.all():
    record.name ="String without number"
    record.save()
  transaction.commit()
 
# 用update更新,共花费0.33秒
def builtin():
  Record.objects.all().update(name="String without number")

补充知识:django的model使用上容易遇到的坑,default=datetime.now和auto_now、null和blank、save和update、bulk_create

一、django设置字段动态默认时间的四种方式:

from django.db import models
from datetime import datetime

class User(models.Model):
  id = models.BigAutoField('主键', primary_key=True)
 
  name = models.CharField('名字', max_length=20, db_index=True, default='')
 
  create_time_one = models.DateTimeField('创建时间', default=datetime.now())
  update_time_one = models.DateTimeField('更新时间', default=datetime.now)
 
  create_time_tow = models.DateTimeField('创建时间', auto_now_add=True)
  update_time_tow = models.DateTimeField('更新时间', auto_now=True)

1. default=datetime.now()

model每次初始化,都会自动设置该字段的默认值为初始化时间。

2. default=datetime.now

model每次进行新增或修改操作,都会自动设置该字段的值为操作时间。设置后仍可以使用ORM手动修改该字段。

3. auto_now_add=True

默认值为False,若设置为True,model每次进行新增操作,都会自动设置该字段的值为操作时间。设置为True后无法使用ORM手动修改该字段,哪怕填充了字段的值也会被覆盖。

4. auto_now=True

默认值为False,若设置为True,model每次进行新增或修改操作,都会自动设置该字段的值为操作时间。设置为True后无法使用ORM手动修改该字段,哪怕填充了字段的值也会被覆盖。

5. 要注意的点

除非想设置动态默认时间为项目的启动时间,否则default=datetime.now()这种用法是错误的,会得到期望之外的结果。

使用User.objects.update方法时,设置的default=datetime.now和auto_now=True都不会生效,由于设置了auto_now=True的字段不能手动修改,此时只能使用save方法修改数据,这对于多个数据的更新是不友好的。

因此如果设置动态默认时间的字段,应该使用default=datetime.now和auto_now_add=True来实现。

二、null=True和blank=True的区别

1. null针对数据库,如果null=True,表示数据库的该字段可以为空。

2. blank针对表单的,如果blank=True,表示表单填写该字段时可以不填。

mysql中空值不占用空间,NULL占用空间,而且使用NULL会使索引的效率下降。因此从性能上来说,不建议使用null=True,最好使用default=''。

三、save和build_create的区别

1. 使用save方法:

names = ['张三', '李四']
for name in names:
  user = User(name=name)
  user.save()
  print(user.id) # 此时user对象有id的值

2. 使用bulk_create方法:

names = ['张三', '李四']
users = [User(name=name) for name in names]
users = User.objects.bulk_create(users)
print([user.id for user in users]) # 此时user对象没有id的值

bulk_create的优点:

批量操作时只与数据库进行一次交互,效率高。

bulk_create的缺点:

对于设置了自增的字段,返回值中不会有该字段的值,如上例2中的user对象。

对于设置了动态默认时间的字段,如设置了auto_now=True,同一批处理的记录中该字段的时间将会相同。

四、上面的知识点使用的例子

1. 定义模型

from django.db import models
from datetime import datetime
 
class User(models.Model):
  id = models.BigAutoField('主键', primary_key=True)
  name = models.CharField('名字', max_length=20, db_index=True, blank=False, default='')
  create_time = models.DateTimeField('创建时间', auto_now_add=True)
  update_time = models.DateTimeField('更新时间', default=datetime.now)

2. 插入数据

# 方法一
names = ['张三', '李四']
users = [User(name=name) for name in names]
users = User.objects.bulk_create(users)
 
# 方法二
names = ['张三', '李四']
users = [User(name=name) for name in names]
[user.save() for user in users]

3. 修改数据

# 方法一
names = ['张三', '李四']
User.objects.filter(name__in=names).update(name='changed', update_time=datetime.now()) # 这里必须显式对update_time赋值
 
# 方法二
names = ['张三', '李四']
users = User.objects.filter(name__in=names)
for use in users:
  user.name = 'changed'
  user.save() # 这里会自动更新update_time,但是多次save效率低

以上这篇Django bulk_create()、update()与数据库事务的效率对比分析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python字典操作简明总结
Apr 13 Python
详解flask表单提交的两种方式
Jul 21 Python
python画图的函数用法以及技巧
Jun 28 Python
python适合人工智能的理由和优势
Jun 28 Python
Python如何筛选序列中的元素的方法实现
Jul 15 Python
Python实现汇率转换操作
May 03 Python
python datetime时间格式的相互转换问题
Jun 11 Python
python获取时间戳的实现示例(10位和13位)
Sep 23 Python
Python os库常用操作代码汇总
Nov 03 Python
Ubuntu权限不足无法创建文件夹解决方案
Nov 14 Python
python eventlet绿化和patch原理
Nov 21 Python
python如何进行基准测试
Apr 26 Python
Python实现aes加密解密多种方法解析
May 15 #Python
django 数据库 get_or_create函数返回值是tuple的问题
May 15 #Python
重写django的model下的objects模型管理器方式
May 15 #Python
Python基于pip实现离线打包过程详解
May 15 #Python
Django在Model保存前记录日志实例
May 14 #Python
django 连接数据库出现1045错误的解决方式
May 14 #Python
Django ORM filter() 的运用详解
May 14 #Python
You might like
PHP常量使用的几个需要注意的地方(谨慎使用PHP中的常量)
2014/09/12 PHP
PHP简单获取网站百度搜索和搜狗搜索收录量的方法
2016/08/23 PHP
解决Laravel自定义类引入和命名空间的问题
2019/10/15 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
在jQuery 1.5中使用deferred对象的代码(翻译)
2011/03/10 Javascript
js封装可使用的构造函数继承用法分析
2015/01/28 Javascript
jQuery 遍历函数详解
2015/07/05 Javascript
js实现网站最上边可关闭的浮动广告条代码
2015/09/04 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
浅谈js的url解析函数封装
2016/06/28 Javascript
Node.js获取前端ajax提交的request信息
2017/02/20 Javascript
JS实现侧边栏鼠标经过弹出框+缓冲效果
2017/03/29 Javascript
探索Vue高阶组件的使用
2018/01/08 Javascript
基于JavaScript实现瀑布流布局
2018/08/15 Javascript
使用layui实现树形结构的方法
2019/09/20 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
[49:13]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第一局
2016/02/27 DOTA
[01:23:24]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant BO3 第三场 2月7日
2021/03/11 DOTA
python持久性管理pickle模块详细介绍
2015/02/18 Python
python+matplotlib实现动态绘制图片实例代码(交互式绘图)
2018/01/20 Python
Python断言assert的用法代码解析
2018/02/03 Python
python利用tkinter实现屏保
2019/07/30 Python
感知器基础原理及python实现过程详解
2019/09/30 Python
python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配
2020/02/29 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
2020/06/03 Python
关于前端上传文件全面基础扫盲贴(入门)
2019/08/01 HTML / CSS
详解如何解决canvas图片getImageData,toDataURL跨域问题
2018/09/17 HTML / CSS
Ryderwear美国官网:澳大利亚高端健身训练装备品牌
2018/04/24 全球购物
印尼最大的网上书店:Gramedia.com
2018/09/13 全球购物
weblogic面试题
2016/03/07 面试题
工伤赔偿协议书范本
2014/04/15 职场文书
校庆活动策划方案
2014/06/05 职场文书
五月的鲜花活动方案
2014/08/21 职场文书
2014年护理部工作总结
2014/11/14 职场文书
太空授课观后感
2015/06/17 职场文书
JavaScript获取URL参数的方法分享
2022/04/07 Javascript