hive 表定义:
drop table if exists MUSER_BASICINFO_CPA;
create table MUSER_BASICINFO_CPA
(
USERINDEX STRING,
USERID STRING,
USERIMSI STRING,
REGISTERTYPE STRING,
PROVINDEX STRING,
CITYINDEX STRING,
CREATETIME STRING
)
row format delimited
fields terminated by '\t';
将数据从 oracle同步到 hive:
columns='USERINDEX,USERID,USERIMSI,REGISTERTYPE,PROVINDEX,CITYINDEX,CREATETIME'
sqoop job --create MUSER_BASICINFO_job -- import --connect jdbc:oracle:thin:@//x.x.x.x:1521/odb --table MUSER_BASICINFO --columns=$columns --fields-terminated-by '\t' --lines-terminated-by '\n' --null-string ' ' --null-non-string '0' --direct --hive-import --hive-table MUSER_BASICINFO_CPA --incremental append --check-column USERINDEX --last-value 0 -m 7 --split-by USERINDEX
将数据从 hive同步到 mysql:
columns='USERINDEX,USERID,USERIMSI,REGISTERTYPE,PROVINDEX,CITYINDEX,CREATETIME'
sqoop job --create MUSER_BASICINFO_job -- export --connect jdbc:mysql://10.95.204.19:3306/cpa --table MUSER_BASICINFO_CPA --columns $columns --export-dir /user/hive/warehouse/muser_basicinfo_cpa --input-fields-terminated-by '\t'
定义job的好处是 在需要增量同步的时候,在hive 元数据 数据库中会以 job 的 name 作为记录的唯一标识,会将最后一条记录的 id 记录到 last-value中 那么下次任务从大于这条记录的位置开始读;
启动JOB 命令:
sqoop job --exec MCLIENT_CHANNEL_IMEI_job -- --username xxxx --password xxxxx
将数据从mysql 导入到hive
sqoop import --connect jdbc:mysql://112.64.17.16/cpa –username root –password 123456 --table MUSER_OPENCLIENT --hive-import -m 10 --hive-table muser_openclient_tmp
删除JOB
sqoop job --delete MCLIENT_CHANNEL_IMEI_job
由于 hive底层是mapreducer 首先是 mapreducer 从oracle 读出数据 在hadoop的 用户下面建立 与表名一样的文件夹 里面存放从oracle中读取的数据形成的日志文件,但是这些文件是mapreducer的最终结果,在此之前 会在表名目录下建立临时文件夹用于处理map输出 最后删除临时文件夹,然后才用hive load 命令将数据同步到hive 里 然后 此文件夹下面的mr输出也会消失,这样就会有一个问题,如果job中途失败,那么就会有残存的中间文件在 需要同步的文件夹下面,例如 /MUSER_BASICINFO/log000, 这个时候hive load便会失败, 你会发现 sqoop 任务成功 但是表里面看不到数据;另外如果发现字段全是NULL, 就要好好看看你的表设置的分隔符是否正常(一般是分隔符问题),和字段其实没多大关系(只要列数一样就可以)。
由于 每个map(其实reducer只是原样输出什么也没干)都是一个java进程(map运行前会将需要的资源 包括jar包 待处理数据等复制到工作节点上)因此每个map都会创建数据库连接,如果 设置-m 200 那么就会有200个数据库连接,而且在MAP全工作完毕后 又一起向HIVE 元数据数据库申请连接,因此会给数据库造成压力。。
不要怀疑sqoop的能力 在云平台里面 服务器间的传输速度是可观的,虽然sqoop底层用的是JDBC 但是 我同步了 一张有 100多个字段 五千万条数据的表也就 10来分钟,
一张几个字段 3亿条数据的表也是 不到10分钟, 在HIVE中要利用好分区和桶的概念,比如要统计平台每个用户 每天的下载量,然后将用户一天的行为数据合并成一条记录写入到MYSQL,可以按天做分区,按用户名做桶 这样会提高效率。。。。
本质上来讲 SQOOP 是 JDBC PreparedStatement 批处理 多进程版(不确定每个进程内部是否为多线程,如果不是 我们自己也可以增强),sqoop有个小小的技巧,sqoop是将记录放在JAVABEAN 中每个JAVABEAN是通过 克隆 和赋值来构造。。。。这个可以借鉴一下 如果用反射还要验证CLASS等等 效率比较低,以后遇到类似情况按也用CLONE其实早就思考过,当年思考过 如果spring prototype bean 的获取用clone应该速度快点(当前是通过metadatafactorybean和字节码技术创建)。
最后一句话: 云平台很伟大,但是如果对外界有依赖有时候也很脆弱。。。。 如果想和HADOOP谈一场爱情,就别把他当取款机 白富美,不只是赞美他的光鲜,也要用心理解他,安抚他的脆弱。。。。