Apache Sqoop is a tool designed for efficiently transferring bulk data between?Apache Hadoop?and structured datastores such as relational databases.
Sqoop是RDBMS和Hadoop之間的一個橋梁RDBMS<<==>>Hadoop
平時說的導入導出都是以Hadoop為基準,即
導入:RDBMS==>>Hadoop
導出:RDBMS<<==Hadoop
http://sqoop.apache.org/
Sqoop底層是通過MapReduce來實現的,而且只有map沒有reduce,只負責數據的遷移
一、sqoop-1.4.6-cdh5.7.0部署
1)下載
下載地址:http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.7.0.tar.gz
2)解壓
[hadoop@hadoop001 software]$?tar -zxvf sqoop-1.4.6-cdh5.7.0.tar.gz -C ~/app
3)配環境變量
[hadoop@hadoop001 ~]$ vi .bash_profile
export SQOOP_HOME=/home/hadoop/app/sqoop-1.4.6-cdh5.7.0
export PATH=$SQOOP_HOME/bin:$PATH
[hadoop@hadoop001 ~]$ source .bash_profile
[hadoop@hadoop001 ~]$ which sqoop
~/app/sqoop-1.4.6-cdh5.7.0/bin/sqoop
4)修改sqoop配置文件
[hadoop@hadoop001 ~]$ cd $SQOOP_HOME/conf
[hadoop@hadoop001 conf]$ cp sqoop-env-template.sh sqoop-env.sh
[hadoop@hadoop001 conf]$ vi sqoop-env.sh
export HADOOP_COMMON_HOME=/home/hadoop/app/hadoop-2.6.0
export HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-2.6.0
export HIVE_HOME=/home/hadoop/app/hive-1.1.0-cdh5.7.0
5)copy? mysql驅動到$SQOOP_HOME/lib
6)查看幫助
[hadoop@hadoop001 bin]$ sqoop help
[hadoop@hadoop001 bin]$ sqoop version
[hadoop@hadoop001 bin]$ sqoop list-databases \
> --connect jdbc:mysql://localhost:3306 \
> --username root --password 123456
mysql中驗證一下:
[hadoop@hadoop001 bin]$ sqoop list-tables \
> --connect jdbc:mysql://localhost:3306/ruozedata_basic03 \
> --username root --password 123456
查看mysql
二、常用命令
1.RDBMS==>HDFS導入? ?import
1)--connect? ? ??
Specify JDBC connect string??指定JDBC連接字符串
2)--username <username>
Set authentication?username??設置身份驗證的用戶名
3)--password <password>
Set authentication?password??設置身份驗證密碼
4)--append
Imports data?in append mode? 已追加的方式導入數據
5)--as-textfile
Imports data?as plain?text?(default)??導入數據為純文本(默認)
6)--columns <col,col,col...>
Columns to?import from?table? 選擇要從表導入的列
7)--delete-target-dir
Imports data?in delete mode? 先刪除已有的數據,再導入
8)-e,--query <statment>
Import?results of?SQL?'statement'??導入SQL 'statement'的結果
9)-m,--num-mappers <n>
Use 'n' map?tasks to?import in?parallel?使用n個映射任務并行導入
10)--mapreduce-job-name <name>
Set name for?generated?mapreduce job??為生成的mapreduce作業設置名稱
11)--table <table-name>
Table to read
12)--target-dir <dir>?
HDFS plain?table?destination
13)--where <where clause>
WHERE clause?to use?during?import
14)--fields-terminated-by? <char>
?Sets the field separator character??設置字段分隔符
15)--lines-terminated-by <char>
?Sets the end-of-line character??設置行尾字符
16)--input-fields-terminated-by?<char>
Sets the input field separator??設置輸入字段分隔符
?--input-lines-terminated-by <char>
?Sets the input end-of-line char?設置輸入的行尾字符
17)--create-hive-table
Fail if the target hive?table exists (一般不用)
18)--hive-import
Import tables into Hive? (Uses Hive's default delimiters if none are set.)? 將表導入到Hive中(如果沒有設置,則使用Hive的默認分隔符)
19)--hive-overwrite
Overwrite existing data in?the Hive table
20)--hive-partition-key <partition-key>
Sets the partition key to?use when importing to hive
設置在導入hive時使用的分區鍵
21)--hive-partition-value <partition-value>
Sets the partition value to?use when importing to hive
設置在導入到hive時要使用的分區值
實戰如下:
1)在mysql中新建一個數據庫hivetomysql,并新建一張表emp
create database?hivetomysql;
create table emp (
empno int,
ename varchar(100),
job varchar(100),
mgr int,
hiredate varchar(100),
salary double,
comm double,
deptno int);
2)將hive中ruozedata數據庫下的ruozedata_emp導出至mysql的表emp中
sqoop export \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
--export-dir \hdfs://192.168.137.141:9000/user/hive/warehouse/ruozedata.db/ruozedata_emp \
--input-fields-terminated-by '\t';
若沒有--input-fields-terminated-by '\t'這句,MapReduce會運行失敗,報錯如下:
MapReduce運行日志保存在$HADOOP_HOME/logs/user logs下,MapReduce報錯時可查看相應任務的日志來找到錯誤
加上--input-fields-terminated-by '\t'這句之后,運行成功
3)將emp表格導入到hadoop
a)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp;
再次報錯,提示表格emp沒有主鍵,需要給emp表格增加主鍵
mysql> ALTER TABLE emp
? ? -> ADD PRIMARY KEY (empno);
增加主鍵后再次執行命令,導入成功
默認的splits是4
[hadoop@hadoop001 ~]$ hadoop fs -ls emp
-rw-r--r-- 1 hadoop supergroup 0 2018-06-18 22:05 emp/_SUCCESS
-rw-r--r--? 1 hadoop supergroup? ? ? ? 297 2018-06-18 22:05 emp/part-m-00000
-rw-r--r--? 1 hadoop supergroup? ? ? ? 386 2018-06-18 22:05 emp/part-m-00001
-rw-r--r--? 1 hadoop supergroup? ? ? ? ? 0 2018-06-18 22:05 emp/part-m-00002
-rw-r--r--? 1 hadoop supergroup? ? ? ? 51 2018-06-18 22:05 emp/part-m-00003
這15條數據是怎么分配的呢?
##補充:hadoop fs -ls 和hadoop fs -ls /user/hadoop進的是同一目錄
b)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS;
(將split改為2,并把MapReduce的job名稱命名為?FromMySQLToHDFS)
報錯:ERROR tool.ImportTool: Encountered IOException running import job: org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://192.168.137.141:9000/user/hadoop/emp already exists
emp已經存在
需要加一個語句
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir;
導入成功,并且可以看到number of splits變成了2
打開yarn查看任務
c)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--columns "empno,ename,job,salary,comm" \
--target-dir EMP_COLUMN;
d)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--columns "empno,ename,job,salary,comm" \
--target-dir EMP_COLUMN_SPLIT \
--fields-terminated-by '\t' \
--null-string '' --null-non-string '0';
分隔符變為‘\t’(tab鍵),null變為空,非null字符串變為0
e)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--columns "empno,ename,job,salary,comm" \
--target-dir EMP_COLUMN_WHERE \
--fields-terminated-by '\t' \
--where 'salary>2000';
f)
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--fields-terminated-by '\t' \
--query 'SELECT * FROM emp WHERE empno>=7566';
報錯:Cannot specify --query and --table together.
--query和?--table不可以同時出現,因為query語法里有可能是多表查詢
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--fields-terminated-by '\t' \
--query 'SELECT * FROM emp WHERE empno>=7566';
報錯:When importing query results in parallel, you must specify --split-by.
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--fields-terminated-by '\t' \
--query 'SELECT * FROM emp WHERE empno>=7566' \
--split-by 'empno';
繼續報錯: must contain '$CONDITIONS' in WHERE clause.
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
-m 2 \
--mapreduce-job-name FromMySQLToHDFS \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--fields-terminated-by '\t' \
--query 'SELECT * FROM emp WHERE empno>=7566 AND $CONDITIONS' \
--split-by 'empno';
終于成功了
g)命令封裝
上邊的例子命令太長了,可否封裝到一個腳本里呢?
[hadoop@hadoop001 ~]$ cd shell
[hadoop@hadoop001 shell]$ vi emp.opt
import
--connect
jdbc:mysql://localhost:3306/hivetomysql
--username
root
--password
123456
--table
emp
--delete-target-dir
[hadoop@hadoop001 shell]$ sqoop --options-file emp.opt
2.export? ? ? ? ? ? ? ? RDBMS<<==HDFS
現在mysql中新建一張表emp_demo,且只需要表結構
mysql> create table emp_demo as select * from emp where 1=2;
[hadoop@hadoop001 bin]$ sqoop export \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--mapreduce-job-name FromHDFSToMySQL \
--table emp_demo \
--export-dir /user/hadoop/emp
3.RDBMS==>Hive? ?
1)導入普通表
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
--mapreduce-job-name FromMySQLToHive \
--delete-target-dir \
--create-hive-table \? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(直接自動創建一張表,不建議使用,問題見后續講解)
--hive-database ruozedata \
--hive-table emp_sqoop \
--hive-import
可能會遇到上面兩種報錯的情況,原因是缺少jar包
解決方法:
[hadoop@hadoop001 conf]$ vi sqoop-env.sh
export HADOOP_CLASSPATH=/home/hadoop/app/hive-1.1.0-cdh5.7.0/lib/*
再次運行,繼續報錯:
解決辦法:將$HIVE_HOME/conf下的hive-site.xml拷貝至$SQOOP/HOME/conf
再次運行,成功
為什么說不建議使用--create-hive-table命令呢?
可以看到自動創建的表格是根據mysql中數據的字段類型來確定hive表中的字段類型的,本表中salary和comm都帶小數點,所以,hive表中,salary和comm的字段類型為double。
假如最開始導入的salary和comm的數據中沒有小數點,都是整數,如:
sal和comm便被默認為int類型,往后再插入帶小數點的數據就會出現問題,因此最好事先創建一個hive表,再進行sqoop導入數據到hive表
2)導入分區表
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
--mapreduce-job-name FromMySQLToHive \
--delete-target-dir \
--hive-database ruozedata \
--hive-table ruozedata_emp_partition \
--hive-import \
--hive-partition-key 'pt' \
--hive-partition-value '2018-08-08'
但是,查看表內容發現有問題:
應該是分隔符的問題
sqoop import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp \
--mapreduce-job-name FromMySQLToHive \
--delete-target-dir \
--hive-database ruozedata \
--hive-table ruozedata_emp_partition \
--hive-import \
--hive-partition-key 'pt' \
--hive-partition-value '2018-08-08' \
--fields-terminated-by '\t' \? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (規定分隔符為\t)
--hive-overwrite? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (覆蓋之前數據)
3.hive導出到mysql
現在mysql里創建一張表
mysql> create table emp_export as select * from emp where 1=2;
sqoop export \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp_export \
--export-dir \hdfs://192.168.137.141:9000/user/hive/warehouse/ruozedata.db/ruozedata_emp \
--input-fields-terminated-by '\t';
4.job
先創建一個job
sqoop job --create ruozejob \
-- import \
--connect jdbc:mysql://localhost:3306/hivetomysql \
--username root --password 123456 \
--table emp -m 2 \
--mapreduce-job-name FromHiveToMySQL \
--delete-target-dir;
[hadoop@hadoop001 conf]$ sqoop job --list
[hadoop@hadoop001 conf]$ sqoop job --exec ruozejob