spark版本:amazon emr 5.24.0上的2.4.2
我有一个胶水目录表背后的s3Parquet目录。parquet文件具有区分大小写的列名(如 lastModified
). 不管我做什么,我都会得到小写的列名( lastmodified
)使用spark读取胶水目录表时:
for {
i <- Seq(false, true)
j <- Seq("NEVER_INFER", "INFER_AND_SAVE", "INFER_ONLY")
k <- Seq(false, true)
} {
val spark = SparkSession.builder()
.config("spark.sql.hive.convertMetastoreParquet", i)
.config("spark.sql.hive.caseSensitiveInferenceMode", j)
.config("spark.sql.parquet.mergeSchema", k)
.enableHiveSupport()
.getOrCreate()
import spark.sql
val df = sql("""SELECT * FROM ecs_db.test_small""")
df.columns.foreach(println)
}
[1] https://medium.com/@an_chee/why-使用-mixed-case-field-names-in-hive-spark-sql-is-a-bad-idea-95da8b6ec1e0
[2] https://spark.apache.org/docs/latest/sql-data-sources-parquet.html
1条答案
按热度按时间zhte4eai1#
编辑
以下解决方案不正确。
胶水爬虫不应该设置
spark.sql.sources.schema.*
属性,但spark sql应该。spark 2.4中的默认值spark.sql.hive.caseSensitiveInferenceMode
是INFER_AND_SAVE
这意味着spark从底层文件推断模式,并修改表以添加spark.sql.sources.schema.*
属性到SERDEPROPERTIES
. 在我们的案例中,spark未能做到这一点,因为IllegalArgumentException: Can not create a Path from an empty string
由于配置单元数据库类示例的locationUri
属性字符串。这是因为glue数据库没有location属性. 模式保存后,spark从表中读取它。
有办法解决这个问题
INFER_ONLY
,它应该只从文件中推断模式,而不尝试更改表SERDEPROPERTIES
. 但是,这不起作用,因为存在一个spark bug,其中推断的模式是小写的(参见这里)。原液(不正确)
这个错误的发生是因为胶水表
SERDEPROPERTIES
缺少两个重要属性:spark.sql.sources.schema.numParts
spark.sql.sources.schema.part.0
为了解决这个问题,我必须通过glue控制台添加这两个属性(不能用ALTER TABLE …
)我猜这是胶水爬虫的一个bug,它在创建表时不设置这些属性。