【问题标题】:Time Series in PostgresPostgres 中的时间序列
【发布时间】:2016-07-17 07:37:47
【问题描述】:

我在 Redshift 上有一个庞大的电子商务交易数据库,大约有 9 亿行,标题与此有些相似。

 id | date_stamp | location | item   | amount
001 | 2009-12-28 | A1       | Apples | 2
002 | 2009-12-28 | A2       | Juice  | 2
003 | 2009-12-28 | A1       | Apples | 1
004 | 2009-12-28 | A4       | Apples | 2
005 | 2009-12-29 | A1       | Juice  | 6
006 | 2009-12-29 | A4       | Apples | 2
007 | 2009-12-29 | A1       | Water  | 7
008 | 2009-12-28 | B7       | Juice  | 14

是否可以在项目中找到趋势?例如,如果我想看看“Apples”在 2009 年 12 月 28 日到 2011 年 12 月 28 日期间在 A4 位置的销售表现,我会怎么做?理想情况下,我想生成一个具有正/负趋势的表格,有点类似于这里的帖子 - Aggregate function to detect trend in PostgreSQL 我在 R 中对小型数据集进行了类似的分析,甚至使用 ggplot 对其进行可视化也不是什么大挑战,但是数据库的庞大规模给我带来了一些麻烦,而且查询时间也非常长。 例如,

select * 
from fruitstore.sales
where item = 'Apple' and location = 'A1'
order by date_stamp
limit 1000000;

执行大约需要 2500 秒,并且经常超时。 感谢您对此提供的任何帮助。

【问题讨论】:

  • how "Apples" fared between 2009-12-28 and 2011-12-28, at location A4 到底是什么意思?
  • 向我们展示您的查询、您期望的结果以及需要多长时间。性能问题应该包括EXPLAIN ANALYZE和一些关于表大小、索引、当前时间性能、期望时间等的信息。Slow是一个相对术语,我们需要一个真实的值来比较。
  • 对不起,我将对其进行编辑以使问题更清楚。我的意思是,“苹果”在每天的销售额方面表现如何。
  • select * 你能详细说明你希望结果集显示什么吗?是期间聚合,SUM(amount) GROUP BY month,还是别的什么?

标签: sql postgresql time-series amazon-redshift


【解决方案1】:

看看window functions。它们非常适合这种类型的用例。它们对我来说有点难以理解,但可以为您节省一些 SQL 的严重扭曲。

这将显示您感兴趣的时间段内每天售出多少苹果:

select date_trunc('day', date_stamp) as day, count(*) as sold
from fruitstore.sales
where item = 'Apple' and location = 'A4'
    and date_stamp::date >= '2009-12-28'::date and date_stamp::date <= '2011-12-28'::date
group by 1 order by 1 asc

关于性能,避免在 Redshift 中使用 select *。这是一个列式存储,其中不同列的数据分布在节点上。明确列并仅引用您使用的列将避免 Redshift 在网络上移动大量不需要的数据。

确保为您的桌子选择好的 distkeysortkeys。在时间序列表中,时间戳绝对应该是排序键之一。在您的表上启用压缩也有帮助。

在您的表上安排定期的 VACUUM 和 ANALYZE 运行。

此外,如果有任何方法可以通过在 where 子句中过滤可能的记录来限制您正在查看的数据范围,那么它会很有帮助。例如,如果您知道自己只关心最近几天的趋势,那么限制时间可能会产生巨大的影响,例如:

where date_stamp >= sysdate::date - '5 day'::interval

这是一个 good article 的性能提示。

【讨论】:

    【解决方案2】:

    900M 行对于普通的 Postgres 来说是相当多的。 MPP 变体之一(如 Citus)将能够更好地处理它。

    另一种选择是更改存储数据的方式。一个更有效的结构是每个月/项目/位置有 1 行,并存储一个 int 数量的数组。这会将事情减少到约 3 亿行,这更易于管理。我怀疑您的大多数分析工具无论如何都希望将数据视为数组。

    【讨论】:

    • OP 声明数据在 Redshift 中
    【解决方案3】:

    要过滤 SQL 查询中的结果,您可以使用 WHERE 子句:

    SELECT *
    FROM myTable
    WHERE
         item='Apple' AND
         date_stamp BETWEEN '2009-12-28' AND '2011-12-28' AND
         location = 'A4'
    

    使用聚合函数,您可以汇总某个地点两个日期之间的水果销售情况,例如:

    SELECT item as "fruit", sum(amount) as "total"
    FROM myTable
    WHERE     
         date_stamp BETWEEN '2009-12-28' AND '2011-12-28' AND
         location = 'A4'
    GROUP BY item
    

    你问apples“Fared”的描述性并不可怕,但使用WHERE 子句和聚合函数(不要忘记你的分组依据)可能是你需要瞄准的地方。

    【讨论】:

      猜你喜欢
      • 2013-10-26
      • 2014-10-02
      • 1970-01-01
      • 2012-11-02
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多