在ListView中更新保存与计数对象的模型-在性能方面有什么更好的选择?

时间:2019-07-11 14:54:05

标签: python django performance

我正在创建一个论坛脚本。目前,我正在尝试进行优化,并寻求经验丰富的开发人员的答案。

例如-假设我们正在研究Category的ListView,它应该列出同一论坛类别中的所有主题。对于类别中的每个线程,我们都列出诸如以下的字段:

  • 线程名

  • 主题作者

  • 帖子数

  • 观看次数

  • 最新文章详细信息(作者,日期)

计算帖子数的最佳性能方法是什么?目前,我正在考虑3种解决方案。

  1. 在查询集上使用annotate()
  2. 将IntegerField posts_number添加到Thread模型中。在save()模型中增加Post的值,并在delete()中减少
  3. 使用内存缓存来缓存只读SQL查询,并在save()模型中的每个Post上强制刷新刷新。

我知道在低流量论坛中这不是问题,但我很想知道什么是最佳方法

1 个答案:

答案 0 :(得分:1)

我通常不将线程模型本身的发布数量作为额外的model.field处理,而是作为一种方法或属性来处理,并且一次缓存评估值并仅使该线程的缓存无效 >该线程上有新帖子时。这样

  • 当另一个线程上有新帖子时,并非所有缓存的计数都无效
  • 我可以在没有数据库命中的情况下从整个应用程序访问帖子计数
  • 您无需每次仅在帖子数发生变化(删除和插入)时查询帖子数

为您提供解决方案

  1. 注释比计算for循环中每个线程的计数要快,但是即使没有新的Post,您也必须每次都对其计数。

  2. 线程模型上的
  3. Integer字段容易出现数据不一致,特别是从长远来看(例如,如果有2位用户正在访问它,或者在您使用admin时创建了新帖子,则从admin获得。可能最终会写上带有锁的线程安全代码,或者最终写出额外的样板以使其只读,例如,照顾用户使用' all '序列化器在上面写代码等)

  4. 对于您的memcache解决方案,我认为最好不要将它们绑定在一起(线程A上的新帖子不会让您重新计算所有线程的计数)

另外,在model.save中处理更新缓存也不是一个好习惯,因为它总是被调用(例如,编辑帖子),因此无效而不是更新缓存在您实际创建或删除的位置更好帖子(例如,在管理员和编写自定义表单中,或者在您的视图或serializer.perform_create或信号中,但要注意软删除等)。

更新:

由于您的问题是关于性能的,因此您应该查看django ORM optimization doc,最重要的是select_related and prefetch_related

另外,如果从数据库中获取它们后不需要python对象,只需要它们的值don't convert them to python objects