【问题标题】:Need Django Query optimization (2 Queries instead of 21)需要 Django 查询优化(2 个查询而不是 21 个)
【发布时间】:2021-10-25 00:31:21
【问题描述】:

我在 EBS 上有一个 Django 项目,其中一种返回 Article 对象的 QuerySet 的方法需要很长时间。我想对其进行优化,使其只有一两个查询,但我不确定它是否可能。

型号:WebSite,Article

查询是来自不同网站的Articles列表。

WebSite 模型具有home_orderhome_article_count 属性,用于选择文章的数量以及它们的顺序。

网站 A、B 和 C 的示例:

  1. A - A.home_order = 2, A.home_article_count=3
  2. B - B.home_order = 1, B.home_article_count=5
  3. C - C.home_order = 3, C.home_article_count=7

结果将是(aA 表示来自网站 A 的文章):

aB,aB,aB,aB,aB,aA,aA,aA,aC,aC,aC,aC,aC,aC,aC

列表以aB 开头,表示来自网站B 的文章,因为B.home_order=1,有5 篇aB 文章为B.home_article_count=5

现在,这是一个返回文章的Manager 方法:

def home(self) -> QuerySet:
    articles_pks = []
    for ws in WebSite.objects.active().order_by('home_order', 'name'):
        articles_pks.extend(ws.articles.filter(is_active=True).order_by('-created')[:ws.home_article_count].values_list('pk',flat=True))
    return self.get_queryset().filter(pk__in=articles_pks)

这意味着,对于 20 个 WebSite 对象,有 21 个查询(一个获取网站,另一个获取文章 20 个)。

是否可以在尊重WebSite.home_orderWebSite.home_article_count 的同时将其合并为一个或两个查询?

【问题讨论】:

  • 这是 home 的全部代码吗? return self.get_queryset().filter(pk__in=articles_pks) 不关心订单还是您只是删除了一些代码以使其简短?
  • @bdbd 这是全部代码,谢谢通知。
  • 到目前为止,使用self.get_queryset().filter(pk__in=articles_pks) 取消订购似乎很旧。这是故意的吗?
  • @bdbd 不,这不是故意的,但我可以在内存中对其进行排序,这没什么大不了的。

标签: python django postgresql orm django-orm


【解决方案1】:

尝试使用OR | 运算符组合查询集:

def home(self) -> QuerySet:
    articles_pks = Article.objects.none()
    for ws in WebSite.objects.active().order_by('home_order', 'name'):
        articles_pks = articles_pks | ws.articles.filter(is_active=True).order_by('-created')[:ws.home_article_count]
    return self.get_queryset().filter(pk__in=articles_pks.values_list('pk',flat=True)))

您应该只得到两个查询,一个用于获取网站,另一个用于构建和使用文章列表。

【讨论】:

    猜你喜欢
    • 2011-04-25
    • 2014-02-15
    • 1970-01-01
    • 2021-02-01
    • 2016-02-02
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多