【问题标题】:Speed Optimization in DjangoDjango中的速度优化
【发布时间】:2021-09-20 08:31:47
【问题描述】:

我正在构建一个博客应用程序,并且我也在考虑在其中实现视频帖子。我正在尝试优化 Web 应用在开发和生产中的速度。

在过去的几个月里,我在PythonAnywhere 上部署了许多用 Django 构建的站点。我注意到大多数网站都包含简单的功能,例如:-CreateEditImage UploadListViewDetailView 的博客等。带有500 to 600 lines of Code (python)。但是即使只有 2 到 5 页,它们也很慢。

谈发展:-

当我打开一个包含 100 到 150 个带图片的博客的页面时,打开页面需要 2 到 3 秒,然后我认为这可能是因为更多的博客和查询,然后我检查了页面的查询和查询使用Django-Debug-Toolbar 的时间然后我删除了除debug-toolbar 中看到的1 个帖子之外的所有帖子,它正在显示

  • Total time to load the Page is 600ms.

  • 4 次查询6 到 8 毫秒

我删除了一些查询,但结果仍然相同。

我也搜索了它,然后我找到了一篇使用 select_related 优化查询的帖子,然后我也使用了它,但我没有看到任何改进。

作为Template 的初学者,我曾经制作过越来越多的for loops,但后来我在某个地方读到了(抱歉,我不记得出处了)“使用诸如for loop、@987654335 之类的逻辑功能@ 等在 views 而不是 templates".

谈论生产:-

在我的生产站点中-登录,创建或上传文件,在站点中加载图像似乎很慢。所以我认为这可能是因为我使用的数据库,所以我联系他们询问数据库是否会降低站点速度(性能)然后他们说:-

您网站的速度在很大程度上取决于您为处理传入请求而编写的代码的速度。具体的数据库可能不会影响图像下载的速度,但事实上你不会使用静态文件系统。

但我只是像任何人一样编写代码来显示博客文章列表,并且在图像加载缓慢之后我正在使用MEDIA ROOTSTATIC files

我也按照Django-Documentation-About-Performance and Optimization 工作,例如:- 使用counting objects using .count() will increase the speed

在那之后,我仍然没有在ProductionDevelopment 中找到任何优化网站的完美解决方案。

我正在努力优化网站的博客网络应用的视图和模型

models.py

class BlogPost(models.Model):
    user = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
    title = models.CharField(max_length=500,default='',validators=[validate_is_profane])
    description = models.TextField()
    date = models.DateTimeField(null=True,default=timezone.now)
    image = models.ImageField(upload_to='blog_posts',blank=True,null=True)
    slug = models.SlugField(null=True)

views.py

def posts(request):
    blog_profile = get_object_or_404(Profile, user_id=request.user)
    now = timezone.now()
    posts = Post.objects.filter(date__lte=now).order_by('-date').exclude(user=request.user)

    if request.method == 'POST':
        new_blog_post = BlogPostForm(request.POST,
                                    request.FILES,
                                    instance=request.user.profile)

        if which_post_form.is_valid():
            new_blog_post = new_blog_post.save(commit=False)
            new_blog_post.save()
            return redirect('home')

    else:
        new_blog_post = BlogPostForm(instance=request.user.profile)

    context = {
        'posts':posts,
        'blog_profile':blog_profile,
        'new_blog_post':new_blog_form,
    }

    return render(request, 'post_list.html', context)

post_list.html

{% for topic in posts %}

<br>


<a href="{% url 'user_profile' user.id %}">{{ topic.user }}</a>

<p>{{ topic.title|truncatechars:10 }}</p>

{% if topic.image %}
<br>
<a><img src="{{ topic.image.url }}" id="myImg" width="300"></a>
<br>
{% endif %}


<div id="myModal" class="modal">
    <span class="close">&times;</span>
    <img class="modal-content" id="img01">
    <div id="caption"></div>
</div>



<a>{{ topic.description|slice:":10" }}</a>

<a href="{{ topic.get_absolute_url }}">More</a>

{% endblock content %}

如果您对如何优化您的网站有任何进一步的解决方案。那么我将非常感谢您的回答和建议。

【问题讨论】:

  • 如果您要进行 4 次查询以显示一个项目,这可能确实表明您正在进行大量查询,这些查询在显示许多对象时会表现不佳(任何给定的查询速度很快但会产生很多仍然很慢),但是您需要将其与有很多对象时进行的查询进行比较-如果您使用select_related,它仍然可能是4,或者如果您不是,它可能是4 * num_objects高效查询。如果您需要其他帮助,您还需要提供代码(视图和模型)的样例。
  • @tari,感谢您的建议。我已经上传了models.pyviews.py。但我只提供了我正在开发的博客应用程序的代码,但有问题的是,我也在谈论我的其他网站,其中包含简单的 creatingediting 功能,即使它们很慢,功能很少(有 2 到 3 页的网站)。而且我认为我没有在其中做任何conditional functions 但它们仍然很慢
  • 你也可以分享一个模板吗?到目前为止,您共享的代码没有任何明显低效的地方。
  • 这就是我的意思,即使有简单的功能,网站也很慢
  • @tari,我已经更新了模板

标签: python django optimization query-optimization


【解决方案1】:

如果您有大量数据,我发现有两件事可能会导致性能下降,其中第一件事更有可能是一个问题:

默认情况下,访问模板中的topic.user 将对posts 中的每个项目进行额外查询,因为该属性访问需要从不同的表中加载User 模型的信息。在获取Post 查询集时执行select_related('user') 将在与帖子相同的查询中加载用户信息:

Post.objects.filter(date__lte=now) \
    .order_by('-date') \
    .exclude(user=request.user) \
    .select_related('user')

我强烈怀疑以这种方式避免每个帖子的查询将解决您的性能问题,因为如果一个典型的查询需要大约 10 毫秒并且您需要进行数百个查询,那么很容易将您的响应时间延长到几秒钟。由于您实际上并没有读取大量数据,因此查询所花费的时间将主要由固定开销决定,您只需执行较少的查询即可避免这些开销。


虽然除非您有大量帖子(数万或更多),否则不太可能成为问题,但通过 date 订购您的 Posts 将需要数据库读取表的每一行并进行排序在返回任何行之前。对于几百个对象,这成本可以忽略不计,但对于数千个对象,它会更慢。

如果您在查询和排序的字段上add an index,您可以帮助数据库高效地做事:

class Post(models.Model):
    ...
    class Meta:
        indexes = [
            models.Index(fields=['-date'], name='date_ordering'),
        ]

【讨论】:

  • 我明白你所说的一切,但是我将如何使用 Index 方法访问date 的帖子?
  • 没有什么不同:改变数据库架构告诉它维护一个索引,它选择自己使用索引。
猜你喜欢
  • 2017-02-08
  • 1970-01-01
  • 2011-08-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
相关资源
最近更新 更多