sqoop同步工具詳情
未經允許不得轉載
來源
資料同步工具(針對各種資料庫):
開源工具:
sqoop:
datax:
kettle:
cannal:
自定義程式碼:
閉源工具:
1、關係型資料庫中資料怎麼匯入到hdfs、hbase(壓縮或者非壓縮)?
2、hdfs中的資料(壓縮)怎麼匯入關係型資料庫中?
3、增量資料匯入?
2、sqoop****定義
sqoop是一個hadoop和關係型資料庫之間高效批量資料同步工具。
匯入(import): 關係型資料庫 -----> hadoop(hdfs\hive\hbase)
匯出****(export):hadoop(hdfs) ----> 關係型資料庫
資料同步本質:
優點:跨平臺資料同步
缺點:不是很靈活。
3****、sqoop的安裝
準備:
需要hadoop的安裝
需要jdk
需要準備關係型資料庫的依賴jar包
安裝
1、解壓配置環境變數即可
[root@hadoop01 local]# tar -zxvf /home/sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C
/usr/local/
[root@hadoop01 local]# mv ./sqoop-1.4.7.bin__hadoop-2.6.0/ ./sqoop-1.4.7
2、配置環境變數
[root@hadoop01 local]# vi /etc/profile [root@hadoop01 local]# source /etc/profile 驗證 [root@hadoop01 local]# which sqoop
常見命令:
3、配置sqoop-env.sh檔案
[root@hadoop01 local]# mv ./sqoop-1.4.7/conf/sqoop-env-template.sh ./sqoop- 1.4.7/conf/sqoop-env.sh [root@hadoop01 local]# vi ./sqoop-1.4.7/conf/sqoop-env.sh 修改如下: #Set Hadoop-specific environment variables here. #Set path to where bin/hadoop is available export HADOOP_COMMON_HOME=/usr/local/hadoop-2.7.1/ #Set path to where hadoop-*-core.jar is available export HADOOP_MAPRED_HOME=/usr/local/hadoop-2.7.1/ #set the path to where bin/hbase is available export HBASE_HOME=/usr/local/hbase-1.1.2/ #Set the path to where bin/hive is available export HIVE_HOME=/usr/local/hive-2.3.6/ #Set the path for where zookeper config dir is export ZOOCFGDIR=/usr/local/zookeeper-3.4.10/
4、測試
[root@hadoop01 local]# sqoop-version
Warning: /usr/local/sqoop-1.4.7//../hcatalog does not exist! HCatalog jobs will fail.
Please set $HCAT_HOME to the root of your HCatalog installation.
Warning: /usr/local/sqoop-1.4.7//../accumulo does not exist! Accumulo imports will fail.
Please set $ACCUMULO_HOME to the root of your Accumulo installation.
Warning: /usr/local/sqoop-1.4.7//../zookeeper does not exist! Accumulo imports will fail.
Please set $ZOOKEEPER_HOME to the root of your Zookeeper installation.
19/12/02 10:13:30 INFO sqoop.Sqoop: Running Sqoop version: 1.4.7 Sqoop 1.4.7
git commit id 2328971411f57f0cb683dfb79d19d4d19d185dd8
Compiled by maugli on Thu Dec 21 15:59:58 STD 2017
4、sqoop****的實戰
sqoop只允許將語句放到1行,如果想要放到多行,需要\來表示換行。
4.1 sqoop列出mysql****中的所有庫
格式:
$ sqoop list-databases (generic-args) (list-databases-args)
$ sqoop-list-databases (generic-args) (list-databases-args)
準備:
引入mysql的驅動包。
[root@hadoop01 sqoop-1.4.7]# cp /home/mysql-connector-java-5.1.6-bin.jar ./lib/
語句:
sqoop list-databases --connect jdbc:mysql://hadoop01:3306 \
--username root \
--password root
結果:
information_schema
azkaban
bap_dm
bap_ods
hive
kettle
mysql
performance_schema
sales_report
sales_source
test
ywp
4.2 sqoop列出mysql****某庫的所有表
sqoop list-tables --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root
4.3 sqoop****資料的匯入
資料匯入import
資料匯出export
格式:
$ sqoop import (generic-args) (import-args)
$ sqoop-import (generic-args) (import-args)
匯入某個表的所有資料到hdfs中:
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u1 \
--delete-target-dir \
--target-dir '/1906sqoop/u1' \
--split-by id
並行匯入:
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u1 \
--delete-target-dir \
--target-dir '/1906sqoop/u2' \
--split-by id \ -m 1
選擇列匯入:
法一:
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table stu \
--driver com.mysql.jdbc.Driver \
--columns 'id,name,age' \
--where id > 6 \
--delete-target-dir \
--target-dir '/1906sqoop/u3' \
--split-by id \ -m 1
法二: sqoop import
--connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \
--driver com.mysql.jdbc.Driver \
--delete-target-dir \
--target-dir '/1906sqoop/u6' \
--split-by id \ -m 1 \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0'
單引號和雙引號的區別:
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \
--query "select id,name,age from stu where id > 6 and \$CONDITIONS" \
引數屬性:
--table mysql中的表
--delete-target-dir 如果hdfs中的目標目錄存在,則刪除
--target-dir 匯入到hdfs中的那個目錄
--split-by 切分工作單元,後面需要指定column
-m 使用n個map task來並行匯入,一般和
--split-by搭配使用
--columns 匯入指定列,和table搭配使用
--where 指定條件
--driver 指定驅動引數
--query 指定執行的sql語句,不能和--table搭配使用
-warehouse-dir 倉庫目錄,專案可以指定一個根目錄
--fields-terminated-by 匯入的欄位分隔符,預設是,分割
--null-string 字串列空值處理 --null-non-string 非字串列空值處理
--as-parquetfile 輸出的資料檔案格式
--fetch-size 10000 一次獲取的資料條數
--compress 指定壓縮
--compression-codec 指定壓縮型別,預設gzip壓縮
指指定檔案格式匯入:
sqoop import
--connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \
--driver com.mysql.jdbc.Driver \
--delete-target-dir \
--target-dir '/1906sqoop/u5' \
--split-by id \ -m 1 \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
--as-parquetfile \
--fetch-size 10000
問題:
1、如果mysql的表沒有主鍵,將會報錯:19/12/02 10:39:50 ERROR tool.ImportTool: Import failed: No primary key could be found for table u1. Please specify one with -- split-by or perform a sequential import with '-m 1'.
解決方法:
指定--split-by 2、
匯入指定列錯誤 :java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@4c39bec8 is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.
解決方法:
加上該屬性: --driver com.mysql.jdbc.Driver \
思考:
1、怎麼監控資料是否完全匯入???
2、某表如果2G資料,設定多少個mapper合適?
4.4 sqoop****資料的匯出
1、構建mysql的表:
CREATE TABLE `u2` (
`id` int(11) DEFAULT NULL,
`age` int(11) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `u3` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) default NULL,
`age` int(11) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、hdfs匯出到mysql語句
sqoop export --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u2 \
--driver com.mysql.jdbc.Driver \
--export-dir '/1906sqoop/u2/*' \
-m 1
法二:
先從新匯入資料:
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \
--driver com.mysql.jdbc.Driver \
--delete-target-dir \
--target-dir '/1906sqoop/u7' \
--split-by id \ -m 1 \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0'
匯出語句:
sqoop export --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u3 \
--driver com.mysql.jdbc.Driver \
--export-dir '/1906sqoop/u7/*' \
--input-fields-terminated-by '\t' \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
-m 1
注:
1、匯出資料中有些列值有"null",會報沒法解析
2、匯出資料的型別需要和mysql中的一致(能自動轉沒有問題)
5、sqoop****高階例項
5.1 sqoop匯入到hive****表
方式:
1、直接匯入到hdfs中的某個目錄,然後再建立表去指向該目錄即可。
2、直接匯入到hive的表中。
準備:
1、需要hive能正常使用(metastore服務啟動起來)
2、將hive的exec.jar包複製到sqoop的lib目錄下
sqoop import \
--connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u2 \
--hive-import \ --hive-overwrite \
--hive-table u2 \
-m 1
分解步驟:
1、匯入hdfs中的目錄下
2、將該目錄下的資料裝載到hive表中
問題:
1、hive-1.2.1 和 sqoop-1.4.7 ,從mysql匯入資料到hive表中,hive中查詢不出來表,元資料也沒有。
解決辦法:
將hive-site.xml放到sqoop的conf目錄中即可。
5.2 sqoop****匯入到hive的分割槽表
方式:
1、sqoop匯入資料到hdfs目錄(分割槽的形式),然後再hive中建立分割槽表,最後使用alter table add
partition...
2、直接使用sqoop匯入都分割槽表中ss
sqoop import \
--connect jdbc:mysql://hadoop01:3306/test \
--username root \ --password root \
--hive-import \
--hive-overwrite \
--hive-partition-key 'bdp_day' \
--hive-partition-value '20191202' \
--target-dir /root/u22 \
--hive-table u22 \
--num-mappers 1 \
--query 'SELECT * FROM u2 where $CONDITIONS;'
5.3 hive的job
sqoop提供一系列的job語句來操作sqoop。
$ sqoop job (generic-args) (job-args) [-- [subtool-name] (subtool-args)]
$ sqoop-job (generic-args) (job-args) [-- [subtool-name] (subtool-args)]
使用方法:
usage: sqoop job [GENERIC-ARGS] [JOB-ARGS] [-- [<tool-name>] [TOOL-ARGS]]
Job management arguments:
--create <job-id> Create a new saved job
--delete <job-id> Delete a saved job
--exec <job-id> Run a saved job
--help Print usage instructions
--list List saved jobs
--meta-connect <jdbc-uri> Specify JDBC connect string for the
metastore
--show <job-id> Show the parameters for a saved job
--verbose Print more information while working
列出sqoop的job:
sqoop job --list
建立一個sqoop的job:
sqoop job --create sq2
-- import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u2 \
--driver com.mysql.jdbc.Driver \
--delete-target-dir \
--target-dir '/1906sqoop/u9' \
--split-by id \
-m 1
執行sqoop的job:
sqoop job --exec sq1
執行的時候回讓輸入密碼:
輸入該節點使用者的對應的密碼即可
1、配置客戶端記住密碼(sqoop-site.xml)追加
<property>
<name>sqoop.metastore.client.record.password</name>
<value>true</value>
</property>
2、將密碼配置到hdfs的某個檔案,我們指向該密碼檔案
說明:在建立Job時,使用--password-file引數,而且非--passoword。主要原因是在執行Job時使用--password引數將有警告,並且需要輸入密碼才能執行Job。當我們採用--password-file引數時,執行
Job無需輸入資料庫密碼。
echo -n "root" > sqoop.pwd
hdfs dfs -rm sqoop.pwd /input/sqoop.pwd
hdfs dfs -put sqoop.pwd /input
hdfs dfs -chmod 400 /input/sqoop.pwd
hdfs dfs -ls /input
-r-------- 1 hadoop supergroup 6 2018-01-15 18:38 /input/sqoop.pwd
檢視sqoop的job:
sqoop job --show sq1
刪除sqoop的job:
sqoop job --delete sq1
問題:
1、建立job報錯:19/12/02 23:29:17 ERROR sqoop.Sqoop: Got exception running Sqoop:
java.lang.NullPointerException
java.lang.NullPointerException
at org.json.JSONObject.<init>(JSONObject.java:144)
解決辦法:
新增java-json.jar包到sqoop的lib目錄中。
如果上述辦法沒有辦法解決,請注意hcatlog的版本是否過高,過高將其hcatlog包剔除sqoop的lib目錄即可。
2、報錯:Caused by: java.lang.ClassNotFoundException: org.json.JSONObject
解決辦法:
新增java-json.jar包到sqoop的lib目錄中。
job的好處:
1、一次建立,後面不需要建立,可重複執行job即可
2、它可以幫我們記錄增量匯入資料的最後記錄值
3、job的元資料儲存目錄:$HOME/.sqoop/
5.4 更新並插入匯出
場景:
多維結果資料匯出;異常重跑資料
--update-mode : updateonly,是預設,僅更新;allowinsert:更新並允許插入
--update-key :
CREATE TABLE `upv` (
`country_id` int(11) NOT NULL AUTO_INCREMENT,
`visits` int(11) DEFAULT NULL,
PRIMARY KEY (`country_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
匯出語句:
sqoop export --connect jdbc:mysql://hadoop01:3306/test \
--username root --password root --table upv \
--export-dir /1906sqoop/upv/* \
--input-fields-terminated-by "," \
--update-mode allowinsert \
--update-key country_id
5.5 sqoop匯出parquet****格式的資料
匯入資料到HDFS中為parqut格式:
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--query 'select id,age from stu where id > 6 and $CONDITIONS' \
--driver com.mysql.jdbc.Driver \
--delete-target-dir \
--target-dir '/1906sqoop/u9' \
--split-by id \
-m 1 \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
--as-parquetfile
匯出語句:
建立表:
CREATE TABLE `par` (
`id` int(11) NOT NULL DEFAULT '0',
`age` int(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
hive建立表:
create table if not exists par(
`id` int,
`age` int
)
row format delimited fields terminated by '\t'
stored as parquet
location '/1906sqoop/u9/'
;
將hive包中的lib目錄下的hcatlog相關包拷貝到sqoop的lib目錄中去:
[root@hadoop01 sqoop-1.4.7]# cp /usr/local/hive-2.3.6/lib/hive-hcatalog-core-2.3.6.jar /usr/local/hive-2.3.6/lib/hive-hcatalog-server-extensions-2.3.6.jar ./lib/
匯出parquet格式語句:
sqoop export \
--connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table par \
--hcatalog-database default \
--hcatalog-table par \
-m 1
引數說明:
--table:MySQL庫中的表名
--hcatalog-database:Hive中的庫名
--hcatalog-table:Hive庫中的表名,需要抽數的表
5.6 定期執行
方法:
1、直接排程框架排程sqoop語句
2、將sqoop語句封裝到shell指令碼中,排程框架排程指令碼或者直接在伺服器中使用crontab來定時
vi /home/add_u2.sh
#!/bin/bash
/usr/local/sqoop-1.4.7/bin/sqoop import \
--connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \
--table u2 \
--hive-import \
--hive-overwrite \
--hive-table u2 \
-m 1
授予可執行許可權:
[root@hadoop01 sqoop-1.4.7]# chmod a+x /home/add_u2.sh
定時:
[root@hadoop01 sqoop-1.4.7]# crontab -e
\* 2 * * * /home/add_u2.sh >> /home/u2.log
自己搗鼓
1、將資料中 sales_source.sql載入到自己mysql中,並且使用sqoop將裡面的三章表的資料匯入到hive
表中,hive的表名和sales_source.sql中的表名一樣,hive的庫名統一叫sales_ods.
需求:
a、sales_order表需要增量匯入,必須是分割槽表
b、其它兩張表全量匯入,不用分割槽表
c、將其sqoop語句放到shell指令碼中,執行指令碼即可執行把3張表的資料匯入即可。
提示
------------
customer : 全量
product : 全量
orders : 增量
vi /home/hw01.sh
#!/bin/bash
create database if not exists sales_ods;
sqoop import \
--connect jdbc:mysql://hadoop01:3306/sales_source \
--username root \
--password root \
--table customer \
--hive-import \
--hive-overwrite \
--hive-table sales_ods.customer \
-m 1
sqoop import \
--connect jdbc:mysql://hadoop01:3306/sales_source \
--username root \
--password root \
--table product \
--hive-import \
--hive-overwrite \
--hive-table sales_ods.product \
-m 1
思考:
1、怎麼監控資料是否完全匯入???
使用shell指令碼去查詢mysql中某表的資料,然後和hive中表的行數對比。
#!/bin/bash
u2_cnt=`mysql -uroot -proot -e "select count(*) from test.u2"`
echo "u2 table of test total rows:${u2_cnt}"
2、某表如果2G資料,設定多少個mapper合適?
建議128M(和塊大小一致)一個mapper即可。