Database Django查询优化
我目前从事电信分析项目和查询优化新手。要在浏览器中显示结果,需要完整的分钟,而只需访问45000条记录。你能建议一下缩短展示结果时间的方法吗 我编写了以下查询以查找某个年龄组的人的通话持续时间:Database Django查询优化,database,django,django-models,Database,Django,Django Models,我目前从事电信分析项目和查询优化新手。要在浏览器中显示结果,需要完整的分钟,而只需访问45000条记录。你能建议一下缩短展示结果时间的方法吗 我编写了以下查询以查找某个年龄组的人的通话持续时间: 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
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()
谢谢试试看:
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
试试看:
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
像
card\u list=[Demo.objects.filter(age\u group=age)[i].card\u no for i in range(popn)]
这样的语句将生成popn
单独的查询和数据库点击。for
-循环中的查询也会命中数据库popn
次。一般来说,您应该尽量减少使用的查询量,并且只选择需要的记录
只需对代码进行一些调整,就可以在一个查询中完成
- 通常不需要手动指定主键,在所有情况下,除了一些非常特殊的情况外,最好不要定义任何主键。Django自动添加索引的自动增量主键字段。如果需要将card_no字段作为唯一字段,并且需要基于此字段查找行,请使用以下命令:
SlugField会自动向列中添加数据库索引,基本上,该字段的选择速度与主键一样快。这仍然允许其他方式访问表,例如外键(我将在下一点中解释),使用Django指定的(稍微)快一点的整数字段,并将简化Django中模型的使用class Demo(models.Model): card_no = models.SlugField(max_length=20, unique=True) ...
- 如果需要将对象与另一个表中的对象关联,请使用
。Django为您提供了一整套新功能,不仅使模型更易于使用,还通过在SQL查询中使用models.ForeignKey
子句使许多查询更快。比如你:JOIN
相关的\u name字段允许您使用Django中的class Fact_table(models.Model): card = models.ForeignKey(Demo, related_name='facts') ...
访问与演示实例相关的所有事实表对象。(见附件)instance.facts
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\u group')
仅从演示的数据库表中选择age\u group字段.annotate(duration\u avg=avg('facts\u duration'))
从值中获取每个唯一的结果(因此每个唯一的年龄组),对于每个唯一的结果,将获取与该年龄组中的任何演示对象相关的所有事实表对象,并计算所有持续时间字段的平均值-全部在单个查询中 像card\u list=[Demo.objects.filter(age\u group=age)[i].card\u no for i in range(popn)]
这样的语句将生成popn
单独的查询和数据库点击。for
-循环中的查询也会命中数据库popn
次。一般来说,您应该尽量减少使用的查询量,并且只选择需要的记录
只需对代码进行一些调整,就可以在一个查询中完成
- 通常不需要手动指定主键,在所有情况下,除了一些非常特殊的情况外,最好不要定义任何主键。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')
...
相关的\u name字段允许您使用Django中的instance.facts
访问与演示实例相关的所有事实表对象。(见附件)
通过这两个更改,您的查询(包括不同年龄组的循环)可以更改为一个快速的一键查询,为您提供每个年龄组呼叫的平均持续时间:
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\u group')
仅从演示的数据库表中选择age\u group字段.annotate(duration\u avg=avg('facts\u duration'))
从值中获取每个唯一的结果(因此每个唯一的年龄组),对于每个唯一的结果,将获取与该年龄组中的任何演示对象相关的所有事实表对象,并计算所有持续时间字段的平均值-全部在单个查询中 感谢你的耐心。我从未在几行操作代码中见过如此多的反模式。应该是:card\u list=Demo.objects.filter(age\u group=age)。values\u list('card\u no',flat=True)
?第二个查询(card\u list=demo\u by\u age.values\u list('card\u no',flat=True)#两个
)实际上从未执行,而是在执行第三个查询时用作嵌套的select语句。+1请耐心等待。我从未在几行操作代码中见过如此多的反模式。应该是:card\u list=Demo.objects.filter(age\u group=age)。values\u list('card\u no',flat=True)
?在您的第二个查询(card\u list=demo\u by\u age.values\u list(card\u list=demo\u by\u age.values\u list')中缺少一个引号