如何使用列表优化查询集的使用

时间:2011-03-14 21:32:51

标签: django django-queryset

我的模型有几百万个对象。每个对象代表公司拨打/接听的电话。

为简化起见,我们假设这个模型Call有这些字段:
calldate,context,channel。

我的目标是了解每月每个小时内拨打和接听的平均电话数(按小时加载)。问题是:我需要分别为 port1 port2 找到它。

到目前为止,我的代码工作正常,除了大约需要1分钟才能给出4个月的结果,而且效率非常低。

我做了一些简单的分析,发现扩展占用了大约99%的处理时间:

queryset = Call.objects.filter(calldate__gte='SOME_DATE')
port1, port2 = [],[]
port1.extend(queryset.filter(context__icontains="e1-1"))
port2.extend(queryset.filter(context__icontains="e1-2"))
channels_in_port1 = ["Port/%d-2" % x for x in range(1,32)]
channels_in_port2 = ["Port/%d-2" % x for x in range(32,63)]

for i in channels_in_port1:
    port1.extend(queryset.filter(channel__icontains=i))
for i in channels_in_port2:
    port2.extend(queryset.filter(channel__icontains=i))

port1和port2现在有大约150k个对象组合在一起。

只要我打电话给 port1 port2 ,我就很高兴。其余代码基本上是针对 port1 port2 的循环,它们总结并根据小时/天/月取得平均值。琐碎的东西。

我试图通过使用itertools.chain并链接查询集来避免使用任何“扩展”。然而,这使得处理时间转移到我做琐碎for循环的部分,以便按小时计算负载。

任何替代方案?更好的方法来过滤查询集?
非常感谢!!

2 个答案:

答案 0 :(得分:0)

您是否考虑过使用django的聚合函数? http://docs.djangoproject.com/en/dev/topics/db/aggregation/

答案 1 :(得分:0)

我认为你的问题是第二组扩展,即for循环中的那些,而不是第一组。 (在任何情况下,第一个都是完全没必要的:不是在前面定义一个空列表并扩展它,你可以port1 = list(queryset.filter(context__icontains="e1-1"))。)

无论如何,总结一下我认为你要做的事情:你希望获得特定日期的所有Call个对象,分为两个块,具体取决于channel的值:一个包含它的地方值为0到31,值为32到62之间。

看起来你只需要两个查询就可以做到这一点,而根本没有任何扩展:

port1 = queryset.filter(channel__range=["Port/1-2", "Port/31-2"])
port2 = queryset.filter(channel__range=["Port/1-32", "Port/31-62"])

这不符合您的要求吗?

编辑以回复评论,但这只是您可以扩展或连接的两个查询。您的代码发布的问题在于您正在执行 31 查询并扩展每个端口的操作,这必然是昂贵的。如果你只做一个,加上一个扩展/ concat,那将会便宜得多。