在Spark中使用UDF对HIVE表进行查询,再将查询结果RDD写入另一个HIVE表

代码如下:
package xxx
...
import UDF_FUNCTION    // udf1
...

object MyObject {

  case class RecordClass(filed1: String, field2: String)  // table1

  def main(args: Array[String]): Unit = {
    ...
    val hiveContext = new HiveContext(sc)
    hiveContext.udf.register( "UDF_NAME", INPUT => UDF_FUNCTION(INPUT) ) // udf2

    val sql = "select ...UDF_NAME(xxx) from ... where ..." // udf3
    val recordsToHive = hiveContext.sql(sql).map(...)...       // udf4
    
    import hiveContext.implicits._  // table2

    recordsToHive
      .map( r => RecordClass(...) )  // table3
      .toDF()
      .registerTempTable("MY_TABLE_NAME") //table4
    hiveContext.sql("INSERT INTO TABLE hive_table ... SELECT * FROM MY_TABLE_NAME") //table5

    ...
  }
}

 
  
解释如下:该程序使用spark1.5.0版本,其他版本可能会有不同,请查询官网。
1、在Saprk中使用UDF对HIVE表进行查询
 (a)由于自己编写的udf包不在maven库中,所以需进行合并打包:
     使用sbt管理项目,在项目顶层目录下建立lib文件夹,将自己的udf包拷贝到该文件夹下:
 
  

[myname@mycomputer /home/myname/myproject/lib]

$ ls

my-udf.jar

然后在顶层目录进行合并打包

[myname@mycomputer /home/myname/myproject]

$ sbt compile package assembly

之后,udf包就会被合并到项目jar包中

(b)在代码中首先导入需要使用的udf:

        import UDF_FUNCTION    // udf1

(c)在代码中对udf进行注册:

        hiveContext.udf.register( "UDF_NAME", INPUT => UDF_FUNCTION(INPUT) ) // udf2
      其中,"UDF_NAME"为在程序中注册的udf名字,INPUT => UDF_FUNCTION(INPUT) 为该"UDF_NAME"使用的形式。
      这里需要稍微留意的一点是:程序中注册的名字"UDF_NAME"不是必须和被导入的udf函数名相同,事实上程序中注册的udf和导入的udf 函数没有必然联系,"UDF_NAME"只是在程序中注册了一个udf,该udf会按照INPUT => UDF_FUNCTION(INPUT)说明的形式进行处理,之后在hive sql的时候直接使用这个UDF_NAME即可。只不过在实际中使用时,UDF_NAME会调用导入的udf函数,并且注册为相同的名字,以便使用。
 (d)在hive sql时使用注册的udf函数:
 
  
        val sql = "select ...UDF_NAME(xxx) from ... where ..." // udf3
        val recordsToHive = hiveContext.sql(sql).map(...)...       // udf4
 (e)如果出现UDF_FUNCTION未定义的错误,尝试修改spark配置spark-env.sh,增加udf函数jar包的路径:
                    export SPARK_CLASSPATH=...:$path_to/my-udf.jar、
 (f)如果有其他错误,请进行google。
 
  
2、将查询结果RDD写入另一个HIVE表:
 (a)编写case class,该class用于表示RDD转化成的hive表的记录格式:
 
  
        case class RecordClass(field1: String, field2: String)  // table1
 (b)导入HiveContext对象的隐式转换
        import hiveContext.implicits._  // table2
 (c)将RDD进行转换,并注册成hive表
        recordsToHive
          .map( r => RecordClass(...) )  // table3,转换
          .toDF()
          .registerTempTable("MY_TABLE_NAME") //table4,注册成表"MY_TABLE_NAME"
 (d)之后,就可以从RDD注册的表中提取数据,插入另一个表:
 
  
        hiveContext.sql("INSERT INTO TABLE hive_table ... SELECT * FROM MY_TABLE_NAME") //table5
 (e)在插入过程中,如果被插入的表字段不允许为空,则需要在程序中对RDD进行额外处理。若仍有其他问题,请google。


你可能感兴趣的:(spark)