镶木地板上的配置单元外部表未获取数据

Posted

技术标签:

【中文标题】镶木地板上的配置单元外部表未获取数据【英文标题】:hive external table on parquet not fetching data 【发布时间】:2019-05-15 01:17:14 【问题描述】:

我正在尝试创建一个数据管道,其中传入的数据存储到 parquet 中,我创建和外部 hive 表,用户可以查询 hive 表并检索数据。我能够保存 parquet 数据并直接检索它但是当我查询配置单元表它没有返回任何行。我做了以下测试设置

--创建外部蜂巢表 创建外部表 emp ( 身份证双倍, hir_dt 时间戳, 用户字符串 ) 存储为镶木地板 位置'/test/emp';

现在在一些数据上创建了数据框并保存到 parquet。

---创建数据框并插入数据

val employeeDf = Seq(("1", "2018-01-01","John"),("2","2018-12-01", "Adam")).toDF("id","hire_dt","user")
val schema = List(("id", "double"), ("hire_dt", "date"), ("user", "string"))
val newCols= schema.map ( x => col(x._1).cast(x._2)) 
val newDf = employeeDf.select(newCols:_*)
newDf.write.mode("append").parquet("/test/emp")
newDf.show 

--read the contents directly from parquet 
val sqlcontext=new org.apache.spark.sql.SQLContext(sc)
sqlcontext.read.parquet("/test/emp").show 

+---+----------+----+
| id|   hire_dt|user|
+---+----------+----+
|1.0|2018-01-01|John|
|2.0|2018-12-01|Adam|
+---+----------+----+

--read from the external hive table 
spark.sql("select  id,hire_dt,user from  emp").show(false)

+---+-------+----+
|id |hire_dt|user|
+---+-------+----+
+---+-------+----+

如上所示,如果我直接从镶木地板而不是从蜂巢读取数据,我可以看到数据。问题是我在这里做错了什么?我做错了什么,蜂巢没有获取数据。我认为 msck repair 可能是一个原因,但如果我尝试执行 msck repair table 说 table not partitioned,我会出错。

【问题讨论】:

【参考方案1】:

根据您的 create table 语句,您已将位置用作 /test/emp,但在写入数据时,您正在写入 /tenants/gwm/idr/emp。所以你不会在 /test/emp 有数据。

CREATE EXTERNAL HIVE TABLE 创建外部表 emp(id double、hire_dt 时间戳、用户字符串)存储为 parquet location '/test/emp';

请重新创建外部表为

CREATE EXTERNAL HIVE TABLE 创建外部表 emp(id double、hire_dt 时间戳、用户字符串)存储为 parquet location '/tenants/gwm/idr/emp';

【讨论】:

抱歉,发帖时打错字了,因为我想将办公网络中使用的路径更改为通用路径。只是为了确认,问题仍然存在.thnx 以便您快速响应 您可以尝试在您的 spark 代码中描述表 emp 以验证位置。 spark.sql("描述格式化的emp").show(100,false) 这似乎打印精细 col_name data_type id doublehir_dt timestamp user string【参考方案2】:

除了下面 Ramdev 给出的答案外,您还需要谨慎使用日期/时间戳周围的正确数据类型;在创建配置单元表时,镶木地板不支持“date”类型。

为此,您可以将列“hire_dt”的“date”类型更改为“timestamp”。

否则,您通过 spark 持久保存并尝试在 hive(或 hive SQL)中读取的数据将不匹配。在两个地方都将其保持为“时间戳”将解决该问题。我希望它有所帮助。

【讨论】:

感谢您的回复。我尝试将日期更改为时间戳,但它仍然没有返回任何行【参考方案3】:

您的 sparkSession builder() 语句中是否有 enableHiveSupport()。你能连接到蜂巢元存储吗?尝试在您的代码中显示表/数据库,看看您是否可以在您的配置单元位置显示表?

【讨论】:

【参考方案4】:

我在下面的 chgn 下得到了这个。

val dfTransformed = employeeDf.withColumn("id", employeeDf.col("id").cast(DoubleType))
            .withColumn("hire_dt", employeeDf.col("hire_dt".cast(TimestampType))

所以基本上问题是数据类型不匹配以及一些原始代码似乎无法正常工作。所以我做了一个明确的演员,然后写它很好并且能够查询回来。逻辑上两者都在做同样的事情,不知道为什么原始代码不起作用。

val employeeDf = Seq(("1", "2018-01-01","John"),("2","2018-12-01", "Adam")).toDF("id","hire_dt","user")

val dfTransformed = employeeDf.withColumn("id", employeeDf.col("id").cast(DoubleType))
    .withColumn("hire_dt", employeeDf.col("hire_dt".cast(TimestampType))

dfTransformed.write.mode("append").parquet("/test/emp")
dfTransformed.show 

--read the contents directly from parquet 
val sqlcontext=new org.apache.spark.sql.SQLContext(sc)
sqlcontext.read.parquet("/test/emp").show 

+---+----------+----+
| id|   hire_dt|user|
+---+----------+----+
|1.0|2018-01-01|John|
|2.0|2018-12-01|Adam|
+---+----------+----+

--read from the external hive table 
spark.sql("select  id,hire_dt,user from  emp").show(false)
+---+----------+----+
| id|   hire_dt|user|
+---+----------+----+
|1.0|2018-01-01|John|
|2.0|2018-12-01|Adam|
+---+----------+----+

【讨论】:

以上是关于镶木地板上的配置单元外部表未获取数据的主要内容,如果未能解决你的问题,请参考以下文章

使用镶木地板文件作为存储在 Hive 中创建外部表后获取 NULL

将数据帧保存为外部配置单元表

获取分区镶木地板数据帧的最新模式

如何从 pyspark 数据框的模式属性(来自镶木地板文件)中获取特定字段名称的数据类型?

如何根据表中的数据获取镶木地板文件名

如何从配置单元表插入分区表(作为镶木地板)?