Django的性能优化实现解析


Posted in Python onJuly 30, 2019

一 利用标准数据库优化技术

传统数据库优化技术博大精深,不同的数据库有不同的优化技巧,但重心还是有规则的。在这里算是题外话,挑两点通用的说说:

索引,给关键的字段添加索引,性能能更上一层楼,如给表的关联字段,搜索频率高的字段加上索引等。Django建立实体的时候,支持给字段添加索引,具体参考Django.db.models.Field.db_index。按照经验,Django建立实体之前应该早想好表的结构,尽量想到后面的扩展性,避免后面的表的结构变得面目全非。

使用适当字段类型,本来varchar就搞定的字段,就别要text类型,小细节别不关紧要,后头数据量一上去,愈来愈多的数据,小字段很可能是大问题。

二 了解Django的QuerySets

了解Django的QuerySets对象,对优化简单程序有至关重要的作用。QuerySets是有缓存的,一旦取出来,它就会在内存里呆上一段时间,尽量重用它。

# 了解缓存属性:
>>> entry = Entry.objects.get(id=1)
>>> entry.blog  # 博客实体第一次取出,是要访问数据库的
>>> entry.blog  # 第二次再用,那它就是缓存里的实体了,不再访问数据库
>>> entry = Entry.objects.get(id=1)
>>> entry.authors.all()  # 第一次all函数会查询数据库
>>> entry.authors.all()  # 第二次all函数还会查询数据库

all,count exists是调用函数(需要连接数据库处理结果的),注意在模板template里的代码,模板里不允许括号,但如果使用此类的调用函数,一样去连接数据库的,能用缓存的数据就别连接到数据库去处理结果。还要注意的是,自定义的实体属性,如果调用函数的,记得自己加上缓存策略。

利用好模板的with标签:

模板中多次使用的变量,要用with标签,把它看成变量的缓存行为吧。

使用QuerySets的iterator():

通常QuerySets先调用iterator再缓存起来,当获取大量的实体列表而仅使用一次时,缓存行为会耗费宝贵的内存,这时iterator()能帮到你,iterator()只调用iterator而省 去了缓存步骤,显著减少内存占用率,具体参考相关文档。

三 数据库的工作就交给数据库本身计算,别用Python处理

  • 使用 filter and exclude 过滤不需要的记录,这两个是最常用语句,相当是SQL的where
  • 同一实体里使用F()表达式过滤其他字段
  • 使用annotate对数据库做聚合运算

不要用python语言对以上类型数据过滤筛选,同样的结果,python处理复杂度要高,而且效率不高, 白白浪费内存

  • 使用QuerySet.extra() extra虽然扩展性不太好,但功能很强大,如果实体里需要需要增加额外属性,不得已时,通过extra来实现,也是个好办法
  • 使用原生的SQL语句 如果发现Django的ORM已经实现不了你的需求,而extra也无济于事的时候,那就用原生SQL语句

四 如果需要就一次性取出你所需要的数据

单一动作(如:同一个页面)需要多次连接数据库时,最好一次性取出所有需要的数据,减少连接数据库次数。

此类需求推荐使用QuerySet.select_related() (主动连表)和 prefetch_related()(被动连表)

相反,别取出你不需要的东西,模版templates里往往只需要实体的某几个字段而不是全部,这时QuerySet.values() 和 values_list(),对你有用,它们只取你需要的字段,返回字典dict和列表list类型的东西,在模版里够用即可,这可减少内存损耗,提高性能

同样QuerySet.defer()和only()对提高性能也有很大的帮助,一个实体里可能有不少的字段,有些字段包含很多元数据,比如博客的正文,很多字符组成,Django获取实体时(取出实体过程中会进行一些python类型转换工作),我们可以延迟大量元数据字段的处理,只处理需要的关键字段,这时QuerySet.defer()就派上用场了,在函数里传入需要延时处理的字段即可;而only()和defer()是相反功能

使用QuerySet.count()代替len(queryset),虽然这两个处理得出的结果是一样的,但前者性能优秀很多。同理判断记录存在时,QuerySet.exists()比if queryset实在强得太多了

五 懂减少数据库的连接数

使用 QuerySet.update() 和 delete(),这两个函数是能批处理多条记录的,适当使用它们事半功倍;如果可以,别一条条数据去update delete处理。

对于一次性取出来的关联记录,获取外键的时候,直接取关联表的属性,而不是取关联属性,如:

entry.blog.id
优于
entry.blog__id


# 善于使用批量插入记录,如:
Entry.objects.bulk_create([
  Entry(headline="Python 3.0 Released"),
  Entry(headline="Python 3.1 Planned")
])
优于
Entry.objects.create(headline="Python 3.0 Released")
Entry.objects.create(headline="Python 3.1 Planned")
# 前者只连接一次数据库,而后者连接两次


# 还有相似的动作需要注意的,如:多对多的关系,
my_band.members.add(me, my_friend)
优于
my_band.members.add(me)
my_band.members.add(my_friend)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python调用shell的方法
Nov 20 Python
详解Python的Lambda函数与排序
Oct 25 Python
Collatz 序列、逗号代码、字符图网格实例
Jun 22 Python
Python元组操作实例分析【创建、赋值、更新、删除等】
Jul 24 Python
python虚拟环境的安装配置图文教程
Oct 20 Python
Python在不同目录下导入模块的实现方法
Oct 27 Python
Python+tkinter使用80行代码实现一个计算器实例
Jan 16 Python
Python图像处理之gif动态图的解析与合成操作详解
Dec 30 Python
Python使用sax模块解析XML文件示例
Apr 04 Python
Pytorch 实现权重初始化
Dec 31 Python
tensorflow图像裁剪进行数据增强操作
Jun 30 Python
python 制作本地应用搜索工具
Feb 27 Python
Python爬虫学习之获取指定网页源码
Jul 30 #Python
django-初始配置(纯手写)详解
Jul 30 #Python
django 单表操作实例详解
Jul 30 #Python
Apache部署Django项目图文详解
Jul 30 #Python
Python 使用list和tuple+条件判断详解
Jul 30 #Python
用python wxpy管理微信公众号并利用微信获取自己的开源数据
Jul 30 #Python
Python实现二叉搜索树BST的方法示例
Jul 30 #Python
You might like
php checkdate、getdate等日期时间函数操作详解
2010/03/11 PHP
PHP 开发环境配置(Zend Server安装)
2010/04/28 PHP
PHP连接SQLServer2005的实现方法(附ntwdblib.dll下载)
2012/07/02 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
浅析PHP中的闭包和匿名函数
2017/12/25 PHP
Yii2框架类自动加载机制实例分析
2018/05/02 PHP
PHP实现的杨辉三角求解算法分析
2019/03/11 PHP
javascript之更有效率的字符串替换
2008/08/02 Javascript
各种常用浏览器getBoundingClientRect的解析
2009/05/21 Javascript
JavaScript 组件之旅(一)分析和设计
2009/10/28 Javascript
jQuery控制元素显示、隐藏、切换、滑动的方法总结
2015/04/16 Javascript
js实现左侧网页tab滑动门效果代码
2015/09/06 Javascript
js学习笔记之事件处理模型
2016/10/31 Javascript
Nodejs下用submit提交表单提示cannot post错误的解决方法
2016/11/21 NodeJs
import与export在node.js中的使用详解
2017/09/28 Javascript
浅谈javascript错误处理
2019/08/11 Javascript
[01:06]DOTA2隆重推出2016冬季勇士令状 内含上海特级锦标赛互动指南
2016/02/17 DOTA
利用Python的Django框架生成PDF文件的教程
2015/07/22 Python
从头学Python之编写可执行的.py文件
2017/11/28 Python
numpy matrix和array的乘和加实例
2018/06/28 Python
Pandas统计重复的列里面的值方法
2019/01/30 Python
python中嵌套函数的实操步骤
2019/02/27 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
2019/06/28 Python
使用keras框架cnn+ctc_loss识别不定长字符图片操作
2020/06/29 Python
Python gevent协程切换实现详解
2020/09/14 Python
HTML5实现的图片无限加载的瀑布流效果另带边框圆角阴影
2014/03/07 HTML / CSS
美国伴娘礼服商店:Evening Collective
2019/10/07 全球购物
如何从一个文件档案的尾端新增记录
2016/12/02 面试题
新学期红领巾广播稿
2014/01/14 职场文书
法院先进个人事迹材料
2014/05/04 职场文书
2015年毕业生自荐信范文
2015/03/24 职场文书
简历上的自我评价,该怎么写呢?
2019/06/13 职场文书
导游词之丽江普济寺
2019/10/22 职场文书
WebRTC记录音视频流(web技术分享)
2022/02/24 Javascript
一行Python命令实现批量加水印
2022/04/07 Python
git中cherry-pick命令的使用教程
2022/06/25 Servers