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查找第k小元素代码分享
Dec 18 Python
Python3.6通过自带的urllib通过get或post方法请求url的实例
May 10 Python
基于数据归一化以及Python实现方式
Jul 11 Python
Python 实现Windows开机运行某软件的方法
Oct 14 Python
python使用for循环计算0-100的整数的和方法
Feb 01 Python
Python3.0中普通方法、类方法和静态方法的比较
May 03 Python
Python利用sqlacodegen自动生成ORM实体类示例
Jun 04 Python
python使用Matplotlib改变坐标轴的默认位置
Oct 18 Python
Python3 解决读取中文文件txt编码的问题
Dec 20 Python
Python测试Kafka集群(pykafka)实例
Dec 23 Python
flask框架蓝图和子域名配置详解
Jan 25 Python
简述python&pytorch 随机种子的实现
Oct 07 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
计数器详细设计
2006/10/09 PHP
PHP生成等比缩略图类和自定义函数分享
2014/06/25 PHP
常见php数据文件缓存类汇总
2014/12/05 PHP
YiiFramework入门知识点总结(图文教程)
2015/12/28 PHP
PHP实现的曲线统计图表示例
2016/11/10 PHP
PHP基于双向链表与排序操作实现的会员排名功能示例
2017/12/26 PHP
thinkPHP5.0框架事务处理操作简单示例
2018/09/07 PHP
PHP chunk_split()函数讲解
2019/02/12 PHP
javascript iframe内的函数调用实现方法
2009/07/19 Javascript
对 lightbox JS 图片控件进行了一下改造, 使其他支持复杂的图片说明
2010/03/20 Javascript
Jquery设置attr的disabled属性控制某行显示或者隐藏
2014/09/25 Javascript
jQuery实现简单的日期输入格式化控件
2015/03/12 Javascript
文件上传,iframe跨域数据提交的实现
2016/11/18 Javascript
详解vue-router基本使用
2017/04/18 Javascript
微信小程序实现滚动消息通知
2018/02/02 Javascript
使用react实现手机号的数据同步显示功能的示例代码
2018/04/03 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
JS控制GIF图片的停止与显示
2019/10/24 Javascript
mpvue实现微信小程序快递单号查询代码
2020/04/03 Javascript
jQuery实现二级导航菜单的示例
2020/09/30 jQuery
Webpack5正式发布,有哪些新特性
2020/10/12 Javascript
如何在JavaScript中等分数组的实现
2020/12/13 Javascript
Python的一些用法分享
2012/10/07 Python
用Python进行行为驱动开发的入门教程
2015/04/23 Python
Python制作豆瓣图片的爬虫
2017/12/28 Python
在Python中增加和插入元素的示例
2018/11/01 Python
pycharm 实现显示project 选项卡的方法
2019/01/17 Python
python读写csv文件实例代码
2019/07/05 Python
白兰氏健康Mall:BRAND’S
2017/11/13 全球购物
工厂标语大全
2014/10/06 职场文书
2015年预算员工作总结
2015/05/14 职场文书
芙蓉镇观后感
2015/06/10 职场文书
心得体会格式及范文
2016/01/25 职场文书
2019垃圾分类宣传口号汇总
2019/08/16 职场文书
浅谈python中的多态
2021/06/15 Python