Dataframe 使用数据帧在Spark中使用数据差异(增量)
我在hdfs中有一个拼花文件作为数据的初始加载。接下来的所有拼花只是这些数据集,这些数据集每天都会更改为初始荷载(按时间顺序)。这是我的三角洲。 我想读取所有或几个拼花地板文件,以获得特定日期的最新数据。增量也可以包含新记录 例如: 初始数据(文件夹:/path/spezific_Data/20180101):Dataframe 使用数据帧在Spark中使用数据差异(增量),dataframe,apache-spark,hadoop,bigdata,parquet,Dataframe,Apache Spark,Hadoop,Bigdata,Parquet,我在hdfs中有一个拼花文件作为数据的初始加载。接下来的所有拼花只是这些数据集,这些数据集每天都会更改为初始荷载(按时间顺序)。这是我的三角洲。 我想读取所有或几个拼花地板文件,以获得特定日期的最新数据。增量也可以包含新记录 例如: 初始数据(文件夹:/path/spezific_Data/20180101): ID| Name | Street | 1 | "Tom" |"Street 1"| 2 | "Peter"|"Street 2"| ID| Name | Street
ID| Name | Street |
1 | "Tom" |"Street 1"|
2 | "Peter"|"Street 2"|
ID| Name | Street |
1 | "Tom" |"Street 21"|
ID| Name | Street |
2 | "Peter" |"Street 44"|
3 | "Hans" | "Street 12"|
ID| Name | Street |
2 | "Hans" |"Street 55"|
Delta 1(文件夹:/path/spezific_data/20180102):
ID| Name | Street |
1 | "Tom" |"Street 1"|
2 | "Peter"|"Street 2"|
ID| Name | Street |
1 | "Tom" |"Street 21"|
ID| Name | Street |
2 | "Peter" |"Street 44"|
3 | "Hans" | "Street 12"|
ID| Name | Street |
2 | "Hans" |"Street 55"|
Delta 2(文件夹::/path/spezific_data/20180103):
ID| Name | Street |
1 | "Tom" |"Street 1"|
2 | "Peter"|"Street 2"|
ID| Name | Street |
1 | "Tom" |"Street 21"|
ID| Name | Street |
2 | "Peter" |"Street 44"|
3 | "Hans" | "Street 12"|
ID| Name | Street |
2 | "Hans" |"Street 55"|
Delta 3(文件夹::/path/spezific_data/20180105):
ID| Name | Street |
1 | "Tom" |"Street 1"|
2 | "Peter"|"Street 2"|
ID| Name | Street |
1 | "Tom" |"Street 21"|
ID| Name | Street |
2 | "Peter" |"Street 44"|
3 | "Hans" | "Street 12"|
ID| Name | Street |
2 | "Hans" |"Street 55"|
可能某一天有增量,但在第二天加载。(看看Delta 2和Delta 3)
所以文件夹/path/spezific_data/20180104确实存在,我们永远不想加载这个日期。
现在我想加载不同的案例
new_df=delta_df.union(initila_df).dropDuplicates(“ID”)
delta_df=spark.read.parqeut(“hdfs:/mypath/20180103/”)
new_df=delta_df.union(new_df).dropDuplicates(“ID”)
但我认为这不是一个好办法
当前加载时间很长(一小时) 更新1:
我试着做这样的事。如果我运行此代码,它将遍历所有日期,直到我的enddate(我在println(date)上看到)。之后,我得到一个Java.lang.StackOverflower错误。 错误在哪里
import org.apache.spark.sql.functions.col
import util.control.Breaks._
var sourcePath = "hdfs:sourceparth/"
var destinationPath = "hdfs:destiantionpath/result"
var initial_date = "20170427"
var start_year = 2017
var end_year = 2019
var end_month = 10
var end_day = 31
var m : String = _
var d : String = _
var date : String = _
var delta_df : org.apache.spark.sql.DataFrame = _
var doubleRows_df : org.apache.spark.sql.DataFrame = _
//final DF, initial load
var final_df = spark.read.parquet(sourcePath + initial_date + "*")
breakable{
for(year <- 2017 to end_year; month <- 1 to 12; day <- 1 to 31){
//Create date String
m = month.toString()
d = day.toString()
if(month < 10)
m = "0" + m
if(day < 10)
d = "0" + d
date = year.toString() + m + d
try{
//one delta
delta_df = spark.read.parquet(sourcePath + date + "*")
//delete double Rows (i want to ignore them
doubleRows_df = delta_df.groupBy("key").count().where("count > 1").select("key")
delta_df = delta_df.join(doubleRows_df, Seq("key"), "leftanti")
//deletes all (old) rows in final_df, that are in delta_df
final_df = final_df.join(delta_df, Seq("key"), "leftanti")
//add all new rows in delta
final_df = final_df.union(delta_df)
println(date)
}catch{
case e:org.apache.spark.sql.AnalysisException=>{}
}
if(day == end_day && month == end_month && year == end_year)
break
}
}
final_df.write.mode("overwrite").parquet(destinationPath)
import org.apache.spark.sql.functions.col
导入util.control.Breaks_
var sourcePath=“hdfs:sourceparth/”
var destinationPath=“hdfs:destinationPath/result”
风险值初始日=“20170427”
风险值起始年=2017年
var年末=2019年
月底风险值=10
var结束日=31
变量m:String=_
变量d:字符串=_
变量日期:字符串=_
var delta_df:org.apache.spark.sql.DataFrame=_
var doubleRows_df:org.apache.spark.sql.DataFrame=_
//最终DF,初始荷载
var final\u df=spark.read.parquet(源路径+初始日期+“*”)
易碎的{
年
distinct
或dropDuplicates
不是一个选项,因为您无法控制将采用哪些值。很可能发生的情况是,不会添加新值,而保留旧值
您需要在ID
上执行join
操作-请参见连接类型。然后,连接的行应仅包含旧的、或仅包含新的或两者都包含。当仅包含旧的或仅包含新的行时,您将获取当前的行,当两者都包含时,您将仅获取新的行
如何一次添加多个增量的示例
问题:在每个类别中,什么是最畅销和第二畅销的产品
val dataset = Seq(
("Thin", "cell phone", 6000),
("Normal", "tablet", 1500),
("Mini", "tablet", 5500),
("Ultra thin", "cell phone", 5000),
("Very thin", "cell phone", 6000),
("Big", "tablet", 2500),
("Bendable", "cell phone", 3000),
("Foldable", "cell phone", 3000),
("Pro", "tablet", 4500),
("Pro2", "tablet", 6500))
.toDF("product", "category", "revenue")
val overCategory = Window.partitionBy('category).orderBy('revenue.desc)
val ranked = data.withColumn("rank", dense_rank.over(overCategory))
scala> ranked.show
+----------+----------+-------+----+
| product| category|revenue|rank|
+----------+----------+-------+----+
| Pro2| tablet| 6500| 1|
| Mini| tablet| 5500| 2|
| Pro| tablet| 4500| 3|
| Big| tablet| 2500| 4|
| Normal| tablet| 1500| 5|
| Thin|cell phone| 6000| 1|
| Very thin|cell phone| 6000| 1|
|Ultra thin|cell phone| 5000| 2|
| Bendable|cell phone| 3000| 3|
| Foldable|cell phone| 3000| 3|
+----------+----------+-------+----+
scala> ranked.where('rank <= 2).show
+----------+----------+-------+----+
| product| category|revenue|rank|
+----------+----------+-------+----+
| Pro2| tablet| 6500| 1|
| Mini| tablet| 5500| 2|
| Thin|cell phone| 6000| 1|
| Very thin|cell phone| 6000| 1|
|Ultra thin|cell phone| 5000| 2|
+----------+----------+-------+----+
有关更多详细信息,请参阅
第二-请发布完整的stacktrace,而不仅仅是StackOverflowException
您是否仅限于spark?您描述的用例几乎适用于HBase或其他数据库。这是我的任务。我被告知要使用spark执行此操作。我是这个BigData上下文中的新手。我的第一步是使用spark执行此操作。在此之后,我还可以使用其他技术可以做到这一点,但我如何才能仅使用联接获取特定日期的数据帧?如果初始日期为20180101,我希望加载到20180101,这是31个文件夹。我必须加载31次do 31联接吗?或者我可以加载initial和一个delta。然后在initial中删除所有键,它们位于delta和dann Union initial和delta中?要知道该日期-您需要有一个指定日期的列。例如,您可以在从名称读取数据后进行设置。对于加载多个增量,我认为您有几种方法。一种方法是逐个执行31个联接。另一种方法是读取所有增量,然后从所有增量中找出最新值,然后执行一个联接。要查找需要窗口操作的最新值-