我有一些数据,其中时间戳列字段很长且具有时代标准,因此我需要使用Spark Scala将数据以yyyy / mm / dd / hh的拆分格式保存
data.write.partitionBy("timestamp").format("orc").save("mypath")
这只是按如下所示的时间戳划分数据
timestamp=1458444061098
timestamp=1458444061198
但我希望它像
└── YYYY
└── MM
└── DD
└── HH
答案 0 :(得分:3)
您可以为此使用各种spark sql日期/时间函数。首先,添加一个从unix时间戳列创建的新日期类型列。
val withDateCol = data
.withColumn("date_col", from_unixtime(col("timestamp", "YYYYMMddHH"))
在此之后,您可以将年,月,日和小时列添加到DF,然后按这些新列进行分区以进行写入。
withDateCol
.withColumn("year", year(col("date_col")))
.withColumn("month", month(col("date_col")))
.withColumn("day", dayofmonth(col("date_col")))
.withColumn("hour", hour(col("date_col")))
.drop("date_col")
.partitionBy("year", "month", "day", "hour")
.format("orc")
.save("mypath")
partitionBy子句中包含的列将不属于文件架构。
答案 1 :(得分:2)
首先,我会警告您过度分区。也就是说,请确保您有足够的数据以使其值得按小时进行分区,否则最终可能会导致很多带有小文件的分区文件夹。我要提醒的第二点是使用分区层次结构(年/月/日/小时),因为它将需要递归分区发现。
话虽如此,如果您确实要按小时细分,我建议将您的时间戳截断为小时,然后分成一个新列,然后按该分区。然后,Spark将足够聪明,可以在您重新读取格式时将其识别为时间戳,并且实际上可以根据需要执行完全过滤。
input
.withColumn("ts_trunc", date_trunc("HOUR", 'timestamp)) // date_trunc added in Spark 2.3.0
.write
.partitionBy("ts_trunc")
.save("/mnt/warehouse/part-test")
spark.read.load("/mnt/warehouse/part-test").where("hour(ts_trunc) = 10")
另一种选择是按日期和一天中的小时进行分区:
input
.withColumn("date", to_date('timestamp))
.withColumn("hour", hour('timestamp))
.write
.partitionBy("date", "hour")
.save("/mnt/warehouse/part-test")