Postgres中的时间序列

时间:2016-03-29 16:09:10

标签: sql postgresql time-series amazon-redshift

我在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

是否有可能在项目中找到趋势?例如,如果我想看看"苹果"在销售方面,在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秒,并且经常超时。 我对此表示感谢。

3 个答案:

答案 0 :(得分:2)

对于Postgres要处理的股票来说,900万行是相当多的。其中一个MPP变体(如Citus)将能够更好地处理它。

另一个选择是更改存储数据的方式。一个更有效的结构是每个月/ item / location有1行,并存储一个int数组。这将把事情减少到约3亿行,这更容易管理。我怀疑大多数分析工具都希望将数据视为数组。

答案 1 :(得分:2)

看看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。在时间序列表中,时间戳肯定应该是sortkeys之一。在表上启用压缩也会有所帮助。

安排在桌面上运行常规VACUUM和ANALYZE。

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

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

这是一个带有效果提示的good article

答案 2 :(得分:0)

要过滤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子句和聚合函数(不要忘记你的分组)可能就是你需要瞄准的地方。