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正则表达式中的括号匹配问题
Dec 14 Python
Python-嵌套列表list的全面解析
Jun 08 Python
利用python将json数据转换为csv格式的方法
Mar 22 Python
Python装饰器知识点补充
May 28 Python
Python图像滤波处理操作示例【基于ImageFilter类】
Jan 03 Python
使用python实现语音文件的特征提取方法
Jan 09 Python
在Pycharm中修改文件默认打开方式的方法
Jan 17 Python
Python实现制度转换(货币,温度,长度)
Jul 14 Python
Python Tkinter图形工具使用方法及实例解析
Jun 15 Python
通俗易懂了解Python装饰器原理
Sep 17 Python
Selenium关闭INFO:CONSOLE提示的解决
Dec 07 Python
pandas将list数据拆分成行或列的实现
Dec 13 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游戏编程25个脚本代码
2011/02/08 PHP
PHP设计模式之装饰者模式
2012/02/29 PHP
php查看当前Session的ID实例
2015/03/16 PHP
PHP易混淆知识整理笔记
2015/09/24 PHP
php表单加入Token防止重复提交的方法分析
2016/10/10 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
JavaScript 提升运行速度之循环篇 译文
2009/08/15 Javascript
js预载入和JavaScript Image()对象使用介绍
2011/08/28 Javascript
推荐17个优美新鲜的jQuery的工具提示插件
2012/09/14 Javascript
JavaScript中判断对象类型的几种方法总结
2013/11/11 Javascript
Vue之mixin全局的用法详解
2018/08/22 Javascript
微信小程序实现留言功能
2018/10/31 Javascript
详解IOS微信上Vue单页面应用JSSDK签名失败解决方案
2018/11/14 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
ES6的Fetch异步请求的实现方法
2018/12/07 Javascript
EasyUI 数据表格datagrid列自适应内容宽度的实现
2019/07/18 Javascript
Vue中登录验证成功后保存token,并每次请求携带并验证token操作
2020/09/08 Javascript
python保存字符串到文件的方法
2015/07/01 Python
Python复数属性和方法运算操作示例
2017/07/21 Python
Python实现程序判断季节的代码示例
2019/01/28 Python
Pandas统计重复的列里面的值方法
2019/01/30 Python
python使用opencv在Windows下调用摄像头实现解析
2019/11/26 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
python 已知平行四边形三个点,求第四个点的案例
2020/04/12 Python
如何编写python的daemon程序
2021/01/07 Python
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
优秀团员个人的自我评价
2013/10/02 职场文书
生日派对邀请函
2014/01/13 职场文书
领导检查欢迎词
2014/01/14 职场文书
入党积极分子自我批评思想汇报
2014/10/10 职场文书
学校党支部承诺书
2015/04/30 职场文书
二十年同学聚会致辞
2015/07/28 职场文书
Angular CLI发布路径的配置项浅析
2021/03/29 Javascript
【海涛解说】暗牧也疯狂,牛蛙成配角
2022/04/01 DOTA
MutationObserver在页面水印实现起到的作用详解
2022/07/07 Javascript
CSS子盒子水平和垂直居中的五种方法
2022/07/23 HTML / CSS