sur*_*nto 8 apache-spark parquet apache-spark-sql
我有一个如下所示的数据框。
itemName, itemCategory
Name1, C0
Name2, C1
Name3, C0
Run Code Online (Sandbox Code Playgroud)
我想将此数据框保存为分区镶木地板文件:
df.write.mode("overwrite").partitionBy("itemCategory").parquet(path)
Run Code Online (Sandbox Code Playgroud)
对于这个数据帧,当我读回数据时,它将具有 String 的数据类型itemCategory。
然而有时,我有来自其他租户的数据框,如下所示。
itemName, itemCategory
Name1, 0
Name2, 1
Name3, 0
Run Code Online (Sandbox Code Playgroud)
在这种情况下,在写入分区后,读回时,生成的数据帧将具有 Int 的数据类型itemCategory。
Parquet 文件具有描述数据类型的元数据。如何指定分区的数据类型,以便将其读回为 String 而不是 Int?
如果将“spark.sql.sources.partitionColumnTypeInference.enabled”设置为“false”,spark 会将所有分区列推断为字符串。
在spark 2.0或更高版本中,你可以这样设置:
spark.conf.set("spark.sql.sources.partitionColumnTypeInference.enabled", "false")
Run Code Online (Sandbox Code Playgroud)
在1.6中,像这样:
sqlContext.setConf("spark.sql.sources.partitionColumnTypeInference.enabled", "false")
Run Code Online (Sandbox Code Playgroud)
缺点是每次读取数据时都必须执行此操作,但至少它有效。
当您按列分区时itemCategory,该数据将存储在文件结构中,而不是实际的 csv 文件中。Spark 根据值推断数据类型,如果所有值都是整数,则列类型将为 int。
一种简单的解决方案是StringType在读取数据后将列转换为:
import spark.implicits._
df.withColumn("itemCategory", $"itemCategory".cast(StringType))
Run Code Online (Sandbox Code Playgroud)
另一种选择是复制列本身。然后其中一列将用于分区,因此保存在文件结构中。但是,其他重复的列将正常保存在镶木地板文件中。要制作副本,只需使用:
df.withColumn("itemCategoryCopy", $"itemCategory")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6556 次 |
| 最近记录: |