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 相关文章推荐
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
Jun 18 Python
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
Apr 16 Python
Python输出9*9乘法表的方法
May 25 Python
Windows下使Python2.x版本的解释器与3.x共存的方法
Oct 25 Python
Python3使用PyQt5制作简单的画板/手写板实例
Oct 19 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 27 Python
75条笑死人的知乎神回复,用60行代码就爬完了
May 06 Python
python使用gdal对shp读取,新建和更新的实例
Mar 10 Python
python实现按键精灵找色点击功能教程,使用pywin32和Pillow库
Jun 04 Python
python爬取2021猫眼票房字体加密实例
Feb 19 Python
Python答题卡识别并给出分数的实现代码
Jun 22 Python
Python如何使用循环结构和分支结构
Apr 13 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/05/16 PHP
PHP类中Static方法效率测试代码
2010/10/17 PHP
PHP中的socket_read和socket_recv区别详解
2015/02/09 PHP
关于PHP中协程和阻塞的一些理解与思考
2017/08/11 PHP
PHP PDOStatement::errorCode讲解
2019/01/31 PHP
通过js为元素添加多项样式,浏览器全兼容写法
2014/08/30 Javascript
JS实现带鼠标效果的头像及文章列表代码
2015/09/27 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
JS中数组重排序方法
2016/11/11 Javascript
AngularJS中isolate scope的用法分析
2016/11/22 Javascript
jQuery实现的表格前端排序功能示例
2017/09/18 jQuery
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
解决vue打包后vendor.js文件过大问题
2019/07/03 Javascript
微信小程序用户拒绝授权的处理方法详解
2019/09/20 Javascript
详解小程序横屏方案对比
2020/06/28 Javascript
JS数组reduce()方法原理及使用技巧解析
2020/07/14 Javascript
vue-cli单页面预渲染seo-prerender-spa-plugin操作
2020/08/10 Javascript
vue使用openlayers实现移动点动画
2020/09/24 Javascript
Python中Random和Math模块学习笔记
2015/05/18 Python
Pycharm远程调试openstack的方法
2017/11/21 Python
python中scikit-learn机器代码实例
2018/08/05 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
Python中字符串String的基本内置函数与过滤字符模块函数的基本用法
2019/05/27 Python
Python利用Scrapy框架爬取豆瓣电影示例
2020/01/17 Python
浅谈keras中自定义二分类任务评价指标metrics的方法以及代码
2020/06/11 Python
Django框架安装及项目创建过程解析
2020/09/14 Python
Python3+PyCharm+Django+Django REST framework配置与简单开发教程
2021/02/16 Python
CSS3实现水平居中、垂直居中、水平垂直居中的实例代码
2020/02/27 HTML / CSS
Needle & Thread官网:英国仙女品牌
2018/01/13 全球购物
锐步香港官方网上商店:Reebok香港
2020/11/05 全球购物
益模软件Java笔试题
2012/03/27 面试题
法人授权委托书范本
2014/04/04 职场文书
领导欢迎词致辞
2015/01/23 职场文书
三好学生竞选稿范文
2019/08/21 职场文书
Python爬虫之爬取某文库文档数据
2021/04/21 Python
解决Maven项目中 Invalid bound statement 无效的绑定问题
2021/06/15 Java/Android