0

私は見解を持っています。モデルから約1000レコードを取得し、2つの値ごとに計算します。正しく動作しますが、約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)

私の見解。要求されたメーターのすべての読み取り値と、過去3年間の計算された消費量と計算された中間消費量を含むjsonを返します。

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

パフォーマンスの問題は、db 操作が多すぎることが原因である可能性があります。たとえば、メソッド middle_consumption で db を少なくとも 2 回クエリすると、

 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には、セットアップと使用が非常に簡単で簡単な 優れたキャッシングフレームワークがあり、多くの労力をかけなくてもすぐに大きな違いが生まれます。


もちろん、最初の呼び出しはまだ遅いでしょう。そこで、最適化することをお勧めします。
最適化の通常のアプローチは、何よりもまず、測定することです。ビューのプロファイルを作成して、最も遅い関数を確認する必要があります。
または、printステートメントを挿入して、速度低下が発生する場所の概要を取得することもできます。ここでの利点は、新しいツールの使用方法を学ぶ必要がないことです。

とは言うものの、私の推測では、meter.readings_for_period()(コードを投稿しなかった)への呼び出しで速度が低下します。これは、非効率的なデータベースクエリが原因です。たとえば、最終的には、ORMにレコードを1つずつ取得するように指示します。単一のselectステートメント。

于 2012-12-24T08:27:36.093 に答える