【问题标题】:Django Fast Access for Time Series Data时间序列数据的 Django 快速访问
【发布时间】:2021-04-19 12:42:43
【问题描述】:

我正在开发一个使用 Django 和 PostgreSQL 作为后端技术堆栈的 Web 应用程序。

我的 models.py 定义了 2 个关键模型。一个是Product,另一个是Timestamp。 有数以千计的产品,每个产品在数据库中都有多个时间戳(60+)。 时间戳包含有关特定日期的产品性能的信息。

class Product:
    owner = models.ForeignKey(AmazonProfile, on_delete=models.CASCADE, null=True)
    state = models.CharField(max_length=8, choices=POSSIBLE_STATES, default="St.Less")
    budget = models.FloatField(null=True)
    product_type = models.CharField(max_length=17, choices=PRODUCT_TYPES, null=True)
    name = models.CharField(max_length=325, null=True)    
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="children")

   



class Timestamp:
    product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
    product_type = models.CharField(max_length=35, choices=ADTYPES, blank=True, null=True)
    owner = models.ForeignKey(AmazonProfile, null=True, blank=True, on_delete=models.CASCADE)
    clicks = models.IntegerField(default=0)
    spend = models.IntegerField(default=0)
    sales = models.IntegerField(default=0)
    acos = models.FloatField(default=0)
    cost = models.FloatField(default=0)
    cpc = models.FloatField(default=0)
    orders = models.IntegerField(default=0)
    ctr = models.FloatField(default=0)
    impressions = models.IntegerField(default=0)
    conversion_rate = models.FloatField(default=0)
    date = models.DateField(null=True)

我将这些数据用于仪表板,用户应该能够在其中查看他们的产品产品的性能 对于 table 中的某个 daterange

例如,用户可能在表格中有 100 种产品,并希望查看过去 2 周所有数据。对于这种情况,我将在下面描述代码的过程:

    1. 调用后端/服务器
    1. 服务器必须过滤和汇总每个产品的所有时间戳
    1. 服务器将数据发送回客户端
    1. 客户端更新表值

问题是,第 2 步需要大量时间,我不知道如何改进表现

products = Product.objects.filter(name="example")
for product in products:
   product.report_set.filter(date_gte="2021-01-01", date__lte="2011-01-14").aggregate(
      Sum("clicks"), 
      Sum("cost"),
      Sum("sales"))

这就是服务器当前检索所显示产品的时间戳值的方式。 有什么想法可以更有效的方式检索和构建数据

【问题讨论】:

  • 您在此处粘贴的模型没有为产品指定 report_set 相关名称。 (timestamp_set,隐含地,是的。)此外,也没有名为 daterange 的字段 - 如果您不向我们展示您实际使用的内容,这将很难提供帮助。
  • 此外,您拥有的日期字段应该是 DateFieldDateTimeField,除此之外,它应该被索引。
  • @AKX 感谢您的评论。索引是否需要唯一?因为许多时间戳将具有相同的日期值。

标签: python django database postgresql


【解决方案1】:

速度很慢,因为您需要对数据库进行多次查询(在循环中)。
看看分组和注释是否更好(一个查询然后可能查询获取每个产品):-

Timestamp.objects.filter(daterange=["2011-01-01", "2011-01-15"]).values('product').annotate(sum_clicks=Sum("clicks")).annotate(sum_cost=Sum("cost")).annotate(sum_sales=Sum("sales"))

我不知道这是否可行,但如果可以,那就更好了:-

Timestamp.objects.filter(daterange=["2011-01-01", "2011-01-15"]).values('product').annotate(sum_clicks=Sum("clicks")).annotate(sum_cost=Sum("cost")).annotate(sum_sales=Sum("sales")).select_related('product')

编辑:- 回想起来也许这可能会更好:-

products = Product.objects.filter(name="example", report_set__daterange=["2011-01-01", "2011-01-15"]).annotate(sum_clicks=Sum("report_set__clicks")).annotate(sum_cost=Sum("report_set__cost")).annotate(sum_sales=Sum("report_set__sales"))

【讨论】:

    【解决方案2】:

    如果没有更多详细信息,我只能建议进行优化,对于数据库优化,我会按照here 列出的说明进行操作,但要知道,当您加快查询速度时,内存使用量可能会增加。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-24
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多