【问题标题】:Optimize queryset with django使用 django 优化查询集
【发布时间】:2018-11-08 15:37:11
【问题描述】:

我创建了一个函数,允许计算status 的数量并将其分配给一个变量。

def get_types_count_display(self):
    dispatches = self.route_dispatches.values_list('dispatch_id', flat=True)
    dispatches = Dispatch.objects.filter(id__in=dispatches)
    d = { "dispatches_types": list(dispatches.values('status_id')) }
    pendents = len([1 for e in d["dispatches_types"] if e["status_id"]==1])
    delivered = len([1 for e in d["dispatches_types"] if e["status_id"]==2])
    partial = len([1 for e in d["dispatches_types"] if e["status_id"]==3])
    undelivered = len([1 for e in d["dispatches_types"] if e["status_id"]==4])
    return dict(pendents=pendents, delivered=delivered, partial=partial, undelivered=undelivered)

d 是我的变量,用于存储它包含的字典

{'dispatches_types': [{'status_id': 2}, {'status_id': 1}, {'status_id': 1}, {'status_id': 1}, {'status_id': 2}]}

{'dispatches_types': []}

这是动态的

我遇到的问题是,当您通过 for 再次调用查询集时,查询变得更重。

如何优化这个功能?

【问题讨论】:

    标签: python django python-3.x query-optimization django-queryset


    【解决方案1】:

    为此,您应该使用conditional aggregation

    from django.db import IntegerField, Sum, Case, When
    
    def get_types_count_display(self):
        dispatches self.route_dispatches.all()
        aggregates = dispatches.aggregate(
            pendents=Sum(Case(When(status_id=1, then=1), output_field=IntegerField())),
            delivered =Sum(Case(When(status_id=2, then=1), output_field=IntegerField())),
            partial=Sum(Case(When(status_id=3, then=1), output_field=IntegerField())),
            undelivered=Sum(Case(When(status_id=4, then=1), output_field=IntegerField()))
        )
        return aggregates 
    

    aggregates 是一个与您之前返回的值相同但使用 1 个查询执行的字典

    【讨论】:

    • 感谢您尝试这种方式,但请继续进行多次查询
    • 你在说什么?您是否在一个请求中多次调用get_types_count_display
    【解决方案2】:

    对于“更少”的查询,您可以使用conditional aggregation。给定的示例实际上正是您想要做的。

    如果 Dispatch 记录的总数相对较小,则将其全部加载到内存中(例如,通过在查询集上调用 .values() 的字典)然后过滤它可能比获取记录块更快每个循环。我经常这样做,尤其是当它意味着避免实例化模型对象时。

    --好像我太慢了!

    【讨论】:

    • 谢谢!!我已经尝试过,它执行相同数量的查询:/
    • 在不知道反复调用get_types_count_display 的方法/循环的情况下,我们真的帮不了你。使用聚合可为您提供最少的查询量。
    • 是的,同样的想法,但咨询次数相同
    【解决方案3】:

    如前所述,条件聚合在这里可能会更好。只是想添加替代查询,因为我们实际上并不需要获取总和聚合,而是具有指定状态的调度计数。所以可以这样写:

    from django.db.models import Q
    
    
    aggregates = dispatches.aggregate(
        pendents=Count('pk', filter=Q(status_id=1)),
        delivered =Count('pk', filter=Q(status_id=2)),
        partial=Count('pk', filter=Q(status_id=3)),
        undelivered=Count('pk', filter=Q(status_id=4)),
    )
    

    【讨论】:

    • 谢谢!!我已经尝试过,它执行相同数量的查询:/
    • 这很奇怪.. 根据 Django 文档,这应该转化为一个带有计数和案例语句的查询。
    猜你喜欢
    • 2019-07-21
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2017-05-25
    • 2022-01-08
    • 2017-08-09
    • 2011-10-08
    • 2012-03-19
    相关资源
    最近更新 更多