我在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秒,并且经常超时。 我对此表示感谢。
答案 0 :(得分:2)
另一个选择是更改存储数据的方式。一个更有效的结构是每个月/ 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无法通过网络移动大量不需要的数据。
确保为表格选择好distkey和sortkeys。在时间序列表中,时间戳肯定应该是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
子句和聚合函数(不要忘记你的分组)可能就是你需要瞄准的地方。