运行环境 centos 5.6 hadoop hive
sqoop是让hadoop技术支持的clouder公司开发的一个在关系数据库和hdfs,hive之间数据导入导出的一个工具
在使用过程中可能遇到的问题:
1 首先安装sqoop,如果你使用的是clouder分发版的话就非常简单
# yum install sqoop
如果用官方版本的话
# cd /etc/yum.repos.d
# wget http://archive.cloudera.com/redhat/cdh/cloudera-cdh3.repo
# yum -y install sqoop
sqoop就会安装完成
2 使用sqoop
首先将mysql-connector-java-5.1.16-bin.jar文件复制到/usr/lib/sqoop/lib文件夹下
3 导入导出数据库
1)列出mysql数据库中的所有数据库命令
# sqoop list-databases --connect jdbc:mysql://localhost:3306/ --username root --password 123456
2)连接mysql并列出数据库中的表命令
# sqoop list-tables --connect jdbc:mysql://localhost:3306/test --username root --password 123456
命令中的test为mysql数据库中的test数据库名称 username password分别为mysql数据库的用户密码
3)将关系型数据的表结构复制到hive中
sqoop create-hive-table --connect jdbc:mysql://localhost:3306/test --table username --username root --password 123456 --hive-table test
其中 --table username为mysql中的数据库test中的表 --hive-table test 为hive中新建的表名称
4)从关系数据库导入文件到hive中
sqoop import --connect jdbc:mysql://localhost:3306/test --username root --password mysql-password --table t1 --hive-import
5)将hive中的表数据导入到mysql中
./sqoop export --connect jdbc:mysql://localhost:3306/test --username root --password admin --table uv_info --export-dir /user/hive/warehouse/uv/dt=2011-08-03
如果报错
11/08/05 10:51:22 INFO mapred.JobClient: Running job: job_201108051007_0010
11/08/05 10:51:23 INFO mapred.JobClient: map 0% reduce 0%
11/08/05 10:51:36 INFO mapred.JobClient: Task Id : attempt_201108051007_0010_m_000000_0, Status : FAILED
java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:350)
at uv_info.__loadFromFields(uv_info.java:194)
at uv_info.parse(uv_info.java:143)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:79)
at com.cloudera.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:38)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at com.cloudera.sqoop.mapreduce.AutoProgressMapper.run(AutoProgressMapper.java:187)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:647)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:323)
at org.apache.hadoop.mapred.Child$4.run(Child.java:270)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1127)
at org.apache.hadoop.mapred.Child.main(Child.java:264)
此错误的原因为sqoop解析文件的字段与MySql数据库的表的字段对应不上造成的。因此需要在执行的时候给sqoop增加参数,告诉sqoop文件的分隔符,使它能够正确的解析文件字段。
hive默认的字段分隔符为'\001'
./sqoop export --connect jdbc:mysql://localhost:3306/datacenter --username root --password admin --table uv_info --export-dir /user/hive/warehouse/uv/dt=2011-08-03 --input-fields-terminated-by '\t'
参考http://archive.cloudera.com/cdh/3/sqoop/SqoopUserGuide.html#_literal_sqoop_create_hive_table_literal
=====================================================
搭建sqoop的eclipse调试环境
a、导入到sqoop到eclipse中:下载sqoop 1.3的tar包解压,我们打开build.xml,发现<target name="eclipse" description="Generate Eclipse project">的target,我们只需要执行,ant eclipse,就可以ant脚本就可以给我们生成eclipse的工程文件,我们只需要在eclipse中导入即可。
b、调试sqoop:由于sqoop bin文件夹中的脚本,sqoop来启动java进程,java进程是sqoop脚本的子进程,sqoop脚本中配置了的许多环境变量需要传到sqoop程序中,所以直接,在eclipse中main函数执行,不能执行,所以需要远程调试java进程。
c、如何进行java进程调试:打开bin\sqoop,最后一行,发现,
exec ${HADOOP_HOME}/bin/hadoop com.cloudera.sqoop.Sqoop "$@",执行这句话,说明执行的hadoop脚本,要想进行远程调试,我们需要在hadoop脚本中加入,我们调试参数,我是这样加的,在hadoop脚本中加入,
HADOOP_DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=9991,server=y,su spend=y",然后在后面的脚本中加入这个选项就行,这样就能远程调试了。
例如,我执行./sqoop import --connect jdbc:mysql://localhost/TEST --username root --password root --table STUDENT,功能把student表中的数据导入到hdfs上,加入调试选项后,进程就会停下来,我们只需要eclipse进行远程调试,就像我们本地代码是一样的,可以打断点,可以看变量的值,很方便,具体eclipse 远程调试可以参照,http://www.ibm.com/developerworks/cn/opensource/os-eclipse-javadebug/,即可。接下就可以学习其源码了。
==============================================================
今天下午碰到了一个诡异的Sqoop问题,一开始认为是奇迹,后来在牛人的协助下才终于找出原因.这里记录下.
我这里通过Sqoop从Mysql中导数据到HDFS,再从HDFS中读取这些数据.我们知道Sqoop会通过SQL语句先获取表结构,然后生成相应的Java类.后来我更改了SQL语句,如之前SELECT AGE,NAME FROM USER;AGE是数值型,NAME是VARCHAR型.后来更改了表结构或者临时SQL转换将AGE换成了VARCHAR.
正常情况下,由于AGE类型已经更改,那么对应Java类也会随着更改.但在Eclipse环境中发生以下不可思议:
Sqoop可以正常获取数据,生成相应的Java class,并且写入到HDFS中.但是在Eclipse中从HDFS中读取这些数据,却报错.报错主要是AGE是STRING,无法转换成Number.如此看来是沿用了老的Java Class,也就是更改SQL以前Sqoop生成的Java Class.
有些不可思议,Sqoop明明会根据SQL重新生成对应的Java Class.看它生成的Java Class,所对应的AGE类型也确实正确.但是什么原因呢?
在牛人的帮助下才知道原因.由于Eclipse中从HDFS中读取刚导入的数据,需要将它生成的Java Class加载进来.而之前生成的Java Class已经被编译成class放在workspace/yourProject/bin目录下.对于Eclipse来说,首先是加载自己的Class,虽然这里Sqoop生成的Java Class才是正宗.所以Eclipse一直用以前的Java Class去解析数据,导致类型不匹配.
如果是使用Sqoop命令,或者不在Eclipse环境里执行或许就不会发生这种问题.
折腾了一下午,也明白了这么一回事.