我目前正在从事电信分析项目和新手查询优化工作。要在浏览器中显示结果,需要完整分钟,而只需访问45,000条记录。你能否建议减少展示结果的时间。
我写了以下查询来查找 a 年龄组人员的通话时间:
sigma=0
popn=len(Demo.objects.filter(age_group=age))
card_list=[Demo.objects.filter(age_group=age)[i].card_no
for i in range(popn)]
for card in card_list:
dic=Fact_table.objects.filter(card_no=card.aggregate(Sum('duration'))
sigma+=dic['duration__sum']
avgDur=sigma/popn
以上代码在for循环内迭代年龄组。
模型如下:
class Demo(models.Model):
card_no=models.CharField(max_length=20,primary_key=True)
gender=models.IntegerField()
age=models.IntegerField()
age_group=models.IntegerField()
class Fact_table(models.Model):
pri_key=models.BigIntegerField(primary_key=True)
card_no=models.CharField(max_length=20)
duration=models.IntegerField()
time_8bit=models.CharField(max_length=8)
time_of_day=models.IntegerField()
isBusinessHr=models.IntegerField()
Day_of_week=models.IntegerField()
Day=models.IntegerField()
由于
答案 0 :(得分:4)
试试:
sigma=0
demo_by_age = Demo.objects.filter(age_group=age);
popn=demo_by_age.count() #One
card_list = demo_by_age.values_list('card_no', flat=True) # Two
dic = Fact_table.objects.filter(card_no__in=card_list).aggregate(Sum('duration') #Three
sigma = dic['duration__sum']
avgDur=sigma/popn
答案 1 :(得分:3)
card_list=[Demo.objects.filter(age_group=age)[i].card_no for i in range(popn)]
之类的语句将生成popn
单独的查询和数据库命中。 for
- 循环中的查询也将在数据库中popn
次。作为一般规则,您应该尽量减少使用的查询量,并且只应选择所需的记录。
通过对代码进行一些调整,可以在一个查询中完成。
通常不需要手动指定primary_key,除了一些非常特殊的情况外,最好不要定义任何一个。 Django自动添加一个索引的自动增量主键字段。如果您需要将card_no字段作为唯一字段,并且需要根据此字段查找行,请使用以下命令:
class Demo(models.Model):
card_no = models.SlugField(max_length=20, unique=True)
...
SlugField会自动向列中添加数据库索引,实际上该字段的选择与主键的选择速度一样快。这仍然允许其他方式来访问表格,例如外键(我将在下一点解释),使用Django指定的(稍微)更快的整数字段,并将简化Django中模型的使用。
如果您需要将对象与另一个表中的对象相关联,请使用models.ForeignKey
。 Django为您提供了一整套新功能,不仅可以更轻松地使用模型,还可以通过在SQL查询中使用JOIN
子句来加快查询速度。所以对你来说:
class Fact_table(models.Model):
card = models.ForeignKey(Demo, related_name='facts')
...
related_name字段允许您通过在Django中使用instance.facts
来访问与Demo实例相关的所有Fact_table对象。 (见https://docs.djangoproject.com/en/dev/ref/models/fields/#module-django.db.models.fields.related)
通过这两项更改,您的查询(包括不同age_groups上的循环)可以更改为一个超快速的单击查询,为您提供每个age_group的平均呼叫持续时间:
age_groups = Demo.objects.values('age_group').annotate(duration_avg=Avg('facts__duration'))
for group in age_groups:
print "Age group: %s - Average duration: %s" % group['age_group'], group['duration_avg']
.values('age_group')
仅从Demo的数据库表中选择age_group字段。 .annotate(duration_avg=Avg('facts__duration'))
从values
获取每个唯一的结果(因此每个唯一的age_group),并且对于每个唯一的结果,将获取与该age_group内的任何Demo对象相关的所有Fact_table对象,并计算所有持续时间字段的平均值 - 所有在一个查询中。