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 初始化多维数组代码
Sep 06 Python
Python学习笔记_数据排序方法
May 22 Python
python中list循环语句用法实例
Nov 10 Python
使用Python的web.py框架实现类似Django的ORM查询的教程
May 02 Python
使用FastCGI部署Python的Django应用的教程
Jul 22 Python
浅谈python字符串方法的简单使用
Jul 18 Python
python实现的多线程端口扫描功能示例
Jan 21 Python
Python实现的矩阵类实例
Aug 22 Python
Django中ORM表的创建和增删改查方法示例
Nov 15 Python
python数据结构之线性表的顺序存储结构
Sep 28 Python
基于Python的图像数据增强Data Augmentation解析
Aug 13 Python
Python调用飞书发送消息的示例
Nov 10 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实现的生成静态HTML速度快类库
2007/03/31 PHP
在PHP语言中使用JSON和将json还原成数组的方法
2016/07/19 PHP
php+ajax简单实现全选删除的方法
2016/12/06 PHP
php中请求url的五种方法总结
2017/07/13 PHP
Javascript操纵Cookie实现购物车程序
2007/02/15 Javascript
提高javascript效率 一次判断,而不要次次判断
2012/03/30 Javascript
js和jquery使按钮失效为不可用状态的方法
2014/01/26 Javascript
javascript实现切换td中的值
2014/12/05 Javascript
jQuery+CSS3折叠卡片式下拉列表框实现效果
2015/11/02 Javascript
解决jQuery使用JSONP时产生的错误
2015/12/02 Javascript
详解AngularJS验证、过滤器、指令
2017/01/04 Javascript
Bootstrap缩略图与警告框学习使用
2017/02/08 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
2017/06/15 Javascript
使用JavaScript实现链表的数据结构的代码
2017/08/02 Javascript
前端把html表格生成为excel表格的实例
2017/09/19 Javascript
JS实现简单表格排序操作示例
2017/10/07 Javascript
使用vue-router设置每个页面的title方法
2018/02/11 Javascript
vue下载excel的实现代码后台用post方法
2019/05/10 Javascript
js函数柯里化的方法和作用实例分析
2020/04/11 Javascript
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
2020/11/04 Javascript
Python的设计模式编程入门指南
2015/04/02 Python
python实现图片横向和纵向拼接
2020/03/05 Python
Python Socketserver实现FTP文件上传下载代码实例
2020/03/27 Python
Python发起请求提示UnicodeEncodeError错误代码解决方法
2020/04/21 Python
python3.4中清屏的处理方法
2020/07/06 Python
德国珠宝和配件商店:Styleserver
2021/02/23 全球购物
合作意向书格式及范文
2014/03/31 职场文书
党课知识竞赛主持词
2014/04/01 职场文书
社区党建工作方案
2014/06/10 职场文书
颂军魂爱军营演讲稿
2014/09/13 职场文书
店铺转让协议书(2014版)
2014/09/23 职场文书
四风问题自查自纠工作情况报告
2014/10/28 职场文书
银行稽核岗位职责
2015/04/13 职场文书
工厂无线对讲系统解决方案
2022/02/18 无线电
JS前端使用Canvas快速实现手势解锁特效
2022/09/23 Javascript