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 图片验证码代码分享
Jul 04 Python
python字符串排序方法
Aug 29 Python
Python文件及目录操作实例详解
Jun 04 Python
用python写的一个wordpress的采集程序
Feb 27 Python
python导入时小括号大作用
Jan 10 Python
用生成器来改写直接返回列表的函数方法
May 25 Python
Python3 模块、包调用&路径详解
Oct 25 Python
15行Python代码带你轻松理解令牌桶算法
Mar 21 Python
python解析json串与正则匹配对比方法
Dec 20 Python
python字典一键多值实例代码分享
Jun 14 Python
如何运行带参数的python脚本
Nov 15 Python
python selenium xpath定位操作
Sep 01 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
东方红 - 来复式再生机的修复
2021/03/02 无线电
追求程序速度,而不是编程的速度
2008/04/23 PHP
PHP隐形一句话后门,和ThinkPHP框架加密码程序(base64_decode)
2011/11/02 PHP
PHP中模拟链表和链表的基本操作示例
2016/02/27 PHP
Laravel 的数据库迁移的方法
2017/07/31 PHP
JavaScript对象、属性、事件手册集合方便查询
2010/07/04 Javascript
网站页面自动跳转实现方法PHP、JSP(上)
2010/08/01 Javascript
获取下拉列表框的值是数组,split,$.inArray示例
2013/11/13 Javascript
javascript数组去重的六种方法汇总
2015/08/16 Javascript
javascript实现简易计算器
2017/02/01 Javascript
关于JS与jQuery中的文档加载问题
2017/08/22 jQuery
微信小程序实现下载进度条的方法
2017/12/08 Javascript
Vue自定义过滤器格式化数字三位加一逗号实现代码
2018/03/23 Javascript
微信小程序实现自定义加载图标功能
2018/07/19 Javascript
javascrit中undefined和null的区别详解
2019/04/07 Javascript
Node 代理访问的实现
2019/09/19 Javascript
关于Node.js中频繁修改代码重启服务器的问题
2020/10/15 Javascript
关于angular 8.1使用过程中的一些记录
2020/11/25 Javascript
python fabric实现远程操作和部署示例
2014/03/25 Python
Python 实现选择排序的算法步骤
2018/04/22 Python
Python3爬虫全国地址信息
2019/01/05 Python
python实现可逆简单的加密算法
2019/03/22 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
Python基于BeautifulSoup和requests实现的爬虫功能示例
2019/08/02 Python
pandas按行按列遍历Dataframe的几种方式
2019/10/23 Python
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
预订全球最佳旅行体验:Viator
2018/03/30 全球购物
时尚孕妇装:HATCH Collection
2019/09/24 全球购物
一个C/C++编程面试题
2013/11/10 面试题
linux面试题参考答案(10)
2016/10/26 面试题
英语自荐信范文
2013/12/11 职场文书
电气自动化专业职业规划范文
2014/02/16 职场文书
体育比赛口号
2014/06/09 职场文书
综治工作汇报材料
2014/10/27 职场文书
年中了,该如何写好个人述职报告?
2019/07/02 职场文书
golang中字符串MD5生成方式总结
2021/07/04 Golang