无法读取 parquet 背面的区分大小写的胶水表

yzckvree  于 2021-06-25  发布在  Hive
关注(0)|答案(1)|浏览(453)

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

zhte4eai

zhte4eai1#

编辑

以下解决方案不正确。
胶水爬虫不应该设置 spark.sql.sources.schema.* 属性,但spark sql应该。spark 2.4中的默认值 spark.sql.hive.caseSensitiveInferenceModeINFER_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,它在创建表时不设置这些属性。

相关问题