【问题标题】:Queryset taking too much time查询集花费太多时间
【发布时间】:2019-11-14 19:20:37
【问题描述】:

我也从数据库中计算了 3000 个项目的一些值。从选择框中选择项目时,字段应由 jquery 填充。

我正在迭代每个项目,将其发送到字典中(项目名称作为键,变量元组作为值)并将这个字典传递给 django 模板。

我在模板中发送 auto_dict 字典。每次用户从选择框中选择值时,在change 函数上,我都会迭代字典并获取值。 页面加载时间过长。

    class Sales(models.Model): # sales detail of items
        item_id = models.ForeignKey('Item', models.DO_NOTHING)
        # some more fields


    class Item(models.Model): # detail of items, around 3000 items
        name = models.CharField(max_length=127)
        # some more fields


    class Order(models.Model): # order detail of each order
        order_number = models.CharField(max_length=63, unique=True)
        created_at = models.DateField(auto_now_add=True)
        status = models.CharField(max_length=2, choices=STATUS, blank=True, null=True, default='NP')
        final_approval = models.CharField(max_length=3,default='No')
        order_type = models.CharField(max_length=2, blank=True, null=True, choices=ORDER_TYPE)
        # some more fields


    class Orderitems(models.Model): # item detail for all order
        qty = models.IntegerField()
        item_id = models.ForeignKey(Item, models.DO_NOTHING, blank=True, null=True)
        order_id = models.ForeignKey(Order, models.DO_NOTHING, blank=True, null=True)
        sales_id = models.ForeignKey(Sales, models.DO_NOTHING, blank=True, null=True)
        # some more fields

-------- 编辑部分 ---------

我想要所有的总和(创建日期与今天之间的差异)。

created_at = models.DateField(auto_now_add=True)

我正在使用这个:

current_date = datetime.date.today()

time_diff = OrderItemTable.objects.annotate(days=Sum((F('prev_order_items__order_id__created_at')-current_date)))

但是这个给出的答案像这样 181715600.0。我想要这样的东西:

第一个订单 - 01/07/2019,差异 = 4 天 * 2(数量)

第二个订单 - 03/07/2019,差异 - 2 天 * 3(数量)

总和 = 14

我还没有在查询中添加乘法部分。

这是针对每个项目的。

【问题讨论】:

  • 为什么不自己做sql查询呢?您可以编写一个 raw_query 并获得格式化的结果,而不是稍后计算它
  • 对不起,我是 django 的新手。你能告诉我怎么做吗?
  • 如果不仔细研究您的代码,就很难知道。但我可以提出一些建议。首先,尝试计算数据库命中数。看起来,不是循环遍历项目并在每个循环上添加一个新过滤器,您应该是annotating 循环外的查询,每行所需的所有信息都由一个数据库命中提供。您可能会发现 Django Debug Toolbar 非常有用,因为它报告了数据库命中。
  • @BerndWechner,谢谢。注释将 DB 命中数从 6797 减少到 7,加载时间从 9 秒减少到 0.007 秒
  • 不客气。请记住 QuerySet 是惰性的,并且在评估它们时要密切注意。每次评估都会进入数据库。所以它们最好是一块一块地构建,同时保持它们的惰性(这意味着它们只记录获取对象的方法,直到需要对象本身时才获取对象!)

标签: python django pandas dictionary django-queryset


【解决方案1】:

我认为您可以在单个查询中执行一些操作。例如:

假设你有这样定义的related_names:

class OrderOrderitemsTable(...):
    item = models.ForeignKey(Item, related_name='prev_order_items')

class OrderItemSales(...):
    item = models.ForeignKey(Item, related_name='sales_order_items')

然后您可以使用aggregation 运行这样的查询:

OrderItemTable.objects.annotate(
    prev_sum_order=Sum('item__prev_order_items__qty')
).annotate(
    sale_sum_order=Sum('item__sale_order_items__qty')
).annotate(
    rating=F('sale_sum_order')/F('sale_sum_order')
).annotate(
    in_wirehouse = Sum('item__qty_in_ferma_warehouse')
)
.values(
    'prev_sum_order',
    'sale_sum_order',
    'rating',
    'in_wirehouse'
)

【讨论】:

  • 此解决方案有效,并且注释将 DB 命中数从 6797 减少到 7。只有我们必须使用 annotate(prev_sum_order=Sum('prev_order_items__qty')) 而不是 annotate(prev_sum_order=Sum('item__prev_order_items__qty'))
  • 酷,它成功了 :) 请考虑marking it as accepted answer :)
  • 另外,在一个查询中使用所有注释会产生意想不到的结果。对两个不同的变量使用两个注释查询。它并没有增加数据库点击率。
猜你喜欢
  • 1970-01-01
  • 2018-01-08
  • 2012-09-03
  • 2013-07-11
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 2013-07-18
相关资源
最近更新 更多