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利用带权重随机数解决抽奖和游戏爆装备问题
Jun 16 Python
Python制作钉钉加密/解密工具
Dec 07 Python
在Django同1个页面中的多表单处理详解
Jan 25 Python
Pycharm学习教程(1) 定制外观
May 02 Python
python中logging库的使用总结
Oct 18 Python
python3+PyQt5 自定义窗口部件--使用窗口部件样式表的方法
Jun 26 Python
python控制台实现tab补全和清屏的例子
Aug 20 Python
python中如何实现将数据分成训练集与测试集的方法
Sep 13 Python
Django中自定义查询对象的具体使用
Oct 13 Python
Pyspark读取parquet数据过程解析
Mar 27 Python
python使用matplotlib的savefig保存时图片保存不完整的问题
Jan 08 Python
详解Python之Scrapy爬虫教程NBA球员数据存放到Mysql数据库
Jan 24 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自定义函数收代码
2010/08/01 PHP
判断Keep-Alive模式的HTTP请求的结束的实现代码
2011/08/06 PHP
ThinkPHP3.1新特性之字段合法性检测详解
2014/06/19 PHP
MyEclipse常用配置图文教程
2014/09/11 PHP
PHP SPL标准库之SplFixedArray使用实例
2015/05/12 PHP
全面解析PHP操作Memcache基本函数
2016/07/14 PHP
redirect_uri参数错误的解决方法(必看)
2017/02/16 PHP
PHPStudy下如何为Apache安装SSL证书的方法步骤
2019/01/23 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
服务端 VBScript 与 JScript 几个相同特性的写法 By shawl.qiu
2007/03/06 Javascript
jQuery 学习第五课 Ajax 使用说明
2010/05/17 Javascript
JavaScript异步回调的Promise模式封装实例
2014/06/07 Javascript
jquery基础知识第一讲之认识jquery
2016/03/17 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
2016/06/23 Javascript
js+html制作简单验证码
2017/02/16 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
webpack+vue中使用别名路径引用静态图片地址
2017/11/20 Javascript
webpack优化的深入理解
2018/12/10 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
vue下载excel的实现代码后台用post方法
2019/05/10 Javascript
vue的注意规范之v-if 与 v-for 一起使用教程
2019/08/04 Javascript
vue el-upload上传文件的示例代码
2020/12/21 Vue.js
[01:32]DOTA2 2015国际邀请赛中国区预选赛第四日战报
2015/05/29 DOTA
对python pandas 画移动平均线的方法详解
2018/11/28 Python
详解pandas的外部数据导入与常用方法
2019/05/01 Python
Python中IP地址处理IPy模块的方法
2019/08/16 Python
Python时间差中seconds和total_seconds的区别详解
2019/12/26 Python
django之导入并执行自定义的函数模块图解
2020/04/01 Python
keras:model.compile损失函数的用法
2020/07/01 Python
一款利用纯css3实现的win8加载动画的实例分析
2014/12/11 HTML / CSS
针对HTML5的Web Worker使用攻略
2015/07/12 HTML / CSS
全球采购的街头服饰和帽子:Urban Excess
2020/10/28 全球购物
成品库仓管员岗位职责
2014/04/06 职场文书
保管员岗位职责
2015/02/14 职场文书
python not运算符的实例用法
2021/06/30 Python
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python