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高级应用实例对比:高效计算大文件中的最长行的长度
Jun 08 Python
Django中间件实现拦截器的方法
Jun 01 Python
python matlibplot绘制多条曲线图
Feb 19 Python
python并发和异步编程实例
Nov 15 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
Apr 04 Python
Python3.5常见内置方法参数用法实例详解
Apr 29 Python
python SQLAlchemy的Mapping与Declarative详解
Jul 04 Python
Python 如何创建一个简单的REST接口
Jul 30 Python
Python源码解析之List
May 21 Python
Python+Appium实现自动抢微信红包
May 21 Python
Python并发编程实例教程之线程的玩法
Jun 20 Python
python中sqllite插入numpy数组到数据库的实现方法
Jun 21 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生成静态页面详解
2006/12/05 PHP
php 定义404页面的实现代码
2012/11/19 PHP
php实现分页工具类分享
2014/01/09 PHP
IE6-8中Date不支持toISOString的修复方法
2014/05/04 Javascript
JavaScript Serializer序列化时间处理示例
2014/07/31 Javascript
Node.js模块加载详解
2014/08/16 Javascript
AngularJS基础 ng-submit 指令简单示例
2016/08/03 Javascript
jQuery EasyUI编辑DataGrid用combobox实现多级联动
2016/08/29 Javascript
Bootstrap 下拉多选框插件Bootstrap Multiselect
2017/01/22 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
微信小程序日历组件calendar详解及实例
2017/06/08 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
2017/06/14 Javascript
基于angular6.0实现的一个组件懒加载功能示例
2018/04/12 Javascript
详解Vue2.0配置mint-ui踩过的那些坑
2018/04/23 Javascript
JS图片预加载三种实现方法解析
2020/05/08 Javascript
Vue路由权限控制解析
2020/11/09 Javascript
vue使用exif获取图片旋转,压缩的示例代码
2020/12/11 Vue.js
基于python及pytorch中乘法的使用详解
2019/12/27 Python
python 如何调用远程接口
2020/09/11 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
Html+Css+Jquery实现左侧滑动拉伸导航菜单栏的示例代码
2020/03/17 HTML / CSS
AmazeUI 点击元素显示全屏的实现
2020/08/25 HTML / CSS
美国Lolё官网:购买大胆而美丽的女性运动服装
2017/05/22 全球购物
美国滑雪和滑雪板商店:Buckman
2018/03/03 全球购物
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
公司委托书范本
2014/04/04 职场文书
工厂门卫岗位职责范本
2014/04/04 职场文书
如何写求职信
2014/05/24 职场文书
办公室主任岗位承诺书
2014/05/29 职场文书
总经理人事任命书
2014/06/05 职场文书
乡镇干部个人对照检查材料思想汇报(原创篇)
2014/09/28 职场文书
领导班子个人对照检查剖析材料
2014/09/29 职场文书
加薪通知
2015/04/25 职场文书
少年犯观后感
2015/06/11 职场文书
安全教育的主题班会
2015/08/13 职场文书
html form表单基础入门案例讲解
2021/07/21 HTML / CSS