使用Spark SQL的临时表解决一个小问题

最近在使用spark处理一个业务场景时,遇到一个小问题,我在scala代码里,使用spark sql访问hive的表,然后根据一批id把需要的数据过滤出来,本来是非常简单的需求直接使用下面的伪SQL即可:

select * from table where  id in (id1,id2,id3,id4,idn)

但现在遇到的问题是id条件比较多,大概有几万个,这样量级的in是肯定会出错的,看网上文章hive的in查询超过3000个就报错了。

如何解决?

主要有两种解决方法:

(一)分批执行,就是把几万个id,按3000一组查询一次,最后把所有的查询结果在汇合起来。

(二)使用join,把几万个id创建成一张hive表,然后两表关联,可以一次性把结果给获取到。

这里倾向于第二种解决办法,比较灵活和方便扩展,尽量不要把数据集分散,一旦分散意味着客户端需要做更多的工作来合并结果集,比如随便一个sum或者dinstict,如果是第一种则需要在最终的结果集再次sum或者distinct。

下面看看如何使用第二种解决:

由于我们id列表是动态的,每个任务的id列表都有可能变换,所以要满足第二种方法,就得把他们变成一张临时表存储在内存中,当spark任务停止时,就自动销毁,因为他们不需要持久化到硬盘上。

在spark中使用临时表是非常简单的,我们只需要把id列表的数据放入rdd中,然后再把rdd注册成一个张表,就可以和hive库里面已有的表做各种join操作了,一个demo代码如下:

import org.apache.spark.sql.SparkSession


object SparkSQLJoinDemo {

  def main(args: Array[String]): Unit = {

    val spark=SparkSession//
      .builder()
      .appName(" spark sql demo ")
      .enableHiveSupport().getOrCreate()

    import spark.implicits._
    import spark.sql

    sql(" use  hivedb ")//指定hive的db库

    val ids="1,2,3,4,5"//模拟的id列表

    val data=ids.split(",").toSeq//转化成Seq结构

    val school_table=spark.sparkContext.makeRDD(data).toDF("id")//指定列名

    school_table.createOrReplaceTempView("temp_table")//在spark的内存里面创建一张临时表

    //这里假设hive_table是存在hive里面的一张表
    val xr=sql("select * from hive_table where hive_id=id")

    println("数据量:"+xr.count()) //打印数据量

    spark.close()//close

    
  }

}

上面代码里的ids,就是我们需要转化成内存表的数据,然后需要转成Seq,并生成RDD,再通过RDD转成DataFrame,注意如果要使用DF,需要导入 import spark.implicits._包下面的函数,这样就能隐式的直接转成DF,在转成DF的同时,我们给数据指定了列名叫id,这里如果有多列,后面可以继续逗号分隔,添加多个列名,最终我们给它注册成了内存临时表,然后在下面的语句中就可以直接使用hive里面存在的表与内存表进行join,最终我们打印一下成功join后数量,可以验证下程序是否正常运行。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值