• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Django程序的优化技巧

python 搞代码 4年前 (2022-01-09) 12次浏览 已收录 0个评论
文章目录[隐藏]

友情提示:

过度性能优化是没有必要甚至有害的,因为花大力气带来的毫秒级的响应提升你的用户可能根本感知不到,毕竟开发人员的时间也很宝贵。

性能优化指标

在对一个Web项目进行性能优化时,我们通常需要评价多个指标:

  • 响应时间
  • 最大并发连接数
  • 代码的行数
  • 函数调用次数
  • 内存占用情况
  • CPU占比

其中响应时间(服务器从接收用户请求,处理该请求并返回结果所需的总的时间)通常是最重要的指标,因为过长的响应时间会让用户厌倦等待,转投其它网站或APP。当你的用户数量变得非常庞大,如何提高最大并发连接数,减少内存消耗也将变得非常重要。

在开发环境中,我们一般建议使用django-debug-toolbar和django-silk来进行性能监测分析。它们提供了每次用户请求的响应时间,并告诉你程序执行过程哪个环节(比如SQL查询)最消耗时间。

对于中大型网站或Web APP而言,最影响网站性能的就是数据库查询部分了。一是反复从数据库读写数据很消耗时间和计算资源,二是当返回的查询数据集queryset非常大时还会占据很多内存。我们先从这部分优化做起。

数据库查询优化

利用Queryset的惰性和缓存,避免重复查询

充分利用Django的QuerySet的惰性和自带缓存特性,可以帮助我们减少数据库查询次数。比如下例中例1比例2要好。因为在你打印文章标题后,Django不仅执行了数据库查询,还把查询到的article_list放在了缓存里,下次可以在其它地方复用,而例2就不行了。

 # 例1: 利用了缓存特性 - Good
 article_list = Article.objects.filter(title__contains="django")
 for article in article_list:
     print(article.title)
 
 # 例2: Bad
 for article in Article.obje<em style="color:transparent">本文来源gao.dai.ma.com搞@代*码#网</em>cts.filter(title__contains="django"):
     print(article.title)

但有时我们只希望了解查询的结果是否存在或查询结果的数量,这时可以使用exists()和count()方法,如下所示。这样就不会浪费资源查询一个用不到的数据集,还可以节省内存。

 # 例3: Good
 article_list = Article.objects.filter(title__contains="django")
 if article_list.exists():
     print("Records found.")
 else:
     print("No records")
     
 # 例4: Good
 count = Article.objects.filter(title__contains="django").count()

一次查询所有需要的关联模型数据

假设我们有一个文章(Article)模型,其与类别(Category)是单对多的关系(ForeignKey), 与标签(Tag)是多对多的关系(ManyToMany)。我们需要编写一个article_list的函数视图,以列表形式显示文章清单及每篇文章的类别和标签,你的模板文件可能如下所示:

 {% for article in articles %}
    <li>{{ article.title }} </li>
    <li>{{ article.category.name }}</li>
    <li>
        {% for tag in article.tags.all %}
            {{ tag.name }},
        {% endfor %}
    </li>
 {% endfor %}

在模板里每进行一次for循环获取关联对象category和tag的信息,Django就要单独进行一次数据库查询,造成了极大资源浪费。我们完全可以使用select_related方法和prefetch_related方法一次性从数据库获取单对多和多对多关联模型数据,这样在模板中遍历时Django也不会执行数据库查询了。

 # 仅获取文章数据 - Bad
 def article_list(request):
     articles = Article.objects.all()
     return render(request, 'blog/article_list.html',{'articles': articles, })
 
 # 一次性提取关联模型数据 - Good
 def article_list(request):
     articles = Article.objects.all().select_related('category').prefecth_related('tags')
     return render(request, 'blog/article_list.html', {'articles': articles, })

仅查询需要用到的数据


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Django程序的优化技巧

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址