我有数据,我想做很多分析查询,我试图弄清楚是否有一种机制可以用来存储它,以便Spark可以有效地对它进行连接。我有一个使用RedShift的解决方案,但理想情况下更喜欢在S3中使用基于文件的内容,而不是全天候提供整个RedShift群集。
这是一个简化的例子。我们有2个初始CSV文件。
这两个表通过person_id字段链接。 person_id在Person表中是唯一的。事件与人有多对一的关系。
我想了解如何设置数据,以便有效地执行以下查询。我需要执行这样的许多查询(所有查询都是基于每个人进行评估):
查询是生成一个包含4列的数据框,每个人都有1行。
我在解决这个问题时使用Spark的所有当前解决方案都涉及重新调整所有数据,最终导致大量(数亿人)的流程变慢。我很高兴有一个解决方案,要求我重新调整数据并将其写入不同的格式,如果这样可以加快以后的查询。
我可以用一种相当直接的方式使用RedShift来完成这个解决方案:
每个文件都作为RedShift表加载,带有DISTKEY person_id,SORTKEY person_id。这会分发数据,以便人员的所有数据都在一个节点上。以下查询将生成所需的数据框:
select person_id, age, e.cost from person
left join (select person_id, sum(cost) as cost from events
where date between '2013-06-01' and '2013-06-30'
group by person_id) as e using (person_id)
我已经想到了在Spark中处理这个问题的几种可能的方法,但没有一种方法可以满足我的需要。我的想法和问题列在下面:
对于我的用例,Spark比RedShift有优势,在这个简单的例子中并不明显,所以我更喜欢用Spark做这个。如果我遗漏了一些东西并且有一个很好的方法,请告诉我。
答案 0 :(得分:2)
根据评论编辑。
假设:
以下是我要尝试的内容:
val eventAgg = spark.sql("""select person_id, sum(cost) as cost
from events
where date between '2013-06-01' and '2013-06-30'
group by person_id""")
eventAgg.cache.count
val personDF = spark.sql("""SELECT person_id, age from person""")
personDF.cache.count // cache is less important here, so feel free to omit
eventAgg.join(personDF, "person_id", "left")
我刚刚用我的一些数据做了这个,这是怎么回事(9 node / 140 vCPU cluster,~600GB RAM):
27,000,000,000个“事件”(汇总至14,331,487“人”)
64,000,000“人”(约20列)
聚合事件构建和缓存需要大约3分钟
人们缓存需要大约30秒(从网络中拉出来,而不是镶木地板)左连接需要几秒钟
没有缓存“人”导致加入时间延长几秒钟。然后强制火花广播几百MB的聚合事件,使得加入时间不到1秒。