假设该表是使用 Hive 创建并使用 Spark 读取的,则编写以下答案(因为问题标记为apache-spark-sql
)
数据是如何创建的?
Spark 支持区分大小写的模式。当我们使用数据框 API 时,可以使用区分大小写的模式进行编写。
例子:
scala> case class Employee(iD: Int, NaMe: String )
defined class Employee
scala> val df =spark.range(10).map(x => Employee(x.toInt, s"name$x")).write.save("file:///tmp/data/")
scala> spark.read.parquet("file:///tmp/data/").printSchema
root
|-- iD: integer (nullable = true)
|-- NaMe: string (nullable = true)
请注意,在上面的示例中,保留了区分大小写的功能。
当我们在从 Spark 创建的数据之上创建 Hive 表时,Hive 将能够正确读取它,因为它不区分大小写。
而当使用 Spark 读取相同的数据时,它使用 Hive 中默认小写的模式,并且返回的行是null
.
为了克服这个问题,Spark 引入了一个 config spark.sql.hive.caseSensitiveInferenceMode
。
object HiveCaseSensitiveInferenceMode extends Enumeration {
val INFER_AND_SAVE, INFER_ONLY, NEVER_INFER = Value
}
val HIVE_CASE_SENSITIVE_INFERENCE = buildConf("spark.sql.hive.caseSensitiveInferenceMode")
.doc("Sets the action to take when a case-sensitive schema cannot be read from a Hive " +
"table's properties. Although Spark SQL itself is not case-sensitive, Hive compatible file " +
"formats such as Parquet are. Spark SQL must use a case-preserving schema when querying " +
"any table backed by files containing case-sensitive field names or queries may not return " +
"accurate results. Valid options include INFER_AND_SAVE (the default mode-- infer the " +
"case-sensitive schema from the underlying data files and write it back to the table " +
"properties), INFER_ONLY (infer the schema but don't attempt to write it to the table " +
"properties) and NEVER_INFER (fallback to using the case-insensitive metastore schema " +
"instead of inferring).")
.stringConf
.transform(_.toUpperCase(Locale.ROOT))
.checkValues(HiveCaseSensitiveInferenceMode.values.map(_.toString))
.createWithDefault(HiveCaseSensitiveInferenceMode.INFER_AND_SAVE.toString)
INFER_AND_SAVE
- Spark 推断架构并存储在 metastore 作为表的一部分TBLEPROPERTIES
(desc extended <table name>
应该显示这一点)
如果属性的值不是INFER_AND_SAVE
or ,则 Spark使用INFER_ONLY
metastore 表中的架构,并且无法读取 parquet 文件。该属性的默认值INFER_AND_SAVE
自 Spark 2.2.0 起。
我们可以检查以下问题是否与模式敏感性有关:
1. 的值spark.sql.hive.caseSensitiveInferenceMode
(spark.sql("set spark.sql.hive.caseSensitiveInferenceMode")
应该揭示这一点)
2. 如果使用 Spark 创建的数据
3. 如果 2 为真,请检查模式是否区分大小写(spark.read(<location>).printSchema
) 4 . 如果 3 使用区分大小写的模式并且 1 的输出不是INFER_AND_SAVE
/ INFER_ONLY
,则设置spark.sql("set spark.sql.hive.caseSensitiveInferenceMode=INFER_AND_SAVE")
、删除表、重新创建表并尝试从 Spark 读取数据。