0

我有看法。它从模型中获取大约 1000 条记录并计算每两个值。它工作正常,但非常慢约 1 分钟。

我的模型。它包含每天的读数:

class Reading(models.Model):
    meter = models.ForeignKey(Meter, verbose_name=_('meter'))
    reading = models.FloatField(verbose_name=_('reading'))
    code = models.ForeignKey(ReadingCode, verbose_name=_('code'))
    date = models.DateTimeField(verbose_name=_('date'))

    class Meta:
        get_latest_by = 'date'
        ordering = ['-date', ]

    def __unicode__(self):
        return u'%s' % (self.date,)

    @property
    def consumption(self):
        try:
            end = self.get_next_by_date(code=self.code, meter=self.meter)
            return (end.reading - self.reading) / (end.date - self.date).days
        except:
            return 0.0

    @property
    def middle_consumption(self):
        data = []
        current_year = self.date.year
        for year in range(current_year - 3, current_year):
            date = datetime.date(year, self.date.month, self.date.day)
            try:
                data.append(Reading.objects.get(
                    date = date,
                    meter = self.meter,
                    code = self.code
                ).consumption)
            except:
                data.append(0.0)
            for i in data:
                if not i:
                    data.pop(0)
        return sum(data) / len(data)

我的观点。它返回 json,其中包含请求仪表的所有读数以及最近 3 年的计算消耗和计算的中间消耗。

class DataForDayChart(TemplateView):
    def get(self, request, *args, **kwargs):
        output = []
        meter = Meter.objects.get(slug=kwargs['slug'])
        # TODO: Make it faster
        for reading in meter.readings_for_period().order_by('date'):
            output.append({
                "label": reading.date.strftime("%d.%m.%Y"),
                "reading": reading.reading,
                "value": reading.consumption / 1000,
                "middle": reading.middle_consumption / 1000
            })
        return HttpResponse(output, mimetype='application/json')

我应该改变什么以使其更快?

4

2 回答 2

2

性能问题可能是由太多的数据库操作引起的,例如在方法 middle_consumption 你查询数据库至少两次,

 end = self.get_next_by_date(code=self.code, meter=self.meter)
 ...
 data.append(Reading.objects.get(
                date = date,
                meter = self.meter,
                code = self.code
            ).consumption)

您没有显示所有代码,所以我想后续循环中的每个步骤都需要 sql 查询。

for reading in meter.readings_for_period().order_by('date'):

正如你所说,只有1000条记录,也许你可以加载一次数据并在内存中操作关系和计算,这应该会提高整体性能。

于 2012-12-24T08:00:30.570 回答
0

从视图名称来看,我想它的数据在白天变化不大;在这种情况下,我建议您使用缓存。
Django 有一个很好的缓存框架,它的设置和使用非常简单直接,它会立即产生巨大的变化,而不需要太多的努力。


当然,第一次调用还是会很慢;在那里,您可能想要优化它。
优化的常用方法首先是测量,你应该分析视图,看看什么是最慢的函数。
或者,您也可以插入一些打印语句以了解减速发生的要点;这里的优点是您不需要学习如何使用新工具。

也就是说,我最好的猜测是,速度下降发生在调用meter.readings_for_period()(您没有发布其代码)中,并且是由于一些低效的数据库查询 - 例如,最终指示 ORM 逐一检索记录,而不是使用单个选择语句。

于 2012-12-24T08:27:36.093 回答