背景
由于经常给业务做一些导数工作,他们会提供一些id,数量2000以内的时候,可以直接用in 但是记录多了,需要再hive中创建对应表,关联查询得到结果集,经常需要通过hue创建表,上传文件,为了能够偷懒,编写程序,打算实现一个功能。 通过传参方式,根据文件地址,表名称,表字段结构。生成对应的hive表。
实现过程
步骤
- 通过spark 连接hive
- 通过不同参数,创建所对应的表(难点)
传参中可能每次所需创建表的字段都不一样,如何动态的创建不同的表,实现方法有2种
1 是通过反射动态的创建不同元组,然后元组根据属性可以直接映射成表。
2 利用spark sql 数组特性,可以将其拆成对应的表的列,当数组中不存在,当前列也回被赋值为null
第一种方案存在一个问题,就是可能文本中的每一行的长度不一样,如果格式不对,创建的元组可能有多种类型,所以可能会有问题, 直接用第二种方案了
具体过程
导入配置文件 hive-site.xml, core-site.xml, and hdfs-site.xml,maven 配置如下
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.11</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>hadoop-lzo</groupId>
<artifactId>hadoop-lzo</artifactId>
<version>0.4.15</version>
</dependency>
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}
/**
* @Description
* @auther eamon.yu
* @date 2021-04-26
*/
object sinkTableToHive {
def main(args: Array[String]): Unit = {
val inputPath = "file:///C:/Users/eamon.yu/Desktop/express.txt"
val colNames = "express_code,express_name"
val tableName = "tmp.express_info"
// val inputPath = "file:///"+args(0)
// val colNames=args(1)
// val tableName=args(2)
val colSql = getColNames(colNames)
val session = SparkSession.builder.master("local")
.appName("Spark Hive Example").enableHiveSupport
.config("spark.sql.legacy.allowCreatingManagedTableUsingNonemptyLocation", "true") //删除表时,文件没删除,也直接创建表
.config("spark.local.dir", "D:\\work\\tmp")
.getOrCreate
// session.sql("select * from tmp.chatroom_robot_ymz limit 20").show(false);
import session.implicits._
val frame: DataFrame = session.read.textFile(inputPath).map(x => {
val strings = x.split("\t")
strings
})
.toDF("tmpColName")
frame.createOrReplaceTempView("tmpTable")
if (tableName.startsWith("tmp.")) {
session.sql("select " + colSql + " from tmpTable").
write.format("orc").mode(SaveMode.Overwrite).saveAsTable(tableName)
}
//执行
println("-- job execute ex success --")
session.stop()
}
def getColNames(colNames: String): String = {
var result: String = null;
val strings = colNames.split(",")
val sb = new StringBuilder;
for (i <- 0 to strings.size - 1) {
sb.append("nvl(tmpColName[" + i + "],'') as ").append(strings(i)).append(",")
}
result = sb.substring(0, sb.size - 1).toString
result
}
}
示例,打成jar之后本地启动方案
| 参数位置 | 参数名称 |
| 1 | 文件路径 |
| 2 | 表字段名称,以,分割 |
| 3 | 表名称 |
spark-submit --class sinkTableToHive --master local[2] D:\work\ideaproject\testYarn\target\testYarn-1.0-SNAPSHOT.jar C:/Users/eamon.yu/Desktop/express.txt express_code,express_name tmp.express_info

2033

被折叠的 条评论
为什么被折叠?



