背景:
现在市面上有很多厂商将spark以及hadoop的生态组件产品化,在ui界面上拖拽来的组件里编写spark sql,或者写spark代码(java,scala,python),类似于传统的数据集成工具datastage,informatica,kettle,将各个组件连接起来组成工作流定时调度,像这样的产品比如联想LeapHD,数梦DTSphere Studio等等,这样的好处是降低大数据开发门槛,新人可以快速的上手工作,数据运维难度大大降低。但是带来的坏处是使用不灵活,下面讲一下在这样的产品中如何将数据快速的从一张表导入到另一张表。
产品界面上不支持只能写spark sql,不能写hql,所以不支持dfs命令,使用HiveContext来解决这个问题
代码:
import org.apache.spark.SparkConf;
import org.apache.spark.SparkContext;
import org.apache.spark.sql.hive.HiveContext;
public class CopyData {
public static void main(String[] args) {
SparkConf sparkConf=new SparkConf().setAppName("JavaSpark");
SparkContext sc=new SparkContext(sparkConf);
HiveContext hiveContext=new HiveContext(sc);
String HdfsPath="hdfs:///user/hive/warehouse/";
String OriginSchema=args[0].toLowerCase()+".db"; //参数一:源表所在库名
String OriginTable=args[1].toLowerCase(); //参数二:源表所在表名
String NowSchema=args[2].toLowerCase()+".db"; //参数三:目标表库名
String NowTable=args[3].toLowerCase(); //参数四:目标表表名
String OriginaUrl=HdfsPath+OriginSchema+"/"+OriginTable+"/*";
String NowUrl=HdfsPath+NowSchema+"/"+NowTable;
hiveContext.sql("set hive.security.authorization.enabled=false");
hiveContext.sql("set role admin");
hiveContext.sql("dfs -cp "+OriginaUrl+" "+NowUrl);
sc.stop();
}
}
优点:
为什么不适用insert导入数据,我观察了一下,对于大表,9亿条数据,使用insert消耗16-20min,使用上述代码只要7分钟,并且insert时消耗的大量的资源,对于只有3台计算存储节点,节点配置不高的小集群,资源全被这一个任务消耗了,很多任务都在排队等待,而使用dfs -cp,yarn上面只消耗了7g内存。
拓展:
如果要筛选数据插入到另一张表,原表可以做成分区表,导入数据时可以直接把分区下的文件复制到目的表对应的分区下。