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中的yield浅析
Jun 16 Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
Nov 02 Python
更改Ubuntu默认python版本的两种方法python-> Anaconda
Dec 18 Python
Python常见字符串操作函数小结【split()、join()、strip()】
Feb 02 Python
Python Xml文件添加字节属性的方法
Mar 31 Python
利用Django提供的ModelForm增删改数据的方法
Jan 06 Python
Python基于plotly模块实现的画图操作示例
Jan 23 Python
Python实现删除排序数组中重复项的两种方法示例
Jan 31 Python
Python自动抢红包教程详解
Jun 11 Python
QML使用Python的函数过程解析
Sep 26 Python
selenium学习教程之定位以及切换frame(iframe)
Jan 04 Python
python语言中pandas字符串分割str.split()函数
Aug 05 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中利用XML技术构造远程服务(上)
2006/10/09 PHP
PHP设计模式之解释器模式的深入解析
2013/06/13 PHP
PHP中使用正则表达式提取中文实现笔记
2015/01/20 PHP
PHP设计模式之工厂模式与单例模式
2016/09/28 PHP
laravel 数据迁移与 Eloquent ORM的实现方法
2019/04/12 PHP
TP - 比RBAC更好的权限认证方式(Auth类认证)
2021/03/09 PHP
js 静态动态成员 and 信息的封装和隐藏
2011/05/29 Javascript
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
JS判断、校验MAC地址的2个实例
2014/05/05 Javascript
Node.js中require的工作原理浅析
2014/06/24 Javascript
js实现目录链接,内容跟着目录滚动显示的简单实例
2016/10/15 Javascript
Bootstrap学习笔记之环境配置(1)
2016/12/07 Javascript
jQuery回调方法使用示例
2017/06/26 jQuery
Js面试算法详解
2018/04/08 Javascript
Vue利用canvas实现移动端手写板的方法
2018/05/03 Javascript
关于JavaScript中高阶函数的魅力详解
2018/09/07 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
vue+elementUI组件table实现前端分页功能
2020/11/15 Javascript
vue使用原生swiper代码实例
2020/02/05 Javascript
浅谈Python浅拷贝、深拷贝及引用机制
2016/12/15 Python
Python使用matplotlib实现绘制自定义图形功能示例
2018/01/18 Python
Django 实现下载文件功能的示例
2018/03/06 Python
python实现一个函数版的名片管理系统过程解析
2019/08/27 Python
pygame用blit()实现动画效果的示例代码
2020/05/28 Python
德国网上药房:Apotal
2017/04/04 全球购物
Lookfantastic澳大利亚官网:英国知名美妆购物网站
2021/01/07 全球购物
初中生自我评价
2014/02/01 职场文书
《在山的那边》教学反思
2014/02/23 职场文书
《歌唱二小放牛郎》教学反思
2014/04/19 职场文书
《青蛙看海》教学反思
2014/04/23 职场文书
好学生评语大全
2014/05/05 职场文书
2014领导班子四风问题对照检查材料思想汇报
2014/09/21 职场文书
捐款感谢信
2015/01/20 职场文书
护士辞职信怎么写
2015/02/27 职场文书
导盲犬小Q观后感
2015/06/11 职场文书
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers