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实现简单的文件传输与MySQL备份的脚本分享
Jan 03 Python
Python 爬虫的工具列表大全
Jan 31 Python
Python使用gensim计算文档相似性
Apr 10 Python
python实现音乐下载器
Apr 15 Python
python numpy格式化打印的实例
May 14 Python
python 编写简单网页服务器的实例
Jun 01 Python
django反向解析URL和URL命名空间的方法
Jun 05 Python
tensorflow: variable的值与variable.read_value()的值区别详解
Jul 30 Python
Python实现的排列组合、破解密码算法示例
Apr 12 Python
详解Python是如何实现issubclass的
Jul 24 Python
Python+OpenCV+图片旋转并用原底色填充新四角的例子
Dec 12 Python
Python用来做Web开发的优势有哪些
Aug 05 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 zlib扩展实现页面GZIP压缩输出
2010/06/17 PHP
php Hex RGB颜色值互换的使用
2013/05/10 PHP
php程序总是提示验证码输入有误解决方案
2015/01/07 PHP
PHP上传文件时自动分配路径的方法
2015/01/09 PHP
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
PHP基于简单递归函数求一个数阶乘的方法示例
2017/04/26 PHP
php数据结构之顺序链表与链式线性表示例
2018/01/22 PHP
准确获得页面、窗口高度及宽度的JS
2006/11/26 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
2013/11/15 Javascript
百度判断手机终端并自动跳转js代码及使用实例
2014/06/11 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
介绍JavaScript的一个微型模版
2015/06/24 Javascript
JS实现网页上随滚动条滚动的层效果代码
2015/11/04 Javascript
js密码强度实时检测代码
2016/03/02 Javascript
KnockoutJs快速入门教程
2016/05/16 Javascript
详解js运算符单竖杠“|”与“||”的用法和作用介绍
2016/11/04 Javascript
webpack 1.x升级过程中的踩坑总结大全
2017/08/09 Javascript
通过vue-cli3构建一个SSR应用程序的方法
2018/09/13 Javascript
JS异步执行结果获取的3种解决方式
2019/02/19 Javascript
Javascript删除数组里的某个元素
2019/02/28 Javascript
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
基于vue和websocket的多人在线聊天室
2020/02/01 Javascript
JS如何生成随机验证码
2020/03/02 Javascript
python脚本内运行linux命令的方法
2015/07/02 Python
一个基于flask的web应用诞生 bootstrap框架美化(3)
2017/04/11 Python
Win7下Python与Tensorflow-CPU版开发环境的安装与配置过程
2018/01/04 Python
pycharm内无法import已安装的模块问题解决
2020/02/12 Python
哈利波特商店:Harry Potter Shop
2018/11/30 全球购物
Elemental Herbology官网:英国美容品牌
2019/04/27 全球购物
美体小铺法国官方网站:The Body Shop法国
2020/06/04 全球购物
linux面试题参考答案(11)
2016/11/26 面试题
入党积极分子学习优秀共产党员先进事迹思想汇报
2014/09/13 职场文书
城市轨道交通工程职业生涯规划书范文
2014/09/16 职场文书
2015年幼儿园保育工作总结
2015/05/12 职场文书
本科毕业论文答辩稿
2015/06/23 职场文书
Apache Hudi数据布局黑科技降低一半查询时间
2022/03/31 Servers