Apache Sqoop是一個性能高、易用、靈活的數據導入導出工具,在關係型數據庫與Hadoop之間搭建了一個橋樑。
php
# 應用場景 須要將HDFS或Hive上的數據導出到傳統關係型數據庫中(如MySQL、Oracle等),或者將傳統關係型數據庫中的數據導入到HDFS或Hive上,若是經過人工手動進行數據遷移的話,就會顯得很是麻煩。爲此,可以使用Apache提供的Sqoop工具進行數據遷移。 - 數據遷移 企業大數據平臺關係型數據倉庫中的數據以分析爲主,綜合考慮擴展性、容錯性和成本開銷等方面。若將數據遷移到Hadoop大數據平臺上,能夠方便地使用Hadoop提供的如Hive、SparkSQL分佈式系統等工具進行數據分析。爲了一次性將數據導入Hadoop存儲系統,可以使用Sqoop。 - 可視化分析結果 Hadoop處理的輸入數據規模多是很是龐大的,好比PB級別,但最終產生的分析結果可能不會太大,好比報表數據等,而這類結果一般須要進行可視化,以便更直觀地展現分析結果。目前絕大部分可視化工具與關係型數據庫對接得比較好,所以,比較主流的作法是,將Hadoop產生的結果導入關係型數據庫進行可視化展現。 - 數據增量導入 考慮到Hadoop對事務的支持比較差,所以,凡是涉及事務的應用,好比支付平臺等,後端的存儲均會選擇關係數據庫,而事務相關的分析數據,好比用戶支付行爲等,可能在Hadoop分析過程當中用到(好比廣告系統,推薦系統等)。爲了減小Hadoop分析過程當中影響這類系統的性能,咱們一般不會直接讓Hadoop訪問這些關係型數據庫,而是單獨導入一份到Hadoop存儲系統中。
從圖能夠看出,經過客戶端CLI(命令行界面)方式或JavaAPI方式調用Sqoop工具,Sqoop能夠將指令轉換爲對應的MapReduce做業(一般只涉及到Map任務,每一個Map任務從數據庫中讀取一片數據,這樣多個Map任務實現併發的拷貝,能夠快速的將整個數據拷貝到HDFS上),而後將關係型數據庫和Hadoop中的數據進行相互轉換,從而完成數據的遷移。
在導入數據以前,Sqoop 使用 JDBC 檢查導入的數據表,檢索出表中的全部列以及列的SQL數據類型,並將這些SQL類型映射爲Java數據類型. 在轉換後的 MapReduce 應用中使用這些對應的Java類型來保存字段的值,Sqoop的代碼生成器使用這些信息來建立對應表的類,用於保存從表中抽取的記錄。
在導出數據以前, Sqoop 會根據數據庫鏈接字符串來選擇一個導出方法,對於大部分系統來講,Sqoop會選擇JDBC。 Sqoop會根據目標表的定義生成一個Java類,這個生成的類可以從文本中解析出記錄數據,並可以向表中插入類型合適的值. 而後啓動一個 MapReduce 做業,從HDFS中讀取源數據文件,使用生成的類解析出記錄,而且執行選定的導出方法。
# 賦值模板文件 cp sqoop-env-template.sh sqoop-env.sh # 參數設置 #Set path to where bin/hadoop is available export HADOOP_COMMON_HOME=/export/servers/hadoop-2.7.5 #Set path to where hadoop-*-core.jar is available export HADOOP_MAPRED_HOME=/export/servers/hadoop-2.7.5 #set the path to where bin/hbase is available #export HBASE_HOME= #Set the path to where bin/hive is available export HIVE_HOME=/export/servers/apache-hive-2.1.1-bin #Set the path for where zookeper config dir is export ZOOCFGDIR=/export/servers/zookeeper-3.4.9 # 系統環境變量配置 vim /etc/profile export SQOOP_HOME=/export/servers/sqoop-1.4.6 export PATH=:$SQOOP_HOME/bin:$PATH source /etc/profile # 上傳mysql驅動包至 sqoop的lib目錄下 cd /export/servers/sqoop-1.4.6/lib
[root@node03 sqoop-1.4.6]# bin/sqoop help
html
# 查看導出到關係型數據庫操做的參數 sqoop help export
是將關係型數據庫中的單個表數據導入到HDFS,HIVE等具備HADOOP分佈式存儲結構的文件系統中 # 建立userdb數據庫,裏面添加三張表 emp, emp_add和emp_contact
# emp create table emp( id int, name varchar(20), deg varchar(20), salary int, dept varchar(20) ); # 插入數據 insert into emp values(1201,'gopal','manager',50000,'TP'); insert into emp values(1202,' manisha ',' Proof reader',50000,'TP'); insert into emp values(1203,' khalil','php dev',30000,'AC'); insert into emp values(1204,' prasanth',' php dev',30000,'AC'); insert into emp values(1205,' kranthi',' admin',20000,'TP');
# emp_add create table emp_add( id int, hno varchar(20), street varchar(20), city varchar(20) ); # 插入數據 insert into emp_add values(1201,'288A','vgiri','jublee'); insert into emp_add values(1202,'1801','aoc','sec-bad'); insert into emp_add values(1203,'144Z','pguttai','hyd'); insert into emp_add values(1204,'78B','old city','sec-bad'); insert into emp_add values(1205,'720X','hitec','sec-bad');
# emp_conn create table emp_conn( id int, phno int, email varchar(20) ); # 插入數據 insert into emp_conn values(1201,'2356742','gopal@tp.com'); insert into emp_conn values(1202,'1661663','manisha@tp.com'); insert into emp_conn values(1203,'8887776','khalil@ac.com'); insert into emp_conn values(1204,'9988774','prasanth@ac.com'); insert into emp_conn values(1205,'1231231','kranthi@tp.com');
# 啓動 hadoop 集羣 # 執行 sqoop import --connect jdbc:mysql://node03:3306/userdb --username root --password 123456 --table emp --m 1 - --m 1表示設置一個mapper任務 # 執行成功,數據在 http://node01:50070/explorer.html#/user/root/emp 打開 # 也能夠設置輸出路徑 --target-dir /sqoopresult sqoop import --connect jdbc:mysql://node03:3306/userdb --username root --password 123456 --target-dir /sqoopresult --table emp --num-mappers 1 # 查看方式 2 hdfs dfs -cat /user/root/emp/part-m-00000
當MySQL表中的數據發生了新增或修改變化,須要更新HDFS上對應的數據時,就可使用Sqoop的增量導入功能。 Sqoop目前支持兩種增量導入模式:append模式和lastmodified模式。 - append模式主要針對INSERT新增數據的增量導入; - lastmodified模式主要針對UPDATE修改數據的增量導入。
- 在進行增量導入操做時,首先必須指定「-check-column」參數,用來檢查數據表列字段,從而肯定哪些數據須要執行增量導入。 - 例如,在執行append模式增量導入時,一般會將「check-column」參數指定爲具備連續自增功能的列(如主鍵id); - 執行lastmodified模式增量導入時,一般會將「--check-column」參數必須指定爲日期時間類型的列(如date 或timestamp類型的列)。
# 在mysql中插入數據 INSERT INTO emp VALUES(1206,'ttw','feis',40000,'th'); # 執行增量導入 sqoop import --connect jdbc:mysql://node03:3306/userdb --username root --password 123456 --table emp --incremental append --check-column id --last-value 1205 --num-mappers 1 # 查看 hdfs dfs -cat /user/root/emp/part-m-00001
# 打開hive cd /export/servers/apache-hive-2.1.1-bin/ bin/hive show databases; - 包含test數據庫,下面將emp_add 上傳至 HIVE上的目標地址爲 test 數據倉庫的 emp_add_sp表中、 sqoop import --connect jdbc:mysql://node03:3306/userdb --u root --p 123456 --table emp_add --hive-table mytest.emp_add_sp --create-hive-table --hive-import --m 1 # 查看 - 在 hive 中進入數據庫-表,select * - 在 hdfs中打開: /user/hive/warehouse/mytest.db/emp_add_sp/part-m-00000 hdfs dfs -cat /user/hive/warehouse/mytest.db/emp_add_sp/part-m-00000
實際業務中,開發人員可能須要只針對部分數據進行導入操做
-使用sqoop提供的 where 和 query 參數,先進行數據過濾,例如,將表emp_add中 city=sec-bad 的數據導入HDFS 中 # where 進行數據過濾 sqoop import \ --connect jdbc:mysql://node03:3306/userdb \ --username root --password '123456' \ --where "city ='sec-bad'" \ --target-dir /wherequery \ --table emp_add --m 1 # query 進行數據過濾 sqoop import \ --connect jdbc:mysql://node03:3306/userdb \ --username root --password '123456' \ --target-dir /wherequery \ --query 'select id,name,deg FROM emp WHERE id>1203 AND $CONDITIONS' \ --m 1
上述代碼示例中,使用了Sqoop的「-query」參數進行數據過濾,它的主要做用就是先經過該參數指定的查詢語句查詢出子集數據,而後再將子集數據進行導入。上述示例中,$CONDITIONS至關於一個動態佔位符,動態的接收傳過濾後的子集數據,而後讓每一個Map任務執行查詢的結果並進行數據導入。 (1)若是沒有指定「-num-mappers 1」(或-m 1,即map任務個數爲1),那麼在指令中必須還要添加「-split-by」參數。「-split-by」參數的做用就是針對多副本map任務並行執行查詢結果並進行數據導入,該參數的值要指定爲表中惟一的字段(例如主鍵id); (2)「-query」參數後的查詢語句中(例如示例中單引號中的SELECT語句),若是已經使用了WHERE關鍵字,那麼在鏈接SCONDITIONS佔位符前必須使用AND關鍵字;不然,就必須使用WHERE關鍵字鏈接; (3)「-query」參數後的查詢語句中的$CONDITIONS佔位符不可省略,而且若是查詢語句使用雙引號(")進行包裝,那麼就必須使用\$CONDITIONS,這樣能夠避免Shell將其視爲Shell變量。
# 數據庫中新建一張表 emp_export DROP TABLE IF EXISTS emp_export; CREATE TABLE emp_export( id INT, NAME VARCHAR(20), deg VARCHAR(20), salary INT, dept VARCHAR(20), PRIMARY KEY (id) );
# 數據導出(將HDFS上的文件導入到mysql中) sqoop export \ --connect jdbc:mysql://node03:3306/userdb \ --username root \ --password 123456 \ --table emp_export \ --export-dir /user/root/emp
# 導出結果 ![](https://img2020.cnblogs.com/blog/1044397/202008/1044397-20200802224322490-645300066.png)