Spark SQL:HiveContext不会忽略标题

时间:2016-07-25 11:30:26

标签: hadoop apache-spark hive apache-spark-sql

我有一个spark作业,它从外部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

有关

我正在使用spark 1.6.0

你能帮我解决这个问题:

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

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

提前感谢您的回复。

3 个答案:

答案 0 :(得分:2)

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

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

希望有所帮助!

答案 1 :(得分:1)

我对此限制有一个解决方法,尽管它价格不高,但可以嵌入。

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|
+---+----+

希望对别人有帮助。

答案 2 :(得分:0)

可能的解决方法:

  • 通过JDBC连接到HiveServer2并让Hive进行反序列化 - 将CLASSPATH设置为正确可能很麻烦,可能无法处理没有开箱即用的并行化的数据量。
  • 使用“旧学校”CSV解析器直接阅读CSV,并找到跳过标题的方法(例如参见that question) - 旧学校,是的
  • 使用带有“标题”选项的Spark-CSV plugin直接读取CSV - 显然这是的方式(但要注意对Apache commons-csv.jar的依赖,应该在文档...)

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

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