Sqoop 使用shell命令的各種參數的配置及使用方法(含主鍵重復問題參數配置)


一、sqoop簡介

Sqoop將用戶編寫的Sqoop命令翻譯為MR程序,MR程序讀取關系型數據庫中的數據,寫入到HDFS或讀取HDFS上的數據,寫入到關系型數據庫!

在MR程序中如果要讀取關系型數據庫中的數據,必須指定輸入格式為DBInputformat!

在MR程序中如果要向關系型數據庫寫入數據,必須指定輸出格式為DBOutputformat!

Sqoop命令運行的MR程序,只有Map階段,沒有Reduce階段!只需要做數據傳輸,不需要對數據進行合並和排序!

二、sqoop導入數據(將關系型數據庫的數據導入到 HDFS)

數據如下

2.1直接導入HDFS

2.1.1 全表導入(部分導入)

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.1updateonly模式

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.2allowinsert模式

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

 參考博客

https://my.oschina.net/u/1765168/blog/1593343


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM