Оптимизация приложения Django для эффективного отображения агрегированных данных из нескольких связанных объектов

Я разрабатываю приложение на Django, в котором пользователи могут создавать и управлять иерархическими структурами данных с несколькими уровнями (в моем случае всего 4 уровня). Приложение должно эффективно отображать агрегированные данные (например, средние значения, суммы и другие более сложные метрики) для каждого уровня на основе агрегированных данных уровня, расположенного ниже него.

Вот упрощенная версия моих моделей данных:

from django.db import models

class Level1(models.Model):
    name = models.CharField(max_length=100)

class Level2(models.Model):
    level1 = models.ForeignKey(Level1, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

class Level3(models.Model):
    level2 = models.ForeignKey(Level2, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

class DataPoint(models.Model):
    level3 = models.ForeignKey(Level3, on_delete=models.CASCADE)
    value = models.FloatField()

Например, агрегированные данные для Level3 объектов будут основаны на DataPoints, агрегированные данные для Level2 объектов будут основаны на агрегированных данных для его связанных Level3 объектов, а агрегированные данные для Level1 моделей будут основаны на агрегированных данных его связанных Level2 объектов.

Это означает, что мне действительно придется пересчитывать агрегированные данные уровня только в том случае, если изменятся данные уровня под ним.

В настоящее время я вычисляю агрегированные данные каждый раз, когда они запрашиваются, но это, вероятно, не очень хорошо для производительности (например, я отображаю агрегированные данные нескольких Level1 объектов одновременно, что означает, что я должен сделать много дорогостоящих вычислений).

Одно из решений, о котором я думаю, - использовать сигналы для повторного вычисления агрегированных данных только при необходимости, а вычисленные данные хранить где-то в базе данных. Однако в этом случае операции записи будут выполняться гораздо медленнее, поскольку придется ждать окончания всех вычислений.

Вернуться на верх