Spark SQL:HiveContext 不要忽略标头

Posted

技术标签:

【中文标题】Spark SQL:HiveContext 不要忽略标头【英文标题】:Spark SQL : HiveContext don't ignore header 【发布时间】:2016-07-25 11:30:25 【问题描述】:

我有一个 spark Job,它从外部 Hive 表中读取数据,并在另一个内部 Hive 表中进行一些转换和重新保存数据

val sparkConf = new SparkConf().setAppName("Bulk Merge Daily Load Job")
val sparkContext = new SparkContext(sparkConf)
val sqlContext = new HiveContext(sparkContext)

// Data Ingestion
val my_df = sqlContext.sql("select * from test")

// Transformation 
...
...

// Save Data into Hive
my_df.write.format("orc")
.option("orc.compress","SNAPPY")
.mode(SaveMode.Overwrite)
.saveAsTable("my_internal_table")

外部表是使用 tblproperties 行创建的:

tblproperties ("skip.header.line.count"="1");

我的问题是我在my_internal_table 表的行中发现了一个表示列名称的附加行。

我猜这与issue有关:

我正在使用火花1.6.0

你能帮我解决这个问题吗:

1.6.0 中是否仍然存在此错误? 有什么简单的方法可以避免这种情况吗?

PS:我正在处理大文件 > 10Go。

提前感谢您的回复。

【问题讨论】:

JIRA 仍然“未解决”,很明显没有人在处理它,所以你为什么要问?只需找到解决方法... 您找到解决方案了吗?我有同样的问题 【参考方案1】:

我遇到了同样的问题,但如果你将同一张表保存为 ORC,它应该可以工作。只需创建一个与原始表具有相同架构的新表,但将格式设置为 ORC。然后将原始表中的数据回填到ORC中。

当你从 Spark 读取 ORC 表时,它不应该带入标题行。

希望有帮助!

【讨论】:

【参考方案2】:

我有一个解决这个限制的方法,虽然它有点贵,但可以嵌入。

scala> val dfData1 = spark.sql("select * from db.mytable")
scala> dfData1.show()
+---+----+
| id|name|
+---+----+
| id|name|
|  1| Sam|
|  2| Pam|
| id|name|
|  3| Jim|
+---+----+
scala> val fileHeader = dfData1.head.getString(0)
fileHeader: String = id

scala> val dfRealData = dfData1.filter(col(dfData1.columns(0)) =!= fileHeader)
dfRealData: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string]

scala> dfRealData.show()
+---+----+
| id|name|
+---+----+
|  1| Sam|
|  2| Pam|
|  3| Jim|
+---+----+

希望对某人有所帮助。

【讨论】:

【参考方案3】:

可能的解决方法:

通过JDBC 连接到 HiveServer2 并让 Hive 进行反序列化 - 获得正确的 CLASSPATH 可能会很麻烦,可能无法处理开箱即用的并行化数据量... 直接读取 CSV,使用“old school” CSV 解析器,并找到跳过标题的方法(例如,参见that question)——old school,是的 直接读取 CSV,使用带有选项“header”的Spark-CSV plugin——显然这是要走的路(但请注意对 Apache commons-csv.jar 的依赖,应该在文档中明确说明... )

请注意,当直接点击 CSV 文件时,您将失去让 Hive Metastore 隐藏实际 HDFS 目录(或目录,以防表已分区)的好处——因此您又回到了硬编码代码中的路径。

或者,如果您想要更便携的解决方案,您可以使用Hive Java API 到connect to the MetaStore,导航到您想要的表(可能还有它的分区)的StorageDescriptor,获取HDFS(列表)目录,然后点击其中的文件。你要进入那个任务吗,年轻的圣骑士……? B-)

【讨论】:

以上是关于Spark SQL:HiveContext 不要忽略标头的主要内容,如果未能解决你的问题,请参考以下文章

Spark HiveContext 使用 sql 方法应用 IN 操作

Spark SQL HiveContext - saveAsTable 创建错误的架构

Spark SQL(通过 HiveContext 进行 Hive 查询)总是创建 31 个分区

使用 spark hivecontext 读取外部 hive 分区表的问题

在 spark 1.6 中计数(不同)不能与 hivecontext 查询一起使用

3. Spark SQL解析