Apache Sqoop

1. sqoop介紹

Apache Sqoop是在Hadoop生態體系和RDBMS體系之間傳送數據的一種工具。來自於Apache軟件基金會提供。
Sqoop工作機制是將導入或導出命令翻譯成mapreduce程序來實現。在翻譯出的mapreduce中主要是對inputformat和outputformat進行定製。
Hadoop生態系統包括:HDFS、Hive、Hbase等
RDBMS體系包括:Mysql、Oracle、DB2等
Sqoop可以理解爲:“SQL 到 Hadoop 和 Hadoop 到SQL”。
在這裏插入圖片描述
站在Apache立場看待數據流轉問題,可以分爲數據的導入導出:
Import:數據導入。RDBMS----->Hadoop
Export:數據導出。Hadoop---->RDBMS

2. sqoop安裝

安裝sqoop的前提是已經具備java和hadoop的環境。
最新穩定版: 1.4.6
配置文件修改:
cd $SQOOP_HOME/conf
mv sqoop-env-template.sh sqoop-env.sh
vi sqoop-env.sh
export HADOOP_COMMON_HOME= /export/servers/hadoop-2.7.5
export HADOOP_MAPRED_HOME= /export/servers/hadoop-2.7.5
export HIVE_HOME= /export/servers/hive
加入mysql的jdbc驅動包
cp /hive/lib/mysql-connector-java-5.1.32.jar $SQOOP_HOME/lib/
驗證啓動
bin/sqoop list-databases
–connect jdbc:mysql://localhost:3306/
–username root --password hadoop
本命令會列出所有mysql的數據庫。
到這裏,整個Sqoop安裝工作完成。

3、 Sqoop導入

“導入工具”導入單個表從RDBMS到HDFS。表中的每一行被視爲HDFS的記錄。所有記錄都存儲爲文本文件的文本數據
下面的語法用於將數據導入HDFS。
$ sqoop import (generic-args) (import-args)
Sqoop測試表數據
在mysql中創建數據庫userdb,然後執行參考資料中的sql腳本:
創建三張表: emp僱員表、 emp_add僱員地址表、emp_conn僱員聯繫表。

3.1 全量導入mysql表數據到HDFS

下面的命令用於從MySQL數據庫服務器中的emp表導入HDFS。
bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–delete-target-dir
–target-dir /sqoopresult
–table emp --m 1
其中–target-dir可以用來指定導出數據存放至HDFS的目錄;
mysql jdbc url 請使用 ip 地址。

爲了驗證在HDFS導入的數據,請使用以下命令查看導入的數據:
hdfs dfs -cat /sqoopresult/part-m-00000
可以看出它會在HDFS上默認用逗號,分隔emp表的數據和字段。可以通過
–fields-terminated-by '\t’來指定分隔符。

1201,gopal,manager,50000,TP
1202,manisha,Proof reader,50000,TP
1203,khalil,php dev,30000,AC
1204,prasanth,php dev,30000,AC
1205,kranthi,admin,20000,TP

3.2 全量導入mysql表數據到HIVE

3.2.1 方式一:先複製表結構到hive中再導入數據
將關係型數據的表結構複製到hive中
bin/sqoop create-hive-table
–connect jdbc:mysql://node-1:3306/sqoopdb
–table emp_add
–username root
–password hadoop
–hive-table test.emp_add_sp
其中:
–table emp_add爲mysql中的數據庫sqoopdb中的表。
–hive-table emp_add_sp 爲hive中新建的表名稱。

從關係數據庫導入文件到hive中
bin/sqoop import
–connect jdbc:mysql://node-1:3306/sqoopdb
–username root
–password hadoop
–table emp_add
–hive-table test.emp_add_sp
–hive-import
–m 1

3.2.2. 方式二:直接複製表結構數據到hive中

bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table emp_conn
–hive-import
–m 1
–hive-database test;
在這裏插入圖片描述

3.3. 導入表數據子集(where過濾)

where可以指定從關係數據庫導入數據時的查詢條件。它執行在數據庫服務器相應的SQL查詢,並將結果存儲在HDFS的目標目錄。
bin/sqoop import
–connect jdbc:mysql://node-1:3306/sqoopdb
–username root
–password hadoop
–where “city =‘sec-bad’”
–target-dir /wherequery
–table emp_add --m 1
在這裏插入圖片描述

3.4. 導入表數據子集(query查詢)

注意事項
使用query sql語句來進行查找不能加參數–table ;
並且必須要添加where條件;
並且where條件後面必須帶一個$CONDITIONS 這個字符串;
並且這個sql語句必須用單引號,不能用雙引號;
bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–target-dir /wherequery12
–query ‘select id,name,deg from emp WHERE id>1203 and $CONDITIONS’
–split-by id
–fields-terminated-by ‘\t’
–m 2
sqoop命令中,–split-by id通常配合-m 10參數使用。用於指定根據哪個字段進行劃分並啓動多少個maptask。

3.5. 增量導入

在實際工作當中,數據的導入,很多時候都是只需要導入增量數據即可,並不需要將表中的數據每次都全部導入到hive或者hdfs當中去,這樣會造成數據重複的問題。因此一般都是選用一些字段進行增量的導入, sqoop支持增量的導入數據。
增量導入是僅導入新添加的表中的行的技術。

–check-column (col)
用來指定一些列,這些列在增量導入時用來檢查這些數據是否作爲增量數據進行導入,和關係型數據庫中的自增字段及時間戳類似。
注意:這些被指定的列的類型不能使任意字符類型,如char、varchar等類型都是不可以的,同時-- check-column可以去指定多個列。
–incremental (mode)
append:追加,比如對大於last-value指定的值之後的記錄進行追加導入。lastmodified:最後的修改時間,追加last-value指定的日期之後的記錄
–last-value (value)
指定自從上次導入後列的最大值(大於該指定的值),也可以自己設定某一值

3.5.1. Append模式增量導入
 執行以下指令先將我們之前的數據導入:
bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–target-dir /appendresult
–table emp --m 1

  • 使用hadoop fs -cat查看生成的數據文件,發現數據已經導入到hdfs中。
  • 然後在mysql的emp中插入2條增量數據:
insert into `userdb`.`emp` (`id`, `name`, `deg`, `salary`, `dept`) values ('1206', 'allen', 'admin', '30000', 'tp');
insert into `userdb`.`emp` (`id`, `name`, `deg`, `salary`, `dept`) values ('1207', 'woon', 'admin', '40000', 'tp');
  • 執行如下的指令,實現增量的導入:
    bin/sqoop import
    –connect jdbc:mysql://node-1:3306/userdb
    –username root --password hadoop
    –table emp --m 1
    –target-dir /appendresult
    –incremental append
    –check-column id
    –last-value 1205
    在這裏插入圖片描述
  • 最後驗證導入數據目錄 可以發現多了一個文件 裏面就是增量數據
    在這裏插入圖片描述

3.5.2. Lastmodified模式增量導入

  • 首先創建一個customer表,指定一個時間戳字段:
create table customertest(id int,name varchar(20),last_mod timestamp default current_timestamp on update current_timestamp);

此處的時間戳設置爲在數據的產生和更新時都會發生改變.

  • 分別插入如下記錄:
insert into customertest(id,name) values(1,'neil');
insert into customertest(id,name) values(2,'jack');
insert into customertest(id,name) values(3,'martin');
insert into customertest(id,name) values(4,'tony');
insert into customertest(id,name) values(5,'eric');

  • 執行sqoop指令將數據全部導入hdfs:

bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–target-dir /lastmodifiedresult
–table customertest --m 1

  • 查看此時導出的結果數據:
    在這裏插入圖片描述
  • 再次插入一條數據進入customertest表
insert into customertest(id,name) values(6,'james')

  • 使用incremental的方式進行增量的導入:

bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table customertest
–target-dir /lastmodifiedresult
–check-column last_mod
–incremental lastmodified
–last-value “2019-05-28 18:42:06”
–m 1
–append
在這裏插入圖片描述
在這裏插入圖片描述

此處已經會導入我們最後插入的一條記錄,但是我們卻發現此處插入了2條數據,這是爲什麼呢?
這是因爲採用lastmodified模式去處理增量時,會將大於等於last-value值的數據當做增量插入。
3.5.3. Lastmodified模式:append、merge-key
使用lastmodified模式進行增量處理要指定增量數據是以append模式(附加)還是merge-key(合併)模式添加
下面演示使用merge-by的模式進行增量更新,我們去更新 id爲1的name字段。

update customertest set name = 'Neil' where id = 1;

更新之後,這條數據的時間戳會更新爲更新數據時的系統時間.
執行如下指令,把id字段作爲merge-key:
bin/sqoop import
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table customertest
–target-dir /lastmodifiedresult
–check-column last_mod
–incremental lastmodified
–last-value “2019-05-28 18:42:06”
–m 1
–merge-key id
由於merge-key模式是進行了一次完整的mapreduce操作,
因此最終我們在lastmodifiedresult文件夾下可以看到生成的爲part-r-00000這樣的文件,會發現id=1的name已經得到修改,同時新增了id=6的數據。
在這裏插入圖片描述

4、 Sqoop導出

將數據從Hadoop生態體系導出到RDBMS數據庫導出前,目標表必須存在於目標數據庫中。
export有三種模式:
默認操作是從將文件中的數據使用INSERT語句插入到表中。
更新模式:Sqoop將生成UPDATE替換數據庫中現有記錄的語句。
調用模式:Sqoop將爲每條記錄創建一個存儲過程調用。

以下是export命令語法:
$ sqoop export (generic-args) (export-args)

4.1. 默認模式導出HDFS數據到mysql

默認情況下,sqoop export將每行輸入記錄轉換成一條INSERT語句,添加到目標數據庫表中。如果數據庫中的表具有約束條件(例如,其值必須唯一的主鍵列)並且已有數據存在,則必須注意避免插入違反這些約束條件的記錄。如果INSERT語句失敗,導出過程將失敗。此模式主要用於將記錄導出到可以接收這些結果的空表中。通常用於全表數據導出。
導出時可以是將Hive表中的全部記錄或者HDFS數據(可以是全部字段也可以部分字段)導出到Mysql目標表。
4.1.1. 準備HDFS數據
在HDFS文件系統中“/emp/”目錄的下創建一個文件emp_data.txt:
1201,gopal,manager,50000,TP
1202,manisha,preader,50000,TP
1203,kalil,php dev,30000,AC
1204,prasanth,php dev,30000,AC
1205,kranthi,admin,20000,TP
1206,satishp,grpdes,20000,GR
4.1.2. 手動創建mysql中的目標表
mysql> USE userdb;
mysql> CREATE TABLE employee (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
deg VARCHAR(20),
salary INT,
dept VARCHAR(10));
4.1.3. 執行導出命令
bin/sqoop export
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table employee
–export-dir /emp/emp_data
在這裏插入圖片描述

4.1.4. 相關配置參數
–input-fields-terminated-by ‘\t’
指定文件中的分隔符
–columns
選擇列並控制它們的排序。當導出數據文件和目標表字段列順序完全一致的時候可以不寫。否則以逗號爲間隔選擇和排列各個列。沒有被包含在–columns後面列名或字段要麼具備默認值,要麼就允許插入空值。否則數據庫會拒絕接受sqoop導出的數據,導致Sqoop作業失敗
–export-dir 導出目錄,在執行導出的時候,必須指定這個參數,同時需要具備–table或–call參數兩者之一,–table是指的導出數據庫當中對應的表,
–call是指的某個存儲過程。
–input-null-string --input-null-non-string
如果沒有指定第一個參數,對於字符串類型的列來說,“NULL”這個字符串就回被翻譯成空值,如果沒有使用第二個參數,無論是“NULL”字符串還是說空字符串也好,對於非字符串類型的字段來說,這兩個類型的空串都會被翻譯成空值。比如:
–input-null-string “\N” --input-null-non-string “\N”

4.2. 更新導出(updateonly模式)

4.2.1. 參數說明
– update-key,更新標識,即根據某個字段進行更新,例如id,可以指定多個更新標識的字段,多個字段之間用逗號分隔。
– updatemod,指定updateonly(默認模式),僅僅更新已存在的數據記錄,不會插入新紀錄。
4.2.2. 準備HDFS數據
在HDFS “/updateonly_1/”目錄的下創建一個文件updateonly_1.txt:
1201,gopal,manager,50000
1202,manisha,preader,50000
1203,kalil,php dev,30000
4.2.3. 手動創建mysql中的目標表
mysql> USE userdb;
mysql> CREATE TABLE updateonly (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
deg VARCHAR(20),
salary INT);
4.2.4. 先執行全部導出操作
bin/sqoop export
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table updateonly
–export-dir /updateonly_1/

4.2.5. 查看此時mysql中的數據
可以發現是全量導出,全部的數據
在這裏插入圖片描述
4.2.6. 新增一個文件
updateonly_2.txt。修改了前三條數據並且新增了一條記錄。上傳至/updateonly_2/目錄下:
1201,gopal,manager,1212
1202,manisha,preader,1313
1203,kalil,php dev,1414
1204,allen,java,1515
4.2.7. 執行更新導出
bin/sqoop export
–connect jdbc:mysql://node-1:3306/userdb
–username root --password hadoop
–table updateonly
–export-dir /updateonly_2/
–update-key id
–update-mode updateonly
4.2.8. 查看最終結果
雖然導出時候的日誌顯示導出4條記錄:
在這裏插入圖片描述
但最終只進行了更新操作
在這裏插入圖片描述

4.3. 更新導出(allowinsert模式)

4.3.1. 參數說明
– update-key,更新標識,即根據某個字段進行更新,例如id,可以指定多個更新標識的字段,多個字段之間用逗號分隔。
– updatemod,指定allowinsert,更新已存在的數據記錄,同時插入新紀錄。實質上是一個insert & update的操作。
4.3.2. 準備HDFS數據
在HDFS “/allowinsert_1/”目錄的下創建一個文件allowinsert_1.txt:
1201,gopal,manager,50000
1202,manisha,preader,50000
1203,kalil,php dev,30000
4.3.3. 手動創建mysql中的目標表
mysql> USE userdb;
mysql> CREATE TABLE allowinsert (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
deg VARCHAR(20),
salary INT);
4.3.4. 先執行全部導出操作
bin/sqoop export
–connect jdbc:mysql://node-1:3306/userdb
–username root
–password hadoop
–table allowinsert
–export-dir /allowinsert_1/

4.3.5. 查看此時mysql中的數據
可以發現是全量導出,全部的數據
在這裏插入圖片描述

4.3.6. 新增一個文件
allowinsert_2.txt。修改了前三條數據並且新增了一條記錄。上傳至/ allowinsert_2/目錄下:
1201,gopal,manager,1212
1202,manisha,preader,1313
1203,kalil,php dev,1414
1204,allen,java,1515
4.3.7. 執行更新導出
bin/sqoop export
–connect jdbc:mysql://node-1:3306/userdb
–username root --password hadoop
–table allowinsert
–export-dir /allowinsert_2/
–update-key id
–update-mode allowinsert
4.3.8. 查看最終結果
導出時候的日誌顯示導出4條記錄:
在這裏插入圖片描述
數據進行更新操作的同時也進行了新增的操作
在這裏插入圖片描述

發佈了41 篇原創文章 · 獲贊 208 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章