如何使用 spark 在 Hive 中正确加载数据?
Posted
技术标签:
【中文标题】如何使用 spark 在 Hive 中正确加载数据?【英文标题】:How do I load data correctly in Hive using spark? 【发布时间】:2017-06-28 05:15:53 【问题描述】:我想输入看起来像-
的数据"58;""management"";""married"";""tertiary"";""no"";2143;""yes"";""no"";""unknown"";5;""may"";261;1;-1;0;""unknown"";""no"""
"44;""technician"";""single"";""secondary"";""no"";29;""yes"";""no"";""unknown"";5;""may"";151;1;-1;0;""unknown"";""no"""
"33;""entrepreneur"";""married"";""secondary"";""no"";2;""yes"";""yes"";""unknown"";5;""may"";76;1;-1;0;""unknown"";""no"""
"47;""blue-collar"";""married"";""unknown"";""no"";1506;""yes"";""no"";""unknown"";5;""may"";92;1;-1;0;""unknown"";""no"""
我的创建表语句是 as-
sqlContext.sql("create table dummy11(age int, job string, marital string, education string, default string, housing string, loan string, contact string, month string, day_of_week string, duration int, campaign int, pday int, previous int, poutcome string, emp_var_rate int, cons_price_idx int, cons_conf_idx int, euribor3m int, nr_employed int, y string)row format delimited fields terminated by ';'")
当我运行语句时-
sqlContext.sql("from dummy11 select age").show()
或
sqlContext.sql("from dummy11 select y").show()
它返回 NULL
值而不是正确的值,尽管其他值是可见的
那我该如何纠正呢?
【问题讨论】:
你是如何读取数据的? 当您考虑您的第一张唱片时;它有 17 个字段(将;
视为 delim),但在您的查询中,您定义了 21 个字段,对吗!!
sqlContext.sql("load data inpath 'hdfs://user/nikita.jaiswal25_gmail/dataset.csv' into table dummy11")
@RaktotpalBordoloi 是的,这是正确的......我如何正确阅读?我也必须声明这些字段,因为我的数据集很大。它只是我用来检查错误的虚拟 4 行。其余数据也可能有 21 个值。这种类型的输入在 Hive 中是否可行。
分隔符是必需的,即使这些记录没有任何值 - 在 hive 中。 ----->>> 因此,根据查询,前 17 个字段(来自您定义的 DDL)填充了值;其余部分填充为 NULL。
【参考方案1】:
由于您使用的是 Hive QL 语法,因此您需要在处理之前验证输入数据。
在您的数据中,很少有记录的列数少于 DDL 中定义的实际列数。
因此,对于这些记录,其余列(从最后一个)设置为 NULL;因为该行没有足够的值。
这就是为什么,最后一列 y
的值是 NULL
。
另外,在 DDL 中,第一个字段的数据类型是 INT
;但在记录中,第一个字段值为:
"58
"44
"33
由于"
,这些值没有被类型转换为INT
;将字段值设置为NULL
。
根据您提供的 DDL 和数据,值设置为:
age "58
job ""management""
marital ""married""
education ""tertiary""
default ""no""
housing 2143
loan ""yes""
contact ""no""
month ""unknown""
day_of_week 5
duration ""may""
campaign 261
pday 1
previous -1
poutcome 0
emp_var_rate ""unknown""
cons_price_idx ""no""
cons_price_idx NULL
cons_conf_idx NULL
euribor3m int NULL
nr_employed NULL
y NULL
检查最后 5 列的 NULL
值。
因此,如果这不是预期的,您需要先验证数据,然后再继续。
对于age
列,如果需要INT
类型,请清理数据以删除不需要的"
字符。
解决方法
作为解决方法,您可以在开始时将age
定义为STRING
,因为使用火花转换来解析第一个字段并将其转换为INT
import org.apache.spark.sql.functions._
val ageInINT = udf (make: String) =>
Integer.parseInt(make.substring(1))
df.withColumn("ageInINT", ageInINT(df("age"))).show
df
是您在执行 hive DDL 时创建的数据框,列 age
为 sTRING
。
现在,您可以对新列 ageInINT
执行操作,而不是对具有 INTEGER
值的列 age
执行操作。
【讨论】:
【参考方案2】:由于您的数据在年龄之前包含"
,因此它被视为字符串。在代码中,您已将其定义为 int
,因此 sql 解析器正在尝试查找整数值,因此您将获得 null
记录。将age int
更改为age string
,您将能够看到结果。
请参阅下面使用 Spark HiveContext
的工作示例。
import org.apache.spark.sql.hive.HiveContext;
import org.apache.spark.sql.types._
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
val sc = new SparkContext(conf)
val sqlContext = new HiveContext(sc)
sqlContext.sql("create external table dummy11(age string, job string, marital string, education string, default string, housing string, loan string, contact string, month string, day_of_week string, duration int, campaign int, pday int, previous int, poutcome string, emp_var_rate int, cons_price_idx int, cons_conf_idx int, euribor3m int, nr_employed int, y string)row format delimited fields terminated by ';' location '/user/skumar143/stack/'")
sqlContext.sql("select age, job from dummy11").show()
它的输出:
+---+----------------+
|age| job|
+---+----------------+
|"58| ""management""|
|"44| ""technician""|
|"33|""entrepreneur""|
|"47| ""blue-collar""|
+---+----------------+
【讨论】:
在这里您已将age
声明为字符串。我需要在进一步计算中使用age
。我不能将其保留为string
,因为它不会被计算。我们需要将其设为int
,以便它可以用于数学计算。
那么请使用不同的方法来解析数据。创建一个数据框和临时表来解析数据,然后将其加载到最终表中。其他解决方法是将此列转换为数字类型或删除所有想要的"
。以上是关于如何使用 spark 在 Hive 中正确加载数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spark 将镶木地板文件加载到 Hive 表中?