Sqoop官网:
http://sqoop.apache.org/
*) Sqoop介绍
Sqoop用来在Hadoop和关系数据库中传递数据。通过sqoop,我们可以方便的将数据从关系数据库导入到HDFS,或者将数据从HDFS导出到关系数据库。
参考链接:
http://blog.csdn.net/yfkiss/article/details/8700480
*) 简单的sample案例
目标: 把oracle中全表数据导入到hdfs文件系统中
1) 在Oracle中添加如下表:
CREATE TABLE tb_message
(
ID INT PRIMARY KEY,
MSGID INT,
MESSAGE VARCHAR(256)
);
2). 添加如下数据:
INSERT INTO tb_message(ID, MSGID, MESSAGE) VALUES(1, 1001, 'message 1');
INSERT INTO tb_message(ID, MSGID, MESSAGE) VALUES(2, 1002, 'message 2');
INSERT INTO tb_message(ID, MSGID, MESSAGE) VALUES(3, 1003, NULL);
3). 数据验证
SELECT * FROM tb_message;
ID MSGID MESSAGE
---------- -------------------------------------
1 1001 message 1
2 1002 message 2
3 1003
4). 创建目标目录
sudo -u hdfs hdfs dfs -mkdir -p /sqoop-test/data
5). 采用sqoop import命令导入
sqoop import --connect jdbc:oracle:thin:@<oralce_server_ip>:<oracle_server_port>:<sid> --username <username> --password <password> --table <table_name> --columns <col,col,col…> --target-dir <hdfs_location> -m <map-number>
sudo -u hdfs sqoop import --connect jdbc:oracle:thin:@172.16.1.108:1521:XE --username SYSTEM --password tiger --table tb_message --columns ID,MSGID,MESSAGE --target-dir /sqoop-test/data/message -m 1
6). hdfs文件验证
sudo -u hdfs hdfs dfs -cat /sqoop-test/data/message/part-m-00000
1,1001,message 1
2,1002,message 2
3,1003,null
作为一个简单的sample, 其整个过程还是比较简单易懂的.
*) Sqoop命令行参数详解
import
用于从RDMS到HDFS的数据导出
export
用于从HDFS从RDMS的数据导入
--append
用于数据的追加
--connect JDBC连接串
常见的mysql/oracle连接字符串如下:
mysql: jdbc:mysql://<server_ip>:<server_port>/<dbname>
oracle: jdbc:oracle:thin:@<server_ip>:<server_port>:<dbname>
--username
数据库登录用户名
--password
数据库登录用户密码, 可借用-P来从console中输入
--table
指定导入/导出的数据库表名
--columns
指定导出的列名, 各个列名通过','分割, 如id,msgid
--target-dir
指定导出的hdfs路径
--num-mappers
指定map的任务数, 简写为-m
以上为常见的命令行参数, 具体详细的参数请查见官方用户手册:
http://sqoop.apache.org/docs/1.4.4/SqoopUserGuide.html
*) 性能分析
对于两种方案:
RDBMS -> Local File -> HDFS
RDBMS -> Sqoop -> HDFS
性能对比:
#) 采用JDBC的方式, 使得其导入/导出的性能, 未必比RDBMS自带的导入/导出工具好, 事实上表现要差
#) sqoop进行数据导入/导出, 其可靠性更好
#) Sqoop还支持导入/导出到Hive/Hbase中
优化方案:
并行导入
1). 调大--num-mappers值, 启动多个map任务去加速
但对于没有主键的表, 会执行失败, 并报如下错误:
14/06/25 17:47:33 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-hdfs/compile/a1525a92a1a74988ed98d367452e7fa8/tb_nopk_table.jar
14/06/25 17:47:33 ERROR tool.ImportTool: Error during import: No primary key could be found for table tb_nopk_table. Please specify one with --split-by or perform a sequential import with '-m 1'.
大意是没有主键的表, sqoop不允许指定多个map任务, 只允许'-m 1', 即导入/导出工作必须串行执行.
2). 指定--split-by, 选定适合拆分的字段
--split-by字段适合于没有主键的表数据的导入/导出, 其参数和--num-mapper配合使用
3). 人为拆分多个Sqoop命令
选定适合拆分的字段, 指定--where作为范围隔离, 启动多个sqoop命令同时执行
比如:
sqoop import ... --table tb_message --where "ID > 0 AND ID <= 1000"
sqoop import ... --table tb_message --where "ID > 1000 AND ID <= 2000"
sqoop import ... --table tb_message --where "ID > 2000 AND ID <= 3000"
可参考: http://www.cnblogs.com/gpcuster/archive/2011/03/01/1968027.html
*) Sqoop其他疑惑
1. 数据一致性问题
export中途停止, 会导致数据不一致性的情况, 即partially-complete export.
2. 对Value为NULL, 如何处理?
默认情况, 如果sqoop命令不指定相关参数, 若字段值为空, 则写入到文件中为"NULL", 若想要特殊处理, 可以指定--null-string, --null-non-string两参数来处理.
--null-string <null-string> The string to be written for a null value for string columns
--null-non-string <null-string> The string to be written for a null value for non-string columns
在import的时候, 指定
--null-string '\\N'
--null-non-string '\\N'
在export的时候, 指定
--input-null-string '\\N'
--input-null-non-string '\\N'