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多进程通信Queue、Pipe、Value、Array实例
Nov 21 Python
python打开文件并获取文件相关属性的方法
Apr 23 Python
python清除字符串里非数字字符的方法
Jul 02 Python
详解python之简单主机批量管理工具
Jan 27 Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
Feb 14 Python
python绘制双柱形图代码实例
Dec 14 Python
解决python3读取Python2存储的pickle文件问题
Oct 25 Python
Python基于Tkinter模块实现的弹球小游戏
Dec 27 Python
33个Python爬虫项目实战(推荐)
Jul 08 Python
Python响应对象text属性乱码解决方案
Mar 31 Python
Python如何爬取b站热门视频并导入Excel
Aug 10 Python
Python Request类源码实现方法及原理解析
Aug 17 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
全国FM电台频率大全 - 1 北京市
2020/03/11 无线电
PHP 一个随机字符串生成代码
2010/05/26 PHP
批量修改RAR文件注释的php代码
2010/11/20 PHP
php判断两个浮点数是否相等的方法
2015/03/14 PHP
PHP中Static(静态)关键字功能与用法实例分析
2019/04/05 PHP
详解如何实现Laravel的服务容器的方法示例
2019/04/15 PHP
tp5.1 实现setInc字段自动加1
2019/10/18 PHP
IE不出现Flash激活框的小发现的js实现方法
2007/09/07 Javascript
JS复制到剪贴板示例代码
2013/10/30 Javascript
jquery限定文本框只能输入数字即整数和小数
2013/11/29 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
JQuery 给元素绑定click事件多次执行的解决方法
2014/09/09 Javascript
JavaScript学习笔记整理之引用类型
2016/01/22 Javascript
jQuery 选择同时包含两个class的元素的实现方法
2016/06/01 Javascript
Select2.js下拉框使用小结
2016/10/24 Javascript
JavaScript 用fetch 实现异步下载文件功能
2017/07/21 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
2018/10/26 Javascript
详解Python函数作用域的LEGB顺序
2016/05/14 Python
Python中字典和集合学习小结
2017/07/07 Python
使用python实现unix2dos和dos2unix命令的例子
2019/08/13 Python
Python OpenCV视频截取并保存实现代码
2019/11/30 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
2020/02/07 Python
Python同时迭代多个序列的方法
2020/07/28 Python
使用sublime text3搭建Python编辑环境的实现
2021/01/12 Python
Sephora丝芙兰菲律宾官方网站:购买化妆品和护肤品
2017/04/05 全球购物
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
土木工程专业自荐信
2013/10/04 职场文书
创建文明学校实施方案
2014/03/11 职场文书
幼儿园新年寄语
2014/04/03 职场文书
小学生纪律委员竞选稿
2015/11/19 职场文书
百年校庆宣传标语口号
2015/12/26 职场文书
医务人员岗前培训心得体会
2016/01/08 职场文书
小学四年级班务总结该怎么写?
2019/08/16 职场文书
Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)
2021/06/07 Python
mysql下的max_allowed_packet参数设置详解
2022/02/12 MySQL
微软Win11 全新照片应用面向 Dev预览版推出 新版本上手体验图集
2022/09/23 数码科技