You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spark Shell中HiveContext内Lateral View explode是否失效?结果不符预期

搞定Spark HiveContext中Lateral View explode结果不符的问题

我来帮你排查这个预期6条实际8条的问题,大概率是数据或者split函数的行为导致的,咱们一步步来:

先明确问题场景

你创建了Hive外部表aa,字段col1是字符串类型,存储逗号分隔的值;用Spark的HiveContext执行带LATERAL VIEW explode(split(col1, ','))的查询时,结果比预期多了2条。

最可能的原因:split出了空元素

这种情况几乎都是因为原始数据里的col1存在以下情况:

  • 部分行末尾带逗号,比如"1,2,",用split(col1, ',')会得到["1","2",""],explode后就多了一条空值记录
  • 存在col1是空字符串的行,split后得到[""],explode也会生成一条记录
  • 还有可能是连续逗号,比如"a,,b",split后得到["a","","b"],多出来一个空元素

先验证问题所在

你可以在Spark Shell里先跑这条SQL,看看split后的数组是不是有问题:

sql("select col1, split(col1, ',') as split_result from aa").show()

如果输出的split_result里包含空字符串,那就是这个问题无疑了。

解决办法:过滤空元素或者优化split逻辑

给你两种实用的解决方式,根据你的业务数据选就行:

方式1:过滤数组里的空元素

用Spark的filter函数在explode前把空值去掉,SQL写法如下:

select col1, elem
from aa
lateral view explode(filter(split(col1, ','), x -> x != '')) tmp_table as elem

方式2:优化split的正则表达式

如果是首尾逗号或者连续逗号导致的,可以先清理数据再split:

-- 处理首尾逗号 + 正常分割
select col1, elem
from aa
lateral view explode(split(regexp_replace(col1, '^,|,$', ''), ',')) tmp_table as elem

-- 或者直接匹配一个或多个逗号,自动忽略连续逗号
select col1, elem
from aa
lateral view explode(split(col1, ',+')) tmp_table as elem

注意:第二种正则方式会把连续逗号(比如a,,b)当成一个分隔符,得到["a","b"];而第一种清理首尾的方式会保留中间的空元素,根据你的业务需求选。

用DataFrame API实现(更直观)

如果你习惯用Scala代码而不是SQL,也可以这么写:

import org.apache.spark.sql.functions._

// 加载Hive表
val aaDF = sql("select col1 from aa")
// 拆分、展开、过滤空值
val vasOtherDF = aaDF
  .withColumn("elem", explode(split(col1, ',')))
  .filter(col("elem") =!= "")

// 查看结果数量
vasOtherDF.count() // 应该就是你预期的6了

额外排查:对比Hive和Spark的行为

如果在Hive CLI里跑同样的SQL得到6条,但Spark里还是8条,那可能是Spark的Hive兼容配置问题。可以检查下Spark版本(比如1.x和2.x的HiveContext行为有差异),或者是否设置了spark.sql.hive.convertMetastoreOrc这类影响解析的参数。

内容的提问来源于stack exchange,提问作者ankitbaldua

火山引擎 最新活动