如何使用Hive1.2从s3中的Parquet文件创建外部表?

gwo2fgha  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(542)

我已经在qubole(hive)中创建了一个外部表,它从s3读取parquet(compressed:snappy)文件,但是在执行 SELECT * table_name 我得到除分区列以外的所有列的空值。
我尝试在serdeProperty中使用不同的serialization.format值,但仍然面临相同的问题。在搬走财产的时候 'serialization.format' = '1' 我要走了 ERROR: Failed with exception java.io.IOException:Can not read value at 0 in block -1 in file s3://path_to_parquet/ .
我检查了Parquet文件,能够使用Parquet工具读取数据:


**file_01.snappy.parquet:**

{"col_2":1234,"col_3":ABC}
{"col_2":124,"col_3":FHK}
{"col_2":12515,"col_3":UPO}

**External table stmt:**

CREATE EXTERNAL TABLE parquet_test
(
    col2 int,
    col3 string
)
PARTITIONED BY (col1 date) 
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
)
STORED AS PARQUET
LOCATION 's3://path_to_parquet'
TBLPROPERTIES ('parquet.compress'='SNAPPY');

Result:
col_1   col_2   col_3
5/3/19  NULL    NULL
5/4/19  NULL    NULL
5/5/19  NULL    NULL
5/6/19  NULL    NULL

Expected Result:
col_1   col_2   col_3
5/3/19  1234    ABC
5/4/19  124     FHK
5/5/19  12515   UPO
5/6/19  1234    ABC
hmmo2u0o

hmmo2u0o1#

假设表是使用hive创建的,并且使用spark读取(因为问题被标记为 apache-spark-sql )

数据是如何创建的?

spark支持区分大小写的模式。当我们使用dataframeapi时,可以使用区分大小写的模式进行编写。
例子:

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创建的数据之上创建一个配置单元表时,配置单元将能够正确地读取它,因为它不区分大小写。
而当使用spark读取相同的数据时,它使用hive中的模式(默认情况下为小写),并且返回的行是 null .
为了克服这个问题,spark引入了一个配置 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` 或者 `INFER_ONLY` ,则spark使用metastore表中的模式,将无法读取Parquet文件。属性的默认值为 `INFER_AND_SAVE` 从spark 2.2.0开始。
我们可以检查以下内容,看看问题是否与模式敏感性有关:
1的价值 `spark.sql.hive.caseSensitiveInferenceMode` ( `spark.sql("set spark.sql.hive.caseSensitiveInferenceMode")` (应该揭示这一点)
2如果使用spark创建的数据
三。如果2为真,请检查架构是否区分大小写( `spark.read(<location>).printSchema` ) 4. 如果3使用区分大小写的架构,而1的输出不是 `INFER_AND_SAVE` / `INFER_ONLY` ,套 `spark.sql("set spark.sql.hive.caseSensitiveInferenceMode=INFER_AND_SAVE")` ,删除表,重新创建表并尝试从spark读取数据。

相关问题