我有一个将在火花中处理的kafka流。我想将此流的输出写入文件。但是,我想按天对这些文件进行分区,因此每天它将开始写入新文件。可以这样做吗?我希望它保持运行状态,当发生新的一天时,它将切换为写入新文件。
val streamInputDf = spark.readStream.format("kafka")
.option("kafka.bootstrapservers", "XXXX")
.option("subscribe", "XXXX")
.load()
val streamSelectDf = streamInputDf.select(...)
streamSelectDf.writeStream.format("parquet)
.option("path", "xxx")
???
答案 0 :(得分:2)
可以通过提供的
partitionBy
从spark添加分区DataFrameWriter
(用于非流媒体)或DataStreamWriter
(用于非流媒体) 流数据。
下面是签名:
公共DataFrameWriter partitionBy(scala.collection.Seq colNames)
DataStreamWriter partitionBy(scala.collection.Seq colNames) 按文件系统上给定的列对输出进行分区。
DataStreamWriter partitionBy(String ... colNames)对 通过文件系统上给定的列输出。
说明: partitionBy通过public DataStreamWriter partitionBy(String ... colNames) 按文件系统上给定的列对输出进行分区。如果 指定后,输出将放置在类似于Hive的文件系统上 分区方案。例如,当我们通过 一年又一个月,目录布局如下:
- year=2016/month=01/ - year=2016/month=02/分区是最广泛用于优化的技术之一 物理数据布局。它提供了用于跳过的粗粒度索引 当查询对分区进行断言时,不必要的数据读取 列。为了使分区正常工作, 每列中的不同值通常应小于几十 数千。
参数:colNames-(未记录)返回:(未记录)由于: 2.0.0
因此,如果要按年份和月份对数据进行分区,spark会将数据保存到以下文件夹中:
year=2019/month=01/05 year=2019/month=02/05
选项1 (直接写入): 您已经提到过实木复合地板-您可以通过以下方式使用保存为实木复合地板格式:
df.write.partitionBy('year', 'month','day').format("parquet").save(path)
选项2 (使用相同的partitionBy
插入到蜂巢中):
您还可以像下面这样插入配置单元表:
df.write.partitionBy('year', 'month', 'day').insertInto(String tableName)
获取所有配置单元分区:
Spark sql基于配置单元查询语言,因此您可以使用SHOW PARTITIONS
获取特定表中的分区列表。
sparkSession.sql("SHOW PARTITIONS partitionedHiveParquetTable")
结论: 我建议使用选项2 ...因为Advantage是稍后使用的,您可以基于分区查询数据(也可以查询原始数据以了解所收到的内容),并且基础文件可以是镶木地板或orc。
注意:
在创建与.enableHiveSupport()
的会话时,请确保已拥有SparkSessionBuilder
,并确保是否已正确配置hive-conf.xml
等。
答案 1 :(得分:1)
基于this answer,spark应该能够根据年,月和日写入文件夹,这似乎正是您要查找的内容。尚未在Spark Streaming中尝试过它,但希望该示例能使您走上正确的轨道:
df.write.partitionBy("year", "month", "day").format("parquet").save(outPath)
如果没有,您可能可以基于current_date()