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调用cmd命令行制作刷博器
Jan 13 Python
在Django的视图(View)外使用Session的方法
Jul 23 Python
Python随手笔记第一篇(2)之初识列表和元组
Jan 23 Python
让Django支持Sql Server作后端数据库的方法
May 29 Python
Python中pandas模块DataFrame创建方法示例
Jun 20 Python
Python将列表数据写入文件(txt, csv,excel)
Apr 03 Python
详解python编译器和解释器的区别
Jun 24 Python
Python换行与不换行的输出实例
Feb 19 Python
python属于哪种语言
Aug 16 Python
如何在windows下安装配置python工具Ulipad
Oct 27 Python
基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码
Feb 18 Python
python内置进制转换函数的操作
Jun 02 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
详解WordPress中添加和执行动作的函数使用方法
2015/12/29 PHP
phpstudy的php版本自由修改的方法
2017/10/18 PHP
用户注册常用javascript代码
2009/08/29 Javascript
使用apply方法处理数组的三个技巧[译]
2012/09/20 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(四)用地图块拼成大地图
2013/01/23 Javascript
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
js propertychange和oninput事件
2014/09/28 Javascript
node.js中的console.timeEnd方法使用说明
2014/12/09 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
2017/01/13 Javascript
详解vue项目打包步骤
2019/03/29 Javascript
JavaScript中Dom操作实例详解
2019/07/08 Javascript
vue 解决异步数据更新问题
2019/10/29 Javascript
HTML元素拖拽功能实现的完整实例
2020/12/04 Javascript
Python使用minidom读写xml的方法
2015/06/03 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
2016/10/12 Python
Python字典简介以及用法详解
2016/11/15 Python
Python实现Youku视频批量下载功能
2017/03/14 Python
django框架forms组件用法实例详解
2019/12/10 Python
Python 脚本的三种执行方式小结
2019/12/21 Python
Python xlrd excel文件操作代码实例
2020/03/10 Python
使用keras实现孪生网络中的权值共享教程
2020/06/11 Python
python简单利用字典破解zip文件口令
2020/09/07 Python
python 两种方法修改文件的创建时间、修改时间、访问时间
2020/09/26 Python
电子商务专业个人的自我评价
2013/11/19 职场文书
家长对孩子评语
2014/01/30 职场文书
ktv中秋节活动方案
2014/01/30 职场文书
财务管理职业生涯规划书
2014/02/26 职场文书
销售员态度差检讨书
2014/10/26 职场文书
2015年社区反邪教工作总结
2015/10/14 职场文书
只用20行Python代码实现屏幕录制功能
2021/06/02 Python
Spring Cloud 中@FeignClient注解中的contextId属性详解
2021/09/25 Java/Android
Mysql排序的特性详情
2021/11/01 MySQL
Win11绿屏怎么办?Win11绿屏死机的解决方法
2021/11/21 数码科技
JS函数式编程实现XDM一
2022/06/16 Javascript