SQOOP安裝及使用
SQOOP安裝及使用SQOOP安裝1、上傳并解壓2、修改文件夾名字3、修改配置文件4、修改環境變量5、添加MySQL連接驅動6、測試準備MySQL數據登錄MySQL數據庫創建student數據庫切換數據庫并導入數據另外一種導入數據的方式使用Navicat運行SQL文件導出MySQL數據庫importMySQLToHDFS編寫腳本,保存為MySQLToHDFS.conf執行腳本注意事項:MySQLToHive編寫腳本,并保存為MySQLToHive.conf文件執行腳本--direct--e參數的使用MySQLToHBase編寫腳本,并保存為MySQLToHBase.conf在HBase中創建student表執行腳本exportHDFSToMySQL編寫腳本,并保存為HDFSToMySQL.conf先清空MySQL student表中的數據,不然會造成主鍵沖突執行腳本查看sqoop helpSqoop 在從HDFS中導出到關系型數據庫時的一些問題問題一:問題二:問題三:**增量同步數據總結
SQOOP安裝
1、上傳并解壓
tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /usr/local/soft/
2、修改文件夾名字
mv sqoop-1.4.6.bin__hadoop-2.0.4-alpha/ sqoop-1.4.6
3、修改配置文件
# 切換到sqoop配置文件目錄 cd /usr/local/soft/sqoop-1.4.6/conf # 復制配置文件并重命名 cp sqoop-env-template.sh sqoop-env.sh # vim sqoop-env.sh 編輯配置文件,并加入以下內容 export HADOOP_COMMON_HOME=/usr/local/soft/hadoop-2.7.6 export HADOOP_MAPRED_HOME=/usr/local/soft/hadoop-2.7.6/share/hadoop/mapreduce export HBASE_HOME=/usr/local/soft/hbase-1.4.6 export HIVE_HOME=/usr/local/soft/hive-1.2.1 export ZOOCFGDIR=/usr/local/soft/zookeeper-3.4.6/conf export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.4.6 ? # 切換到bin目錄 cd /usr/local/soft/sqoop-1.4.6/bin # vim configure-sqoop 修改配置文件,注釋掉沒用的內容(就是為了去掉警告信息)
4、修改環境變量
vim /etc/profile # 將sqoop的目錄加入環境變量
5、添加MySQL連接驅動
# 從HIVE中復制MySQL連接驅動到$SQOOP_HOME/lib cp /usr/local/soft/hive-1.2.1/lib/mysql-connector-java-5.1.49.jar /usr/local/soft/sqoop-1.4.6/lib/
6、測試
# 打印sqoop版本 sqoop version
# 測試MySQL連通性 sqoop list-databases -connect jdbc:mysql://master:3306/ -username root -password 123456
準備MySQL數據
登錄MySQL數據庫
mysql -u root -p123456;
創建student數據庫
create database studentdb;
切換數據庫并導入數據
# mysql shell中執行 use studentdb; source /usr/local/soft/bigdata29/student.sql; source /usr/local/soft/bigdata29/score.sql;
另外一種導入數據的方式
# linux shell中執行 mysql -uroot -p123456 studentdb < /usr/local/soft/shujia/student.sql mysql -uroot -p123456 studentdb < /usr/local/soft/shujia/score.sql
使用Navicat運行SQL文件
也可以通過Navicat導入
導出MySQL數據庫
mysqldump -u root -p123456 數據庫名>任意一個文件名.sql
import
從傳統的關系型數據庫導入HDFS、HIVE、HBASE......
MySQLToHDFS
編寫腳本,保存為MySQLToHDFS.conf
sqoop執行腳本有兩種方式:第一種方式:直接在命令行窗口中直接輸入腳本;第二種方式是將命令封裝成一個腳本文件,然后使用另一個命令執行 第一種方式: sqoop import \ --append \ --connect jdbc:mysql://master:3306/studentdb \ --username root \ --password 123456 \ --table student \ --m 1 \ --split-by id \ --target-dir /bigdata29/sqoopdata/student1/ \ --fields-terminated-by '\t' ? 第二種方式:使用腳本文件的形式 mysql2hdfs.conf import --append --connect jdbc:mysql://master:3306/studentdb --username root --password 123456 --table student --m 1 --split-by id --target-dir /bigdata29/sqoopdata/student2/ --fields-terminated-by ',' ? ?
執行腳本
sqoop --options-file MySQLToHDFS.conf
注意事項:
1、--m 表示指定生成多少個Map任務,不是越多越好,因為MySQL Server的承載能力有限
2、當指定的Map任務數>1,那么需要結合--split-by
參數,指定分割鍵,以確定每個map任務到底讀取哪一部分數據,最好指定數值型的列,最好指定主鍵(或者分布均勻的列=>避免每個map任務處理的數據量差別過大)
3、如果指定的分割鍵數據分布不均,可能導致數據傾斜問題
4、分割的鍵最好指定數值型的,而且字段的類型為int、bigint這樣的數值型
5、編寫腳本的時候,注意:例如:--username
參數,參數值不能和參數名同一行
--username root // 錯誤的 ? // 應該分成兩行 --username root
6、運行的時候會報錯InterruptedException,hadoop2.7.6自帶的問題,忽略即可
21/01/25 14:32:32 WARN hdfs.DFSClient: Caught exception java.lang.InterruptedExceptionat java.lang.Object.wait(Native Method)at java.lang.Thread.join(Thread.java:1252)at java.lang.Thread.join(Thread.java:1326)at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeResponder(DFSOutputStream.java:716)at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.endBlock(DFSOutputStream.java:476)at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:652) ?
7、實際上sqoop在讀取mysql數據的時候,用的是JDBC的方式,所以當數據量大的時候,效率不是很高
8、sqoop底層通過MapReduce完成數據導入導出,只需要Map任務,不許需要Reduce任務 part-m-00000
9、每個Map任務會生成一個文件
MySQLToHive
先會將MySQL的數據導出來并在HDFS上找個目錄臨時存放,默認為:/user/用戶名/表名
然后再將數據加載到Hive中,加載完成后,會將臨時存放的目錄刪除
編寫腳本,并保存為MySQLToHive.conf文件
import --connect jdbc:mysql://master:3306/studentdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false --username root --password 123456 --table student --m 1 --hive-import --hive-overwrite --hive-database bigdata29 --create-hive-table --hive-table sqoop_students1 --fields-terminated-by ','
執行腳本
sqoop --options-file MySQLToHive.conf
--direct
加上這個參數,可以在導出MySQL數據的時候,使用MySQL提供的導出工具mysqldump,加快導出速度,提高效率
需要將master上的/usr/bin/mysqldump分發至 node1、node2的/usr/bin目錄下
scp /usr/bin/mysqldump node1:/usr/bin/ scp /usr/bin/mysqldump node2:/usr/bin/
--e參數的使用
sqoop在導入數據時,可以使用--e搭配sql來指定查詢條件,并且還需在sql中添加$CONDITIONS,來實現并行運行mr的功能。
只要有--e+sql,就需要加$CONDITIONS,哪怕只有一個maptask。
sqoop通過繼承hadoop的并行性來執行高效的數據傳輸。 為了幫助sqoop將查詢拆分為多個可以并行傳輸的塊,需要在查詢的where子句中包含$conditions占位符。 sqoop將自動用生成的條件替換這個占位符,這些條件指定每個任務應該傳輸哪個數據片。
# 需求:將學號1500100007學生從mysql查出來導入到hive中 select * from student where id=1500100007 ? ? ? import --connect jdbc:mysql://master:3306/studentdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false --username root --password 123456 --query "select * from score where id=1500100007 and $CONDITIONS" --target-dir /shujia/history/score1 --m 1 --hive-import --hive-overwrite --hive-database bigdata29 --create-hive-table --hive-table sqoop_score1 --fields-terminated-by ',' --direct
MySQLToHBase
編寫腳本,并保存為MySQLToHBase.conf
sqoop1.4.6 只支持 HBase1.0.1 之前的版本的自動創建 HBase 表的功能
import --connect jdbc:mysql://master:3306/studentdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false --username root --password 123456 --query "select * from student where id<1500100003 and $CONDITIONS" --target-dir /shujia/history/hbase_student --m 1 --hbase-create-table --hbase-table mysql2hbase1 --column-family info --hbase-row-key id --direct
在HBase中創建student表
create 'studentsq','cf1'
執行腳本
sqoop --options-file MySQLToHBase.conf
export
HDFSToMySQL
編寫腳本,并保存為HDFSToMySQL.conf
在往關系型數據庫中導出的時候我們要先在關系型數據庫中創建好庫以及表,這些sqoop不會幫我們完成。
export --export-dir /bigdata29/teachers/ --columns id,name,grade,clazz --fields-terminated-by ',' --connect jdbc:mysql://master:3306/studentdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false --username root --password 123456 --table sqoop_teacher --num-mappers 1
先清空MySQL student表中的數據,不然會造成主鍵沖突
執行腳本
sqoop --options-file HDFSToMySQL.conf
查看sqoop help
sqoop help ? 21/04/26 15:50:36 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6 usage: sqoop COMMAND [ARGS] ? Available commands:codegen ? ? ? ? ? Generate code to interact with database recordscreate-hive-table Import a table definition into Hiveeval ? ? ? ? ? ? ? Evaluate a SQL statement and display the resultsexport ? ? ? ? ? ? Export an HDFS directory to a database tablehelp ? ? ? ? ? ? ? List available commandsimport ? ? ? ? ? ? Import a table from a database to HDFSimport-all-tables Import tables from a database to HDFSimport-mainframe ? Import datasets from a mainframe server to HDFSjob ? ? ? ? ? ? ? Work with saved jobslist-databases ? ? List available databases on a serverlist-tables ? ? ? List available tables in a databasemerge ? ? ? ? ? ? Merge results of incremental importsmetastore ? ? ? ? Run a standalone Sqoop metastoreversion ? ? ? ? ? Display version information ? See 'sqoop help COMMAND' for information on a specific command.
# 查看import的詳細幫助 sqoop import --help
1、并行度不能太高,就是 -m 2、如果沒有主鍵的時候,-m 不是1的時候就要指定分割字段,不然會報錯,如果有主鍵的時候,-m 不是1 可以不去指定分割字段,默認是主鍵,不指定 -m 的時候,Sqoop會默認是分4個map任務。
export --export-dir /user/hive/warehouse/bigdata29.db/t_movie1/ --columns id,name,types --fields-terminated-by ',' --connect jdbc:mysql://master:3306/bigdata29?useUnicode=true&characterEncoding=UTF-8&useSSL=false --username root --password 123456 --table sqoop_movie --num-mappers 1 --direct
Sqoop 在從HDFS中導出到關系型數據庫時的一些問題
問題一:
在上傳過程中遇到這種問題:
ERROR tool.ExportTool: Encountered IOException running export job: java.io.IOException: No columns to generate for ClassWriter
驅動版本的過低導致的,其實在嘗試這個方法的時候我們可以先進行這樣:加一行命令,--driver com.mysql.jdbc.Driver \ 然后問題解決!!! ? 如果添加命令之后還沒有解決就把jar包換成高點版本的。
問題二:
依舊是導出的時候,會報錯,但是我們很神奇的發現,也有部分數據導入了。這也就是下一個問題。
Caused by: java.lang.NumberFormatException: For input string: "null"
解決方式:因為數據有存在null值得導致的 ? 在命令中加入一行(方式一中的修改方式,方式二也就是轉換一下格式):--input-null-string '\\N' \ ? ? --input-null-string '\\N'
問題三:**
java.lang.RuntimeException: Can't parse input data: '1998/5/11'
出現像這樣的問題,大多是因為HDFS上的數據與關系型數據庫創建表的字段類型不匹配導致的。仔細對比修改后,就不會有這個報錯啦!!
增量同步數據
我們之前導入的都是全量導入,一次性全部導入,但是實際開發并不是這樣,例如web端進行用戶注冊,mysql就增加了一條數據,但是HDFS中的數據并沒有進行更新,但是又再全部導入一次又完全沒有必要。
所以,sqoop提供了增量導入的方法。
1、數據準備:
CREATE TABLE sqoop_stu2( id int, name STRING, age int, gender STRING, clazz STRING, last_mod TIMESTAMP )row format delimited fields terminated by ','
2、將其先用全量導入到HDFS(hive)中去
?
3、先在mysql中添加一條數據,在使用命令進行追加
4、根據時間進行大量追加(不去重)
#前面的案例中,hive本身的數據也是存儲在HDFS上的,所以我今后要做增量操作的時候,需要指定HDFS上的路徑 import --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student --target-dir /user/hive/warehouse/testsqoop.db/from_mysql_student --fields-terminated-by '\t' --incremental append --check-column id --last-value 3 ?
結果:但是我們發現有兩個重復的字段
5、往往開發中需要進行去重操作:sqoop提供了一個方法進行去重,內部是先開一個map任務將數據導入進來,然后再開一個map任務根據指定的字段進行合并去重
結果:
之前有重復的也進行合并去重操作,最后生成一個結果。
總結:
–check-column 用來指定一些列,這些列在增量導入時用來檢查這些數據是否作為增量數據進行導入,和關系型數據庫中的自增字段及時間戳類似. 注意:這些被指定的列的類型不能使任意字符類型,如char、varchar等類型都是不可以的,同時–check-column可以去指定多個列 –incremental 用來指定增量導入的模式,兩種模式分別為Append和Lastmodified –last-value 指定上一次導入中檢查列指定字段最大值
總結
RDBMS-->HDFS ? ? import HDFS--->RDBMS ? ?export ? Mysql--->HDFS(hive) 要知道你要數據的來源和數據的目的地 mysql: --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student ? hdfs: --target-dir /user/hive/warehouse/sqooptest.db/from_mysql_student --fields-terminated-by '\t' ? hive: 1) --hive-import --hive-overwrite --create-hive-table (如果表不存在,自動創建,如果存在,報錯,就不需要這個參數) --hive-database testsqoop --hive-table from_mysql_student --fields-terminated-by '\t' 2) --target-dir /user/hive/warehouse/bigdata29.db/sqoop_stu2 --fields-terminated-by ',' # 增量需要添加的參數================================================= --incremental append --check-column id --last-value 3 (或者是)------------------------------------------------------------ --fields-terminated-by '\t' --check-column (hive的列名) last_mod --incremental lastmodified --last-value "2022-06-18 16:40:09" --m 1 ======================================================================== # 如果需要去重,請先搞清楚根據什么去重,否則結果可能不是你想要的 --merge-key name ? (這里是根據姓名去重,你可以改成自己的去重列名) # 經過實踐得出,如果要追加導入到hive中并且要進行去重的話,建議最好使用lastmodified以時間戳的方式追加,以寫入hdfs的路徑方式追加,這樣可以實現追加的同時并且去重。 ? ? hbase:(如果hbase導入要創建表的話,需要將--hbase-create-table參數放到hbase參數的第一個才會生效) --hbase-create-table --hbase-table studentsq --column-family cf1 --hbase-row-key id (mysql中的列名) --m 1 ? ? ? HDFS--->mysql ? hdfs: --columns id,name,age,gender,clazz --export-dir /shujia/bigdata17/sqoopinput/ --fields-terminated-by ',' # 如果數據分割出來的字段值有空值,需要添加以下參數(面試可能會面到) --null-string '\\N' --null-non-string '\\N'