关于spark以parquet写入时的小问题

本文描述了在使用Spark对DataFrame进行GroupBy操作时遇到的错误,并详细记录了解决过程。通过重命名带有括号的列名,成功避免了在将数据写入HDFS时出现的AnalysisException。

今天使用spark对一个dataframe中的数据以某一个为主键做groupby进行求和,数据类似如下:

scala> userDF.show
+---------+--------+
| userid | count |
+--------+---------+
| 11111111|  102|
| 2222222|    97|
| 3333333|    10|
| 11111111|    24|
+----------+-------+

scala> val dataFrame = userDF.groupBy("userid").sum("count")
dataFrame: org.apache.spark.sql.DataFrame = [uid: string, sum(count): bigint]

scala>dataFrame.repartition(5).write.mode(SaveMode.Overwrite).parquet("hdfs://xxx.xxx.xxx.xxx:8020/userdata/userdata_20181017")

结果出错了,报了下面的错(org.apache.spark.sql.AnalysisException: Attribute name "xxxxx" contains invalid character(s) among ",;{}()\n\t=".):

想来想去,dataframe的数据没问题,根据报错分析下,提示有特殊字符,那在dataframe的表头仅有“sum(count)”,这里面包含有括号,于是想着对dataframe表头进行重命名,代码如下:

scala> val dataFrame = userDF.groupBy("userid").sum("count").toDF("userid", "count")
dataFrame: org.apache.spark.sql.DataFrame = [uid: string, sum(count): bigint]

scala>dataFrame.repartition(5).write.mode(SaveMode.Overwrite).parquet("hdfs://xxx.xxx.xxx.xxx:8020/userdata/userdata_20181017")

结果数据能正确写到hdfs上了。

Spark Structured Streaming中,可以通过设置以下参数来减少小文件的数量和大小: 1. `trigger`: 控制作业如何触发。设置较长的触发间隔可以让Spark在处理完更多数据后再写入文件,从而减少小文件数量。 2. `maxFilesPerTrigger`: 每个触发器产生的最大文件数。较高的值会导致更少的文件,但文件大小可能会增加。 3. `checkpointLocation`: 检查点目录,可以在故障恢复时重用数据,减少重新计算的成本。 4. `outputMode`: 输出模式。如果使用`append`模式,Spark将只追加新数据,而不是重写整个文件。这将减少小文件数量。 另外,可以使用`coalesce`或`repartition`操作来合并小文件。这些操作的区别在于`coalesce`尝试将数据合并到较少的分区中,而`repartition`将数据平均分区到指定的数量。 下面是一个简单的示例代码,演示了如何使用`coalesce`和`trigger`来减少小文件数量: ```python from pyspark.sql.functions import col from pyspark.sql import SparkSession spark = SparkSession.builder.appName("StructuredStreamingExample").getOrCreate() # 从kafka消费数据 df = spark \ .readStream \ .format("kafka") \ .option("kafka.bootstrap.servers", "localhost:9092") \ .option("subscribe", "topic1") \ .option("startingOffsets", "earliest") \ .load() # 转换数据 df = df.select(col("value").cast("string")) # 每5分钟写入一个文件,每个文件最多包含1000条记录,并合并小文件 df \ .writeStream \ .trigger(processingTime="5 minutes") \ .option("maxFilesPerTrigger", 1000) \ .option("checkpointLocation", "/tmp/checkpoint") \ .format("parquet") \ .option("path", "/tmp/output") \ .option("compression", "snappy") \ .option("mergeSchema", "true") \ .option("coalesce", "true") \ .start() \ .awaitTermination() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值