Sqoop使用手冊


 

<span id="1"></span>

1 Sqoop概述

Sqoop是一個旨在Hadoop和關系數據庫或主機之間傳輸數據的工具。你可以使用Sqoop從關系型數據庫管理系統(RDBMS),如MySQL、Oracle或大型機到Hadoop分布式文件系統(HDFS)導入數據,在Hadoop中的MapReduce轉換數據,然后將數據導出到一個RDBMS 。Sqoop使用MapReduce導入和導出數據,它提供了並行操作,以及容錯。

<span id="2"></span>

2 版本說明

本文檔適用於Sqoop1。

軟件 版本
Sqoop 1.4.5-cdh5.3.0
Mysql JDBC驅動 5.1.32
ORACLE JDBC驅動 和oracle版本保持一致

<span id="3"></span>

3 驅動安裝

<span id="31"></span>

3.1 MySQL

將驅動對應的jar包放置到 /usr/share/java/下。

如:/usr/share/java/mysql-connector-java-5.1.32-bin.jar
<span id="4"></span>

4 基本用法

<span id="41"></span>

4.1 導入

sqoop import \
--connect  JDBC_URL      \
--username USERNAME      \
--password PASSWORD   \
--table TABLE        \
--hive-import        \
--split-by SPLIT_BY_COL \
--num-mappers N        \
--hive-database HIVE_DB_NAME    \ 
--hive-table HIVE_TABLE_NAME    \ 
(--hive-partition-key partition_name    \
--hive-partition-value partititon_value    \
附:如果是分區表則需指出分區名稱和分區值)
--columns col1,clo2,col3…     \
--warehouse-dir /user/hive/warehouse/       \
--fields-terminated-by ‘|’     \
--direct                       \
--compress

參數說明

參數 說明
--connect 連接RDBMS的jdbc連接字符串。
示例:--connect jdbc:mysql:// MYSQL_SERVER: PORT / DBNAME
其中:mysql默認端口號為3306;
示例:--connect jdbc:oracle:thin:USERNAME/PASSWORD@ORACLE_SERVER:PORT: SID
其中:Oracle默認端口號為1521;
thin:是驅動方式,“瘦”的意思,直接使用原生的Oracle JDBC驅動;
SID:是一個數據庫的唯一標識符,是建立一個數據庫時系統自動賦予的一個初始ID。
--username 連接RDBMS所使用的用戶名。
--password 連接RDBMS所使用的密碼。
--table 將要導入到hive的表。
--split-by 分割導入任務所使用的字段。需要明確指定,推薦使用主鍵。
--hive-import 插入數據到hive當中,使用hive默認的分隔符。
-m, --num-mappers< n> 使用n個map任務並行導入數據。是指生成的map任務的總數量,
不是同時處於RUNNING狀態的數量。
--hive-database hive當中的數據庫。
-- hive-table hive當中的表名
--hive-partition-key hive分區的列名 。
--hive-partition-value hive分區的值。
--columns < col,col,col…> 從表中導出指定的一組列的數據,用逗號分隔,
oracle中列名需要大寫。
--warehouse-dir (必選)可以指定為-warehouse-dir/user/hive/warehouse/
即導入數據的存放路徑,如果該路徑不存在,會首先創建。
在該路徑下會生成和TABLE(--table)同名的文件夾,該文件夾下存放數據文件。
如果路徑存在,需要保證該文件夾下不存在與TABLE(--table)同名文件。
如果不手動指定,默認是啟動sqoop任務的用戶的home目錄。
--direct 使用快速模式導入
--compress 啟用壓縮,生成的文件為經過壓縮的文件。
默認使用GZIP算法。
通過--compression-codec設置壓縮算法。
通常當空間不夠時可以使用壓縮,不過需要注意,如果壓縮率過大可能導致CPU占用過高。
如果可以,推薦使用snappy。
另外,如果配置了mapreduce的“map輸出壓縮”,
那么即使不適用—compress開關,
導入的數據文件也會使用對應的codec進行壓縮。
--compression-codec 使用Hadoop Codec。(默認gzip)前提是設置了—cpmpress。
其他 可使用 sqoop import 命令查看幫助。

附:對於--warehouse-dir需要指定為/user/hive/warehouse/但在該路徑下不能存在與TABLE(--table)同名的文件,否則導入失敗。當導入成功時,會在該路徑下生成數據文件part-m-XXXXX並且生成與TABLE(--table)同名文件,存放導入成功的標志文件_SUCCESS。

<span id="411"></span>

4.1.1 保護密碼

在sqoop命令中顯式指定密碼會是很不安全的操作,使用操作系統的列出正在執行的命令的方式可以很容易的獲取到密碼。有兩種方式可以解決這個問題。
方式一:使用-P(大寫)參數,在執行命令時再輸入密碼。
方式二:使用--password-file參數,即將密碼存放在參數指定的文件中。
<span id="412"></span>

4.1.2 使用其他文件格式

Sqoop支持3中不同的文件格式,其中一種是文本格式,兩外兩種是二進制格式。二進制格式分別是Avro和SequenceFile。使用--as-avrodatafile或--as-sequencefile以指定具體使用哪種二進制格式。
<span id="413"></span>

4.1.3 壓縮導入的數據

使用—compress或-z參數以壓縮導入之后的數據。默認的壓縮算法為GZip,所有文件的后綴名均為.gz。可以使用—compress-codec來指定其他的codec。如

--compression-codec org.apache.hadoop.io.compress.BZip2Codec

使用壓縮需要將mapreduce中對應的設置項開啟,如mapreduce.output.
compress。
<span id="414"></span>

4.1.4 提高傳輸速度

不同於JDBC接口,direct模式下使用數據庫提供的本地工具進行數據傳輸。在MySQL中使用mysqldump和mysqlimport。對於PostgreSQL,sqoop會使用pg_dump工具來導入數據。使用本地工具會極大提高性能,因為他們針對數據傳輸做了優化,以降低數據庫服務器的負擔。當然也有很多限制,比如並不是所有的數據庫都提供本地工具。目前sqoop的direct模式只支持MySQL和PostgreSQL。
<span id="415"></span>

4.1.5 自定義類型映射

使用—amp-column-java參數來將列列映射到java類以覆蓋sqoop提供的默認的映射關系。
如要將c1、c2、c3分別映射為Float、String、String,對應的設置如下所示。

sqoop import --map-column-java c1=Float,c2=String,c3=String ...

<span id="416"></span>

4.1.6 並行控制

Sqoop默認使用4個並發的map任務來項hadoop傳輸數據。當數據量比較大時可以考慮增加並發執行的map任務的數量以提高傳輸速度。使用參數—num-mappers來控制map任務的數量。
<span id="417"></span>

4.1.7 對NULL值進行編碼

Sqoop使用“null”字符串來代替數據庫中的NULL值。對於文本類型的列,使用—null-string來設置替代NULL值得字符串,對於其他類型的列,則使用—null-non-string來設置。

如果想使用\N來編碼NULL值,則對應sqoop命令中的值為\N, \在JAVA中是轉義字符。

--null-string '\\N' \
--null-non-string '\\N'

<span id="418"></span>

4.1.8 導入所有表

使用如下命令導入所有表。sqoop會一次導入每張表,以避免對數據庫服務器造成額外的負擔。

sqoop import-all-tables \

   --connect jdbc:mysql://mysql.example.com/sqoop \

   --username sqoop \

   --password sqoop

<span id="42"></span>

4.2 增量導入

增量導入是每次只導入新增加的或者需要更新的數據。增量導入會大大降低數據庫服務器的負擔。
<span id="421"></span>

4.2.1 只導入細膩數據

假設我們有INTEGER類型的主鍵,並且只追加新列,並且需要定期將表的狀態同步到Hadoop中。我們需要使用增量導入的功能。典型代碼如下所示。

sqoop import \

   --connect jdbc:mysql://mysql.example.com/sqoop \

   --username sqoop \

   --password sqoop \

   --table visits \

   --incremental append \

   --check-column id \

   --last-value 1

--incremental參數表示使用增量導入,參數值為使用的增量導入的類型。,由於我們只添加而不修改列的值,所以使用append。增量導入中還需要額外的兩個參數:--check-column指定一個列,用於檢查新增加的數據,--last-value包含上次成功導入到Hadoop的值。
<span id="422"></span>

4.2.2 增量導入可變數據

使用lastmodified模式而不是append模式來導入變化的數據。例如使用如下命令導入所last_update_date列大於“2013-05-22 01:01:01”的行。

sqoop import \

   --connect jdbc:mysql://mysql.example.com/sqoop \

   --username sqoop \

   --password sqoop \

   --table visits \

   --incremental lastmodified \

   --check-column last_update_date \

   --last-value "2013-05-22 01:01:01"

增量導入模式lastmodified需要一個日期(可選的類型有date、time、datetime和timestamp)列來保存列被修改的時間。

注:--last-value的值在增量導入時是包含在需要導入的范圍之內的。
Sqoop不會檢查數據是否重復,即不會按照MySQL中那樣更新數據。
<span id="423"></span>

4.2.3 保存last-value

Sqoop導入任務完成后會給出新的last-value,我們可以保存當前下來,以便下次使用。
Sqoop的metastore會保存任務的信息,所以我們創建對應的任務即可。

sqoop job \
   --create visits \
   -- \
   import \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table visits \
   --incremental append \
   --check-column id \
   --last-value 0

執行任務

sqoop job --exec visits

刪除任務

sqoop job --delete visits

查看任務信息,信息中會包含last-value的當前值。

sqoop job --show visits

<span id="424"></span>

4.2.4 在metastore中保存密碼

很不幸,每次使用sqoop job執行任務都需要手動輸入密碼。
解決方式有兩種:
第一種方式,使用password-file(“導入”一章中有介紹);
第二種方式,在sqoop-site.xml中添加如下屬性即可(添加后第一次仍然需要輸入密碼 )。

<property>
   <name>sqoop.metastore.client.record.password</name>
   <value>true</value>
</property>

<span id="425"></span>

4.2.5 客戶端之間共享metastore

啟動metastore服務

sqoop metastore

客戶端連接到metastore服務

sqoop job
   --create visits \
   --meta-connect \              
      jdbc:hsqldb:hsql://metastore.example.com:16000/sqoop \
   -- \
   import \
   --table visits
      ...

顯示任務

sqoop  job --list --meta-connect jdbc:hsqldb:hsql://metastore.example.com:16000/sqoop

<span id="43"></span>

4.3 導出

<span id="431"></span>

4.3.1 hive導出數據到mysql

sqoop export
--connect jdbc:mysql://MYSQL_SERVER:PORT/DBNAME    \
--username USERNAME   \
--table TABLE         \
--export-dir /user/hive/warehouse/HIVE_TABLE_NAME/       \
--num-mappers N           \
--fields-terminated-by ','         

附:對於hive中有null時,導入到MySQL中依然是NULL。
<span id="432"></span>

4.3.2 批量插入

sqoop使用獨立的insert語句來添加每一行記錄,使用如下的方式可以每次插入多條記錄。即批量插入,每次插入10條。

sqoop export \
   -Dsqoop.export.records.per.statement=10 \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --export-dir cities \
   --batch

<span id="433"></span>

4.3.3 導出所有數據或不導出任何數據

我們需要確保或者所有數據均導出成功,或者不導出任何數據。為此我們使用臨時表,即先將數據導出到臨時表(staging-table)中,然后再轉移到目標表中。

sqoop export \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --staging-table staging_cities

<span id="434"></span>

4.3.4 更新已有數據

使用—update-key參數指定一列,該列可以識別出被修改的行,通常是表中的主鍵。例如下面的示例中使用列id來更新cities表。

sqoop export \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --update-key id

可以指定多個列,列之間用逗號隔開。
注意,該操作只會更新已有的數據,不會插入新的數據,
<span id="435"></span>

4.3.5 更新或插入數據

使用如下的參數可以同時插入新數據或更新已有數據。

sqoop export \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --update-key id \
   --update-mode allowinsert

<span id="436"></span>

4.3.6 只導出某些列

Sqoop默認hdfs中的數據和數據庫中有相同數量的列並且順序相同,使用—columns參數可以指定需要導出到數據庫中的列或者指定導出列之間的順序。如只導出coutry和city列,就可以使用如下示例。

sqoop export \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --columns country,city

<span id="437"></span>

4.3.7 編碼NULL值

你可以使用—input-null-string和—input-null-no-string參數來覆蓋NULL值的替換字符串,例如使用‘\N’替換NULL值。

sqoop export \
   --connect jdbc:mysql://mysql.example.com/sqoop \
   --username sqoop \
   --password sqoop \
   --table cities \
   --input-null-string '\\N' \
   --input-null-non-string '\\N'

<span id="5"></span>

5 附:import和export參數詳解

<span id="51"></span>

5.1 import和export工具通用選項

選項 說明
--connect < jdbc-uri > 指定JDBC連接字符串
--connection-manager < class-name > 指定要使用的連接管理器類
--driver < class-name > 指定要使用的JDBC驅動類
--hadoop-mapred-home < dir > 指定$HADOOP_MAPRED_HOME路徑
--help 打印用法幫助信息
--password-file 設置用於存放認證的密碼信息文件的路徑
-P 從控制台讀取輸入的密碼
--password < password > 設置認證密碼
--username < username > 設置認證用戶名
--verbose 打印詳細的運行信息
--connection-param-file < filename > 可選,指定存儲數據庫連接參數的屬性文件

<span id="52"></span>

5.2 數據導入工具import參數詳解

import工具,是將HDFS平台外部的結構化存儲系統中的數據導入到Hadoop平台,便於后續分析。我們先看一下import工具的基本選項及其含義,如下表所示:

選項 說明
--append 將數據追加到HDFS上一個已存在的數據集上
--as-avrodatafile 將數據導入到Avro數據文件
--as-sequencefile 將數據導入到SequenceFile
--as-textfile 將數據導入到普通文本文件(默認)
--boundary-query < statement > 邊界查詢,用於創建分片(InputSplit)
--columns < col,col,col…> 從表中導出指定的一組列的數據
--delete-target-dir 如果指定目錄存在,則先刪除掉
--direct 使用直接導入模式(優化導入速度)
--direct-split-size < n > 分割輸入stream的字節大小(在直接導入模式下)
--fetch-size < n > 從數據庫中批量讀取記錄數
--inline-lob-limit < n > 設置內聯的LOB對象的大小
-m,--num-mappers < n > 使用n個map任務並行導入數據
-e,--query < statement > 導入的查詢語句
--split-by < column-name > 指定按照哪個列去分割數據
--table < table-name > 導入的源表表名
--target-dir < dir > 導入HDFS的目標路徑
--warehouse-dir < dir > HDFS存放表的根路徑
--where < where clause> 指定導出時所使用的查詢條件
-z,--compress 啟用壓縮
--compression-codec < c > 指定Hadoop的codec方式(默認gzip)
--null-string < null-string > 如果指定列為字符串類型,使用指定字符串替換值為null的該類列的值
--null-non-string < null-string > 如果指定列為非字符串類型,使用指定字符串替換值為null的該類列的值

hive參數

選項 說明
--hive-home < dir > Override $HIVE_HOME
--hive-import 插入數據到hive當中,使用hive的默認分隔符
--hive-overwrite 覆蓋hive表中的數據
--create-hive-table 建表,如果表已經存在,該操作會報錯
--hive-table < table-name > 設置到hive當中的表名
--hive-drop-import-delims 導入到hive時刪除 \n, \r, and \01
--hive-delims-replacement 導入到hive時用自定義的字符替換掉\n, \r, and \01
--hive-partition-key hive分區的key
--hive-partition-value < v > hive分區的值
--map-column-hive < map > 類型匹配,sql類型對應到hive類型

HBase參數

選項 說明
--column-family < family > 把內容導入到hbase當中,默認是用主鍵作為split列   --hive-partition-key hive分區的key
--hbase-create-table 創建Hbase表
--hbase-row-key < col > 指定字段作為row key ,如果輸入表包含復合主鍵,用逗號分隔
--hbase-table < table-name > 指定hbase表

<span id="53"></span>

5.3 數據導出工具export參數詳解

export工具,是將HDFS平台的數據,導出到外部的結構化存儲系統中,可能會為一些應用系統提供數據支持。我們看一下export工具的基本選項及其含義,如下表所示:

選項 說明
--validate < class-name > 啟用數據副本驗證功能,僅支持單表拷貝,可以指定驗證使用的實現類
--validation-threshold < class-name > 指定驗證門限所使用的類表
--direct 使用直接導出模式(優化速度)
--export-dir < dir > 導出過程中HDFS源路徑
-m,--num-mappers < n > 使用n個map任務並行導出
--table < table-name > 導出的目的表名稱
--call < stored-proc-name > 導出數據調用的指定存儲過程名
--update-key col-name > 更新參考的列名稱,多個列名使用逗號分隔
--update-mode < mode > 指定更新策略,包括:updateonly(默認)、allowinsert
--input-null-string < null-string > 使用指定字符串,替換字符串類型值為null的列
--input-null-non-string < null-string > 使用指定字符串,替換非字符串類型值為null的列
--staging-table < staging-table-name> 在數據導出到數據庫之前,數據臨時存放的表名稱
--clear-staging-table 清除工作區中臨時存放的數據
--batch 使用批量模式導出

<span id="54"></span>

5.4 Sqoop Job參數詳解

選項 說明
--create < job-id > 定義sqoop job
--delete < job-id> 刪除sqoop job
--exec < job-id> 執行sqoop job
--show < job-id> 查看sqoop job狀態
--list 查看所有sqoop job

 

Sqoop 使用詳解(內含對官方文檔的解析)

 

Sqoop 是 Cloudera 公司創造的一個數據同步工具,現在已經完全開源了。 

目前已經是 hadoop 生態環境中數據遷移的首選,另外還有 ali 開發的 DataX 屬於同類型工具,由於社區的廣泛使用和文檔的健全,調研之后決定使用 Sqoop 來做我們之后數據同步的工具。

我們首先來看下 Sqoop 的工作流

 

 他將我們傳統的關系型數據庫 | 文件型數據庫 | 企業數據倉庫 同步到我們的 hadoop 生態集群中。

同時也可以將 hadoop 生態集群中的數據導回到傳統的關系型數據庫 | 文件型數據庫 | 企業數據倉庫中。

那么 Sqoop 如何抽取數據呢

1. 首先 Sqoop 去 rdbms 抽取元數據。

2. 當拿到元數據之后將任務切成多個任務分給多個 map。

3. 然后再由每個 map 將自己的任務完成之后輸出到文件。

 

Sqoop import Command:

先從最簡單的任務開始

復制代碼
復制代碼
sqoop import\
  --connect jdbc:mysql://10.66.38.125:3306/user_db \
--username cloudera \
--password secretkey \
--table department \
--target-dir /sqoopdata/departments \      # HDFS 的目標存儲位置
--where "department_id = 1000" \         # 指定條件,只有達成這個條件的才會被 import 進來
-- m 1
復制代碼
復制代碼

就這個語句就可以將我們關系型數據庫中的某個表 import 進 HDFS 的某個位置。

 

同樣我們可以 import 某些字段進來生成文件

復制代碼
復制代碼
sqoop import \
  --connect jdbc:mysql://localhost:3306/retry_db \
  --username cloudera \ 
  --password secret \ 
  --table departments \
  --columns "dept_id, name" \  # 指定需要的字段
  --as-avrodatafile        # 指定存成 avro 數據文件
復制代碼
復制代碼

 

如果我們要 import 一個庫里面的所有表可以使用

sqoop import-all-tables \
  --connect jdbc:mysql://localhost:3306/retry_db \
  --username cloudera \
  --password secret \
  --warehouse-dir /mydata    # HDFS parent for table 這個會將所有這些表都放到 HDFS 這個文件夾下面

 

Sqoop import Command:

我們將數據從 Hadooop HDFS 導出向 RDBMS

復制代碼
復制代碼
sqoop export \
  --connect jdbc:mysql://localhost:3306/retry_db \
  --username cloudera \
  --password departments \
  --export-dir /sqoopdata/departments \    # HDFS source path for the export
  --table departments
復制代碼
復制代碼

 

Sqoop Job:

Sqoop 提供一種能力,可以把我們經常會執行的任務存儲成 jobs. 這些 jobs 可以在未來任何一個時間點被我們拿來使用。

復制代碼
復制代碼
sqoop job \
  --create job_name \
  --import \
  --connect jdbc:mysql://localhost:3306/retry_db \
  --username cloudera \
  --password departments 
復制代碼
復制代碼

 

常用姿勢上面就介紹完了,當我們需要將 MySQL 數據同步到 Hive 去的時候如果表還沒有創建我們只需要執行:

復制代碼
復制代碼
sudo-u hive sqoop import \
--connect jdbc:mysql://10.66.38.15:3306/user \      # 連接需要被同步的 MySQL
--username xxx \
--password xxx \
--table user \                         # 需要被同步的表
--delete-target-dir \                     # 之前有同步的文件已經存在刪除掉- m 1 \                             # 開一個 map 這個值得注意,不是每個 source 表都可以輕松被分為多個 map 的。如果你這里要填寫非 1 的數最好去熟悉一些細節
--hive-import \                         
--hive-tableuser.user \
--create-hive-table \                     # 創建 hive 表
--hive-drop-import-delims                  # Drops \n, \r, and \01 from string fields when importing to Hive.
復制代碼
復制代碼

 

如果是表已經創建好而需要全量同步數據執行:

復制代碼
復制代碼
sudo -u hive sqoop import\
--connect jdbc:mysql://10.66.38.125:16033/user \
--username xxx \
--password xxx \
--table user \
--delete-target-dir \
--hive-overwrite \          # 全量重寫數據
- m 1 \
--hive-import \
--hive-table user.user \
--hive-drop-import-delims
復制代碼
復制代碼

 

同樣的 Sqoop 還支持 Hive 的增量同步。但是基於 mapreduce 的全量同步速度也快得超出想象。實測在三機集群上(12核 | 32內存)機器上1分鍾基本能完成對 20 個字段左右的表 250w 條記錄的抽取。並且對目標數據庫機器的壓力不算大。是非常理想的大數據同步工具。

 

Sqoop 的配置參數非常之多,在使用的時候建議先擼一遍文檔(文檔不長大概擼一次 2 3 個小時左右),找到自己需要注意的地方和更多適合自己的功能在使用的時候就能避免踩坑。比如上面使用的   hive-drop-import-delims 參數的使用就是還沒看完文檔就使用造成的坑。我們數據庫中有字段沒有過濾 \n 。有個用戶的名字被誤操作使用 \n 開頭導致 hive 誤以為遇到了換行符,該數據不僅錯亂而且后面字段全部被置為 NULL。要避免這種問題一方面要對這個使用鏈上各個組件有所了解,更是應該讀一讀文檔可以最大程度的避免踩坑。

----------------------------------------------------------分割線----------------------------------------------------------

下面將紀錄一下我全量閱讀 Sqoop 文檔覺得需要紀錄的一些東西。

 

7.2. 語法(Syntax)

首先我們上面看到命令 Sqoop Command 這個 Command 其實是指定 Sqoop 使用哪種 Tool 。

復制代碼
復制代碼
$ sqoop help
usage: sqoop COMMAND [ARGS]

Available commands:
  codegen            Generate code to interact with database records
  create-hive-table  Import a table definition into Hive
  eval               Evaluate a SQL statement and display the results
  export             Export an HDFS directory to a database table
  help               List available commands
  import             Import a table from a database to HDFS
  import-all-tables  Import tables from a database to HDFS
  import-mainframe   Import mainframe datasets to HDFS
  list-databases     List available databases on a server
  list-tables        List available tables in a database
  version            Display version information

See 'sqoop help COMMAND' for information on a specific command.
復制代碼
復制代碼

可以看到我上面舉例的所有內容都只是簡單的使用到了 export 和 import 還有 import-all-tables  工具。 還有非常多的工具沒有使用到。

因為 sqoop 是依賴 hadoop 生態的關系,所以也有響應的查找鏈,因為使用了 CDH 大禮包,所以我只是簡單的安裝了一下,相關的依賴都已經被配置好了包括 path

lrwxrwxrwx 1 root root 23 Nov 13 20:55 /usr/bin/sqoop -> /etc/alternatives/sqoop

 

7.2.1 連接數據庫服務器(Connecting to a Database Server)

下面我們在使用 import tool 的時候遵循這個原則:

sqoop import (generic-args) (import-args)
sqoop-import (generic-args) (import-args)
While the Hadoop generic arguments must precede any import arguments, you can type the import arguments in any order with respect to one another.

當我們在寫語句的時候應該首先使用了 generic-args 參數可以是以下的參數。

Argument Description
--connect <jdbc-uri> Specify JDBC connect string
--connection-manager <class-name> Specify connection manager class to use
--driver <class-name> Manually specify JDBC driver class to use
--hadoop-mapred-home <dir> Override $HADOOP_MAPRED_HOME
--help Print usage instructions
--password-file Set path for a file containing the authentication password
-P Read password from console
--password <password> Set authentication password
--username <username> Set authentication username
--verbose Print more information while working
--connection-param-file <filename> Optional properties file that provides connection parameters
--relaxed-isolation Set connection transaction isolation to read uncommitted for the mappers.

后面的 import args 可選項就非常豐富。

比如可以導入校驗使用的 class 刪除控制參數啥的。

Argument Description
--validate Enable validation of data copied, supports single table copy only.
--validator <class-name> Specify validator class to use.
--validation-threshold <class-name> Specify validation threshold class to use.
--validation-failurehandler <class-name> Specify validation failure handler class to use.

 

Argument Description
--append Append data to an existing dataset in HDFS
--as-avrodatafile Imports data to Avro Data Files
--as-sequencefile Imports data to SequenceFiles
--as-textfile Imports data as plain text (default)
--as-parquetfile Imports data to Parquet Files
--boundary-query <statement> Boundary query to use for creating splits
--columns <col,col,col…> Columns to import from table
--delete-target-dir Delete the import target directory if it exists
--direct Use direct connector if exists for the database
--fetch-size <n> Number of entries to read from database at once.
--inline-lob-limit <n> Set the maximum size for an inline LOB
-m,--num-mappers <n> Use n map tasks to import in parallel
-e,--query <statement> Import the results of statement.
--split-by <column-name> Column of the table used to split work units. Cannot be used with --autoreset-to-one-mapper option.
--split-limit <n> Upper Limit for each split size. This only applies to Integer and Date columns. For date or timestamp fields it is calculated in seconds.
--autoreset-to-one-mapper Import should use one mapper if a table has no primary key and no split-by column is provided. Cannot be used with --split-by <col> option.
--table <table-name> Table to read
--target-dir <dir> HDFS destination dir
--temporary-rootdir <dir> HDFS directory for temporary files created during import (overrides default "_sqoop")
--warehouse-dir <dir> HDFS parent for table destination
--where <where clause> WHERE clause to use during import
-z,--compress Enable compression
--compression-codec <c> Use Hadoop codec (default gzip)
--null-string <null-string> The string to be written for a null value for string columns
--null-non-string <null-string> The string to be written for a null value for non-string columns

 

7.2.3 自由的表查詢導入(Free-form Query Imports)

包括支持 free-form query .使用 --query 參數然后寫一個 sql 來過濾自己想要 import 的數據 just like 

$ sqoop import \
  --query 'SELECT a.*, b.* FROM a JOIN b on (a.id == b.id) WHERE $CONDITIONS' \
  --split-by a.id --target-dir /user/foo/joinresults

這個使用方法必須要使用 --target-dir 

 

7.2.4 掌控並行處理(Controlling Parallelism)

如果需要控制並行操作普遍使用的是 -m 參數,--num-mapers參數。我們可以顯示的指定使用的用來並行分配的鍵,使用例如 --split-by employee_id 達到目標。

如果說我們沒有使用 --split-by 參數主鍵也不是 int 型,可能會導致指定 -m 大於 1 的時候出問題。因為程序沒有辦法知道應該根據哪個鍵來分配 map 任務。

另外我們可以使用 --autoreset-to-one-mapper 選項 --autoreset-to-one-mapper Import should use one mapper if a table has no primary key and no split-by column is provided. Cannot be used with --split-by <col> option.

 

7.2.5 掌控分布式緩存(Controlling Distributed Cache)

使用 Oozie 調起 Sqoop job 執行任務的時候要注意一個 Controlling Distributed Cache 的問題。在第一個Sqoop作業期間,Oozie只會在每個工作節點上對Sqoop依賴項進行一次本地化,並會在工作節點上重用jar來執行子節點作業。在Oozie啟動Sqoop命令時使用option - skip-dist-cache,可以跳過Sqoop將依賴項復制到作業緩存並保存大量I/O的步驟。達到優化的目的。

 

7.2.6 掌控導入過程(Controlling the Import Process)

在控制導入的過程中也有很多優化的地方可以做,例如我們在對關系行數據庫 MySQL 進行導入的時候,可以通過使用關鍵字 --direct 加速導入的速度。他的原理是默認情況下我們會使用 JDBC 對數據庫進行連接,但是有一些數據庫提供了更高性能可以指定數據庫進行轉移的工具。比如 MySQL 提供的 MySQL 提供的工具 mysqldump 使用 --direct 參數就可以嘗試讓 Sqoop 使用這種方式去導出數據,可能會得到更高的效能。當我們在使用 --direct option 的時候還可以傳遞一些潛在的參數給這個命令類似於這樣 將命令跟在 -- 后面

$ sqoop import --connect jdbc:mysql://server.foo.com/db --table bar \
    --direct -- --default-character-set=latin1

就可以將后面的 --default-character-set=latin1 傳遞給 mysqldump 。

在 import 表的時候有兩個指定路徑的參數是沖突的  --warehouse-dir 和 --target-dir 都用於指定將生成的表放到指定的這個目錄下面。他們倆是沖突的,指定其中一個 option 即可。

在默認情況下 import 這個工具都會將表導到一個新的路徑下面。如果路徑下面已經有相同名字的文件存在了,將會被拒絕導入。

如果使用 --append 參數 Sqoop將會將文件導入到臨時的文件目錄,然后重命名該文件成不與目標文件夾里面名字沖突的名字。

 

7.2.7 掌控事務隔離級別(Controlling transaction isolation)

Sqoop 提供讀取數據庫 read-uncommitted 事務的能力,只需要帶上參數 --relaxed-isolation 即可。這個操作真是非常騷啊,一般應該不會用到而且也不是所有數據庫都支持,比如官方文檔說 ORACLE 就是不支持的。

 

7.2.8 掌控 mapping 時候的字段類型(Controlling type mapping

可以對指定同步的表進行 schema 的映射轉換,並且可以指定通過 java 或者 hive 類型的轉換。例如:

復制代碼
復制代碼
Argument    Description
--map-column-java <mapping>    Override mapping from SQL to Java type for configured columns.
--map-column-hive <mapping>    Override mapping from SQL to Hive type for configured columns.

Sqoop is expecting comma separated list of mapping in form <name of column>=<new type>. For example:

$ sqoop import ... --map-column-java id=String,value=Integer
復制代碼
復制代碼

另外需要注意的是  --map-column-hive 使用該參數需要使用 urlencode 對轉換 key value 進行轉換。例如

use DECIMAL(1%2C%201) instead of DECIMAL(1, 1)

如果轉換不正確,Sqoop 會 raise exception

 

7.2.10 增量更新(Incremental Imports)

關於使用 Sqoop 進行增量更新處理, Sqoop 提供了三個字段來處理增量更新相關的內容

Argument Description
--check-column (col) Specifies the column to be examined when determining which rows to import. (the column should not be of type CHAR/NCHAR/VARCHAR/VARNCHAR/ LONGVARCHAR/LONGNVARCHAR)
--incremental (mode) Specifies how Sqoop determines which rows are new. Legal values for mode include append and lastmodified.
--last-value (value) Specifies the maximum value of the check column from the previous import.

Sqoop 本身支持兩種不同的方式進行增量更新,分別是 append 和 lastmodified 我們使用 --incremental 參數去指定要使用的增量更新類型。

增量更新的文章有很多基本上建立在兩個基礎上。(之前的數據如果被 update 沒有辦法通過這兩種增量更新機制被更新)

1. 可以提供類似於自增 id 這樣的字段,並且小於這個點的字段可以從上次這個點位繼續往后增加。使用 --last-value 需要注意的是可以使用 Sqoop job 在第一次指定了開始的 last-value 值之后 Sqoop 會保存下來這次執行完之后 last-value 值的節點,下次執行的時候會基於這個繼續執行。

2. 可以提供一個最后修改的字段,例如 update_time 這樣的字段,所有大於這個 update_time 時間的字段將在下個節點被增量追加到后面。--check-column update_time

 

7.2.11 文檔格式化(File Formats)

我們通常導入兩種格式的文件形式,一種是 textfile 也是默認類型。還有一種是 SequenceFiles

我們可以通過指定 --as-textfile 參數顯示指定使用 textfile 導入。textfile 又稱 delimited text 在非二進制數據情況下非常通用,而且很容易支持類似於像 Hive 這種數據庫表的生成。

SequenceFiels 是一種二進制格式用於往自定義的記錄指定的 data types 中存儲獨立的記錄。這些 data types 表現為 java 的類。

另外我們也可以使用表協議 比如我們可以使用 Apache Avro。

默認情況下 Sqoop 不會幫我們壓縮文件使用 -z 或者 --compress 參數或者使用其他壓縮參數比如 --compression-codec 對 SequenceFile text 或者 Avro 文件進行壓縮。

 

7.2.12. 大的對象的處理(Large Objects)

Sqoop 對 blob 和 clob  columns 都有特別的處理方式。他們盡量不要像常規字段這樣全部 load 進內存進行操作。而是使用流式的方法來進行處理,並且和其他數據進行內聯存儲。(這一塊我完全沒有看懂是什么意思,水平不夠可以自行前往官方文檔查看。。。。。。)

 

Table 6. Output line formatting arguments:

Argument Description
--enclosed-by <char> Sets a required field enclosing character
--escaped-by <char> Sets the escape character
--fields-terminated-by <char> Sets the field separator character
--lines-terminated-by <char> Sets the end-of-line character
--mysql-delimiters Uses MySQL’s default delimiter set: fields: , lines: \n escaped-by: \ optionally-enclosed-by: '
--optionally-enclosed-by <char> Sets a field enclosing character

 默認情況下 Sqoop 會使用逗號 comma(,) 來作為字段之間的分隔符,使用換行符 \n 來區別每一條記錄。

Sqoop 官方文檔推薦我們使用 unambiguous 也就是顯示清晰的去指定字段分隔符和行分隔符。比如直接使用 --mysql-delimiters

下面的敘述我想了很久想翻譯成中文我都覺得不是很直接 所以還是直接貼文檔吧。

If unambiguous delimiters cannot be presented, then use enclosing and escaping characters. The combination of (optional) enclosing and escaping characters will allow unambiguous parsing of lines. For example, suppose one column of a dataset contained the following values:

Some string, with a comma.
Another "string with quotes"

The following arguments would provide delimiters which can be unambiguously parsed:

$ sqoop import --fields-terminated-by , --escaped-by \\ --enclosed-by '\"' ...

(Note that to prevent the shell from mangling the enclosing character, we have enclosed that argument itself in single-quotes.)

The result of the above arguments applied to the above dataset would be:

"Some string, with a comma.","1","2","3"...
"Another \"string with quotes\"","4","5","6"...

Here the imported strings are shown in the context of additional columns ("1","2","3", etc.) to demonstrate the full effect of enclosing and escaping. The enclosing character is only strictly necessary when delimiter characters appear in the imported text. The enclosing character can therefore be specified as optional:

$ sqoop import --optionally-enclosed-by '\"' (the rest as above)...

Which would result in the following import:

"Some string, with a comma.",1,2,3...
"Another \"string with quotes\"",4,5,6...
[Note] Note

Even though Hive supports escaping characters, it does not handle escaping of new-line character. Also, it does not support the notion of enclosing characters that may include field delimiters in the enclosed string. It is therefore recommended that you choose unambiguous field and record-terminating delimiters without the help of escaping and enclosing characters when working with Hive; this is due to limitations of Hive’s input parsing abilities.

The --mysql-delimiters argument is a shorthand argument which uses the default delimiters for the mysqldump program. If you use the mysqldump delimiters in conjunction with a direct-mode import (with --direct), very fast imports can be achieved.

While the choice of delimiters is most important for a text-mode import, it is still relevant if you import to SequenceFiles with --as-sequencefile. The generated class' toString() method will use the delimiters you specify, so subsequent formatting of the output data will rely on the delimiters you choose.

 

Table 8. Hive arguments:

Argument Description
--hive-home <dir> Override $HIVE_HOME
--hive-import Import tables into Hive (Uses Hive’s default delimiters if none are set.)
--hive-overwrite Overwrite existing data in the Hive table.
--create-hive-table If set, then the job will fail if the target hive
  table exists. By default this property is false.
--hive-table <table-name> Sets the table name to use when importing to Hive.
--hive-drop-import-delims Drops \n\r, and \01 from string fields when importing to Hive.
--hive-delims-replacement Replace \n\r, and \01 from string fields with user defined string when importing to Hive.
--hive-partition-key Name of a hive field to partition are sharded on
--hive-partition-value <v> String-value that serves as partition key for this imported into hive in this job.
--map-column-hive <map> Override default mapping from SQL type to Hive type for configured columns. If specify commas in this argument, use URL encoded keys and values, for example, use DECIMAL(1%2C%201) instead of DECIMAL(1, 1).

我們想要使用 Sqoop 抽取 RDBMS 的數據到 Hive 可能是再常見不過的情形了,所以這一部分很重要也可能是我們最常使用的部分。

 

7.2.13 導入數據到 Hive (Importing Data Into Hive)

Sqoop 抽取 RDBMS 的數據到 Hive 會先將數據抽取出來在 HDFS 上的指定路徑上放一下。如果指定路徑上已經有文件,但是 Hive 里面卻沒有你的表你還需要指定 --delete-target-dir 來刪除 HDFS 的文件,然后重新上傳一份。當上傳到 HDFS 結束之后,會使用 Hive 的命令 LOAD DATA INPATH 將文件移動到 Hive 的 warehouse 目錄下面如果指定了 Hive 表的創建表參數會直接創建 Hive 表並且映射上數據。

如果表已經存在了 可以使用 --hive-overwrite 將數據直接覆蓋。雖然Hive支持轉義字符,但它不處理換行字符。此外,它不支持在封閉字符串中包含字段分隔符的封閉字符的概念。因此,在使用Hive時,建議您選擇明確的字段和記錄終止分隔符,而無需轉義和包圍字符;這是由於Hive的輸入解析能力的限制。如果您在將數據導入到Hive時使用了--escapby,--enclosed-by, or -optionally-enclosed-by, Sqoop將打印一條警告消息。

Hive 默認會使用 \n 分割行,使用\01 分割字段。如果說我們的數據里面有這些字段就可能會有沖突,我們需要使用 --hive-drop-import-delims 把這些都替換掉。上面表可以參照這個 option 的意義。另外也可以使用 --hive-delims-replacement 將沖突的字段給替換掉。

另外還有一個值得注意的地方 Hive 表默認將從 RDBMS 里面抽取出來的 NULL value 數據轉換成 null string 。這個在使用的時候就會出現問題,因為之前是一個空,現在卻變成了一個 null 字符串。所以我們需要處理一下, Hive在自己的體系里面使用 \N 來表示 NULL 我們使用 --null-string 和 --null-non-string 參數處理 import job 使用 --input-null-string 和 --input-null-non-string  處理 export job 。舉個🌰

$ sqoop import  ... --null-string '\\N' --null-non-string '\\N'

另外我們可以使用 --hive-partition-key 和 --hive-partition-value 參數來指定分區鍵提升 hive 的處理能力。

這一塊 sqoop 只支持單分區導入。

這一塊更詳細的可以參考一下 hive 文檔。

27.2.5. MySQL: Import of TINYINT(1) from MySQL behaves strangely

Problem: Sqoop is treating TINYINT(1) columns as booleans, which is for example causing issues with HIVE import. This is because by default the MySQL JDBC connector maps the TINYINT(1) to java.sql.Types.BIT, which Sqoop by default maps to Boolean.

Solution: A more clean solution is to force MySQL JDBC Connector to stop converting TINYINT(1) to java.sql.Types.BIT by adding tinyInt1isBit=false into your JDBC path (to create something like jdbc:mysql://localhost/test?tinyInt1isBit=false). Another solution would be to explicitly override the column mapping for the datatype TINYINT(1) column. For example, if the column name is foo, then pass the following option to Sqoop during import: --map-column-hive foo=tinyint. In the case of non-Hive imports to HDFS, use --map-column-java foo=integer.

 

 


免責聲明!

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



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