一、sqoop簡介
Sqoop將用戶編寫的Sqoop命令翻譯為MR程序,MR程序讀取關系型數據庫中的數據,寫入到HDFS或讀取HDFS上的數據,寫入到關系型數據庫!
在MR程序中如果要讀取關系型數據庫中的數據,必須指定輸入格式為DBInputformat!
在MR程序中如果要向關系型數據庫寫入數據,必須指定輸出格式為DBOutputformat!
Sqoop命令運行的MR程序,
bin/sqoop import \ ##連接的關系型數據庫的url,用戶名,密碼 --connect jdbc:mysql://hadoop102:3306/test \ --username root \ --password 123 \ ##連接的表 --table t_emp \ ##導出數據在hdfs上存放路徑 --target-dir /sqoopTest \ ##如果路徑已存在則先刪除 --delete-target-dir \ ##導入到Hdfs上后,每個字段使用什么參數進行分割 --fields-terminated-by "\t" \ ##要啟動幾個MapTask,默認4個 --num-mappers 2 \ ##數據集根據哪個字段進行切分,切分后每個MapTask負責一部分 --split-by id \
##要實現部分導入,加入下面的參數,表示導入哪些列
##columns中如果涉及到多列,用逗號分隔,分隔時不要添加空格
--columns id,name,age
2.1.2 使用sqoop關鍵字篩選查詢導入數據
bin/sqoop import \ --connect jdbc:mysql://hadoop102:3306/test \ --username root \ --password 123 \ --table t_emp \ ##指定過濾的where語句,where語句最好使用引號包裹 --where 'id>6' \ --target-dir /sqoopTest \ --delete-target-dir \ --fields-terminated-by "\t" \ --num-mappers 1 \ --split-by id
2.1.3 使用查詢語句導入
bin/sqoop import \ --connect jdbc:mysql://hadoop102:3306/test \ --username root \ --password 123 \ ##查詢語句最好使用單引號 ##如果query后使用的是雙引號,則$CONDITIONS前必須加轉移符,防止shell識別為自己的變量 --query 'select * from t_emp where id>3 and $CONDITIONS' \ --target-dir /sqoopTest \ --delete-target-dir \ --fields-terminated-by "\t" \ --num-mappers 1 \ --split-by id
注意:
1、如果使用了--query,就不能指定--table,和--columns和--where
--query 和 --table一定不能同時存在!
--where和--query同時存在時,--where失效
--columns和--query同時存在時,還有效!
2、--query 必須跟--target-dir
2.2 導入到Hive
bin/sqoop import \ --connect jdbc:mysql://hadoop102:3306/test \ --username root \ --password 123 \ --query 'select * from t_emp where id>3 and $CONDITIONS' \ --target-dir /sqoopTest \ ##如果不限定分隔符,那么hive存儲的數據將不帶分隔符,之后再想操作很麻煩,所以建議加上 --fields-terminated-by "\t" \ --delete-target-dir \ ##導入到hive --hive-import \ ##是否覆蓋寫,不加這個參數就是追加寫 --hive-overwrite \ ##指定要導入的hive的表名 --hive-table t_emp \ --num-mappers 1 \ --split-by id
原理還是分倆步:先把數據從關系數據庫里導到hdfs中,然后再從hdfs中導到hive中,此時hdfs中的文件會被刪除
注意:如果hive中沒表會自動創建表,但是類型是自動生成的,所以還是建議手動創建
也可以分倆步走:
先導入hdfs
#!/bin/bash import_data(){ $sqoop import \ --connect jdbc:mysql://hadoop102:3306/gmall \ --username root \ --password 123 \ --target-dir /origin_data/gmall/db/$1/$do_date \ --delete-target-dir \ --query "$2 and \$CONDITIONS" \ --num-mappers 1 \ --fields-terminated-by '\t' \ # 使用壓縮,和指定壓縮格式為lzop --compress \ --compression-codec lzop \ #將String類型和非String類型的空值替換為\N,方便Hive讀取 --null-string '\\N' \ --null-non-string '\\N' }
然后利用 load data 命令導入hive
注意:這里使用到了空值處理 ——Hive中的Null在底層是以“\N”來存儲,而MySQL中的Null在底層就是Null,為了保證數據兩端的一致性。在導出數據時采用--input-null-string和--input-null-non-string兩個參數。導入數據時采用--null-string和--null-non-string。
2.3導入到Hbase
bin/sqoop import \ --connect jdbc:mysql://hadoop102:3306/test \ --username root \ --password 123 \ --query 'select * from t_emp where id>3 and $CONDITIONS' \ --target-dir /sqoopTest \ --delete-target-dir \ ##表不存在是否創建 --hbase-create-table \ ##hbase中的表名 --hbase-table "t_emp" \ ##將導入數據的哪一列作為rowkey --hbase-row-key "id" \ ##導入的列族 --column-family "info" \ --num-mappers 2 \ --split-by id
1、當選用自動創建表時,如果版本不兼容會報錯:
20/03/24 13:51:24 INFO mapreduce.HBaseImportJob: Creating missing HBase table t_emp
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.hadoop.hbase.HTableDescriptor.addFamily(Lorg/apache/hadoop/hbase/HColumnDescriptor;)V
此時只能自己手動創建或者可以重新編譯sqoop源碼
2、如果要多列族導入,只能多次運行命令,一次導入一個列族
三、導出
將Hdfs上的數據導出到關系型數據庫中
3.1sql中表為空表時
bin/sqoop export \ --connect 'jdbc:mysql://hadoop102:3306/test?useUnicode=true&characterEncoding=utf-8' \ --username root \ --password 123 \ ##導出的表名,需要自己提前創建好 --table t_emp2 \ --num-mappers 1 \ ##hdfs上導出的數據的路徑 --export-dir /user/hive/warehouse/t_emp \ ##hdfs上數據的分隔符 --input-fields-terminated-by "\t"
3.2 表不為空表時
如果插入的數據的主鍵和表中已有數據的主鍵沖突,那么會報錯
Duplicate entry '5' for key 'PRIMARY'
如果在SQL下,可以使用
INSERT INTO t_emp2 VALUE(5,'jack',30,3,1111) ON DUPLICATE KEY UPDATE NAME=VALUES(NAME),deptid=VALUES(deptid), empno=VALUES(empno);
意為
指定當插入時,主鍵重復時時,對於重復的記錄,只做更新,不做插入!
而用sqoop時,則可以啟用以下倆種模式
3.2.1
bin/sqoop export \ --connect 'jdbc:mysql://hadoop103:3306/mydb?useUnicode=true&characterEncoding=utf-8' \ --username root \ --password 123456 \ --table t_emp2 \ --num-mappers 1 \ --export-dir /hive/t_emp \ --input-fields-terminated-by "\t" \ --update-key id
利用 --update-key 字段 ,表示主鍵重復時會進行更新,但是主鍵不重復的時候,數據不會插入進來
3.2.2
bin/sqoop export \ --connect 'jdbc:mysql://hadoop103:3306/mydb?useUnicode=true&characterEncoding=utf-8' \ --username root \ --password 123456 \ --table t_emp2 \ --num-mappers 1 \ --export-dir /hive/t_emp \ --input-fields-terminated-by "\t" \ --update-key id \ --update-mode allowinsert
表示主鍵重復時會進行更新,主鍵不重復的時候,數據也會插入進來
3.3如何查看導出命令的具體實現
3.3.1配置/etc/my.cnf
[mysqld] #開啟binlog日志功能 log-bin=mysql-bin
3.3.2重啟mysql服務
3.3.3進入/var/lib/mysql,調用方法
sudo mysqlbinlog mysql-bin.000001