spark读取hive是最简单的,构造一个sparksession对象,直接执行SQL就得读取,然后直接insert就能写入。
因为spark客户端配置了你的hive数据库的信息,所以能够直接读取hive数据库。
spark = SparkSession
.builder()
.appName("Java Spark SQL basic example")
.master(evm)
.config("hive.exec.dynamic.partition", "true") //
.config("hive.exec.max.dynamic.partitions.pernode", 10000)
.config("hive.exec.max.dynamic.partitions", 100000)
.config("hive.exec.dynamic.partition.mode", "nonstrict")
.enableHiveSupport() // 启用HIVE数据源,必须参数
.getOrCreate();
// SQL : select * from xxx
public Dataset<Row> readFromHive(String sql) {
if (StringUtils.isBlank(sql)) {
throw new NullPointerException();
}
// 一定要先使用use database,不然你就得在sql中指定base。
spark.sql("use " + dataBaseName);
return spark.sql(sql);
}
// 写入的时候需要输入tableName,才能知道写入到哪一张表里面
public void write2Hive(String tableName, Dataset<Row> rowDataset) {
if (rowDataset == null || rowDataset.count() <= 0 || StringUtils.isBlank(tableName)) {
throw new NullPointerException();
}
rowDataset.show();
rowDataset.printSchema();
// 一定要先使用use database,不然你就得在sql中指定base。
spark.sql("use " + dataBaseName);
// 如果你需要删除分区的话,还需要提前执行一下DB
spark.sql("alter table tablename drop if exists partition (partitions=xxx)");
// repartition不是必须的,建议看数据大小自己去觉得分区数大小,我一般是10W数据一个分区,有的人会说,分区越大越快呗,因为多个分区意味着多线程写入,其实不然,总共就几万条数据,重新分区的时间,单个分区就写完了。只有当数据量足够大的时候才需要重新分区,不然使用默认分区就行
rowDataset.repartition(10).write().insertInto(tableName);
}
详细介绍一下启动参数中对于hive的一些配置:
hive.exec.dynamic.partition
默认值:false Hive 0.9.0之前; true 在Hive 0.9.0及更高版本(HIVE-2835)
添加In:Hive 0.6.0
是否允许DML / DDL中的动态分区。
hive.exec.dynamic.partition.mode
默认值: strict
添加In:Hive 0.6.0
在strict模式下,用户必须指定至少一个静态分区,以防用户意外覆盖所有分区。我ñ nonstrict 模式下,所有分区都允许是动态的。
设置为 nonstrict支持INSERT ... VALUES,UPDATE和DELETE 事务(Hive 0.14.0及更高版本)。有关打开Hive事务所需参数的完整列表,请参阅 hive.txn.manager。
hive.exec.max.dynamic.partitions
默认值: 1000
添加In:Hive 0.6.0
允许总共创建的最大 动态分区数。
hive.exec.max.dynamic.partitions.pernode
默认值: 100
添加In:Hive 0.6.0
允许在每个映射器/ reducer节点中创建的最大 动态分区数。
正常来说,大家基本都会用到动态分区,所以这个参数可以说是必须配置的。