Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark中是否有高效连接的数据体系结构(红移)?_Apache Spark_Apache Spark Sql_Spark Dataframe_Amazon Redshift - Fatal编程技术网

Apache spark Spark中是否有高效连接的数据体系结构(红移)?

Apache spark Spark中是否有高效连接的数据体系结构(红移)?,apache-spark,apache-spark-sql,spark-dataframe,amazon-redshift,Apache Spark,Apache Spark Sql,Spark Dataframe,Amazon Redshift,我有一些数据,我想对它们进行大量的分析查询,我想弄清楚是否有一种机制可以用来存储它们,这样Spark就可以有效地对其进行连接。我有一个使用红移的解决方案,但理想情况下,我更喜欢使用基于S3中文件的解决方案,而不是全天候使用整个红移集群 数据简介 这是一个简化的例子。我们有2个初始CSV文件 个人记录 事件记录 这两个表通过person_id字段链接。person_id在person表中是唯一的。事件与人有多对一的关系 目标 我想了解如何设置数据,以便有效地执行以下查询。我将需要执行许多类似这

我有一些数据,我想对它们进行大量的分析查询,我想弄清楚是否有一种机制可以用来存储它们,这样Spark就可以有效地对其进行连接。我有一个使用红移的解决方案,但理想情况下,我更喜欢使用基于S3中文件的解决方案,而不是全天候使用整个红移集群

数据简介 这是一个简化的例子。我们有2个初始CSV文件

  • 个人记录
  • 事件记录
这两个表通过person_id字段链接。person_id在person表中是唯一的。事件与人有多对一的关系

目标 我想了解如何设置数据,以便有效地执行以下查询。我将需要执行许多类似这样的查询(所有查询都是以每人为基础进行评估的):

查询将生成一个包含4列的数据框,每个人一行

  • person_id-数据集中每个人的person_id
  • 年龄-人员记录中的“年龄”字段
  • 成本-该人员所有事件记录的“成本”字段的总和,其中“日期”为2013年6月
目前我使用Spark解决这个问题的所有解决方案都涉及到重新整理所有数据,这最终会使大量(数亿人)的处理过程变慢。我很满意一个解决方案,它要求我重新排列数据,并将其写入不同的格式,如果这样可以加快以后的查询速度的话

使用红移的解决方案 我可以使用红移以一种相当简单的方式完成此解决方案:

这两个文件都作为红移表加载,带有DISTKEY person\u id、SORTKEY person\u 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数据集写入“bucketBy”-读取CSV文件,然后使用“bucketBy”将其重写为拼花地板文件。对这些拼花地板文件的查询可能会非常快。这将产生类似于红移的数据设置,但拼花地板文件不支持bucketBy
  • 火花拼花地板分区-拼花地板确实支持分区。因为parquet为每个分区键创建了一组单独的文件,所以您必须创建一个要分区的计算列,并使用person_id的散列来创建分区键。但是,当您稍后基于“partition\u key”和“person\u id”在spark中加入这些表时,查询计划仍然执行完整的哈希分区。因此,这种方法并不比每次读取CSV并洗牌更好
  • 存储在拼花地板以外的其他数据格式中-我对此持开放态度,但不知道还有其他数据源可以工作
  • 使用复合记录格式-Parquet支持分层数据格式,因此可以将两个表预联接到分层记录中(其中人员记录有一个“事件”字段,它是一个结构元素数组),然后对其进行处理。当您有分层记录时,有两种处理方法:
    • **使用explode创建单独的记录**-使用这种方法,您可以将数组字段分解成整行,然后使用标准数据帧操作进行分析,然后将它们连接回主表。不幸的是,我无法用这种方法有效地编译查询
    • **使用UDF对子记录**执行操作-这保留了结构并在执行时不进行无序排列,但这是一种笨拙而冗长的编程方式。此外,它还需要大量的UDF,这些UDF对性能不是很好(尽管它们比大规模的数据混乱要好)
在我的用例中,Spark比红移有优势,这在这个简单的例子中并不明显,所以我更喜欢使用Spark。请让我知道,如果我错过了什么,有一个很好的方法

按评论编辑

假设:

  • 使用拼花地板
以下是我将尝试的:

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) 节点/140 vCPU群集,~600GB RAM):

27000000000“事件”(总计1431487“人”)

64000000“人”(约20列)

聚合事件生成和缓存耗时约3分钟

人员缓存耗时约30秒(从网络中拉出,而不是拼花地板)

左键连接花了几秒钟

不缓存“人”导致加入时间延长了几秒钟。然后强制spark广播数百MB的聚合事件,使连接耗时不到1秒


谢谢,但出于几个原因,这对我不太管用。首先,当执行左连接而不是完全内部连接时,颠倒连接顺序会产生不同的结果。其次,我的person表也非常大(数千万),这使得广播资源非常密集。最后,虽然这个查询实际上只有一个左连接,但我通常需要创建多个,因此不能依赖于一个表总是被广播。关于左连接生成不同结果的说法,您完全正确,很抱歉错过了这一点。改为尝试右连接?:)更新了答案,考虑更多,测试更明确。是的,我有机会复习了。我认为首先使用personId“BUCKET BY”可以消除加入过程中需要的所有洗牌。这对我很有帮助,因为我会有很多类似这样的重复查询。我也在这个过程中得到红移数字进行比较。谢谢你的视频。这正是我想要的