Sqoop工具模塊之sqoop-export

Sqoop工具模塊之sqoop-export

1、介紹

該export工具將一組文件從HDFS導入RDBMS。目標表必須已經存在於數據庫中。根據用戶指定的分隔符讀取輸入文件並將其解析爲一組記錄。java

一、模式

sqoop-export有三種模式:mysql

默認模式:將它們轉換爲一組將INSERT語句注入數據庫的語句。sql

更新模式:Sqoop將生成UPDATE替換數據庫中現有記錄的語句。數據庫

調用模式:Sqoop將爲每條記錄建立一個存儲過程調用。bash

二、語法

和以前的導入工具同樣,sqoop-export也有兩種語法:服務器

sqoop export (generic-args) (export-args)
sqoop-export (generic-args) (export-args)

2、參數

一、經常使用參數

--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>:提供鏈接參數的可選屬性文件。
--relaxed-isolation:將鏈接事務隔離設置爲未提交給映射器的讀取。

二、驗證參數app

--validate:啓用對複製數據的驗證,僅支持單個表複製。
--validator <class-name>:指定要使用的驗證程序類。
--validation-threshold <class-name>:指定要使用的驗證閾值類。
--validation-failurehandler <class-name>:指定要使用的驗證失敗處理程序類。

三、導出控制參數

1.參數

--columns <col,col,col…>:要導出到表格的列。
--direct:使用直接導出快速路徑。
--export-dir <dir>:用於導出的HDFS源路徑。
-m,--num-mappers <n>:使用n個mapper任務並行導出。
--table <table-name>:要填充的表。
--call <stored-proc-name>:存儲過程調用。
--update-key <col-name>:錨點列用於更新。若是有多個列,請使用以逗號分隔的列列表。
--update-mode <mode>:指定在數據庫中使用不匹配的鍵找到新行時如何執行更新。mode包含的updateonly默認值(默認)和allowinsert。
--input-null-string <null-string>:字符串列被解釋爲空的字符串。
--input-null-non-string <null-string>:要對非字符串列解釋爲空的字符串。
--staging-table <staging-table-name>:數據在插入目標表以前將在其中展開的表格。
--clear-staging-table:表示能夠刪除登臺表中的任何數據。
--batch:使用批處理模式執行基礎語句。

2.詳解

一條導出語句中,必須有--export-dir參數和一個--table或者--call參數。這些指定要填充到數據庫(或要調用的存儲過程)的表以及HDFS中包含源數據的目錄。工具

1>選擇列oop

--columns參數選擇列並控制它們的排序。性能

默認狀況下,表格中的全部列都被選中用於導出。以逗號爲間隔選擇和排列各個列。

例如:

--columns "col1,col2,col3"

注意:--columns參數中不包含的列須要定義默認值或容許NULL值。不然,數據庫將拒絕導入數據,從而致使sqoop導入失敗。

2>先擇並行

--num-mappers或-m 參數控制mapper任務的數量。默認狀況下,Sqoop將爲導出過程提供4個並行任務。

也能夠根據目錄中存在的文件數來控制mapper的數量。導出性能取決於並行度。

若是數據庫已經在更新索引,調用觸發器等方面遇到瓶頸,則額外的負載可能會下降性能。

3>dircet模式

--direct參數來指定direct模式的代碼路徑。此項可能比標準JDBC的性能更高。

4>字符串轉換

--input-null-string和--input-null-non-string參數都是可選的。若是--input-null-string未指定,那麼對於字符串類型的列,字符串「null」將被解釋爲空。若是--input-null-non-string未指定,則字符串「null」和空字符串將被解釋爲非字符串列的空值。

注意,除了由--input-null-non-string參數指定外,空字符串將始終被解釋爲非字符串列的空值。

5>指定分段表

--staging-table選項充當用於分階段導出數據的輔助表。

因爲Sqoop將導出過程分解爲多個事務,致使失敗的導出做業可能致使部分數據被提交給數據庫。這可能進一步致使後續做業因爲在某些狀況下插入衝突而失敗,或致使其餘數據中的重複數據。那麼這種狀況下就能夠經過指定臨時表來解決此問題,該階段性數據最終在單個事務中移動到目標表中。

爲了使用分段工具,您必須在運行導出做業以前建立分段表。該表必須在結構上與目標表相同。此表應該在導出做業運行以前爲空,或者--clear-staging-table必須指定該選項。若是臨時表包含數據而且指定了--clear-staging-table選項,則Sqoop將在開始導出做業以前刪除分段表中全部數據。

注意:

在將數據導入目標表以前支持暫存數據,可是不可用於--direct導出。--update-key更新現有數據的選項以及存儲過程用於插入數據時調用導出時也不可用。

四、輸入格式參數

--input-enclosed-by <char>:設置必需的字段封閉器。
--input-escaped-by <char>:設置輸入轉義字符。
--input-fields-terminated-by <char>:設置輸入字段分隔符。
--input-lines-terminated-by <char>:設置輸入的行尾字符。
--input-optionally-enclosed-by <char>    設置字段包含字符。

五、輸出格式參數

--enclosed-by <char>:設置必需的字段包圍字符。
--escaped-by <char>:設置轉義字符。
--fields-terminated-by <char>:設置字段分隔符。
--lines-terminated-by <char>:設置行尾字符。
--mysql-delimiters:使用MySQL的默認分隔符集:fields:, lines:\n escaped-by:\ optional-enclosed-by:'。
--optionally-enclosed-by <char>:設置字段包含字符。

Sqoop會自動生成代碼來解析和解釋包含要導出到數據庫的數據的文件記錄。若是這些文件是使用非默認分隔符(以換行符分隔的記錄的逗號分隔字段)建立的,則應該再次指定相同的分隔符,以便Sqoop能夠解析您的文件。

若是指定了不正確的分隔符,則Sqoop將沒法在每行中找到足夠的列。這會致使導出mapper任務失敗並拋出異常:ParseExceptions。

六、代碼生成參數

--bindir <dir>:編譯對象的輸出目錄。
--class-name <name>:設置生成的類名稱。這覆蓋--package-name。與之結合使用時--jar-file,設置輸入類。
--jar-file <file>:禁用代碼生成;使用指定的jar。
--outdir <dir>:生成代碼的輸出目錄。
--package-name <name>:將自動生成的類放入此包中。
--map-column-java <m>:覆蓋已配置列的從SQL類型到Java類型的默認映射。

若是要導出的記錄是做爲先前導入的結果生成的,則可使用原始生成的類讀取數據。在這種狀況下指定--jar-file和--class-name避免指定分隔符。

現有生成的代碼的使用與--update-key是不兼容的;更新模式導出須要新的代碼生成來執行更新。也不能使用--jar-file參數,而且必須徹底指定任何非默認分隔符。

3、插入與更新

一、插入

默認狀況下,sqoop-export將新行添加到表中;每行輸入記錄都被轉換成一條INSERT語句,將此行記錄添加到目標數據庫表中。若是數據庫中的表具備約束條件(例如,其值必須惟一的主鍵列)而且已有數據存在,則必須注意避免插入違反這些約束條件的記錄。若是INSERT語句失敗,導出過程將失敗。此模式主要用於將記錄導出到能夠接收這些結果的空表中。

二、更新

若是指定了--update-key參數,則Sqoop將改成修改數據庫中表中現有的數據。每一個輸入記錄都將轉化爲UPDATE語句修改現有數據。語句修改的行取決於--update-key指定的列名,若是數據庫中的表中不存在的數據,那麼也不會插入。

例如,請考慮下表定義:

CREATE TABLE foo(
    id INT NOT NULL PRIMARY KEY,
    msg VARCHAR(32),
    bar INT);

還要考慮HDFS中包含以下記錄的數據集:

0,this is a test,42
1,some more data,100
...

運行sqoop-export --table foo --update-key id --export-dir /path/to/data --connect …將運行一個導出做業,根據數據執行SQL語句,以下所示:

UPDATE foo SET msg='this is a test', bar=42 WHERE id=0;
UPDATE foo SET msg='some more data', bar=100 WHERE id=1;
...

若是UPDATE語句不修改任何行不會被視爲錯誤;導出將繼續。(實際上,這意味着基於更新的導出不會將新行插入到數據庫中。)一樣,若是--update-key指定的列沒有惟一標識行而且多行由單個語句更新,則此條件也檢測不到。

--update-key參數也能夠用逗號分隔列名稱。在這種狀況下,Sqoop在更新現有記錄以前將匹配參數列表中的全部列。

三、更新or插入

根據目標數據庫的不一樣,若是要更新數據庫中已存在的數據行,或者若是行還沒有存在,也能夠插入行,可使用--update-mode參數指定allowinsert模式。

這個模式下,--update-key指定的字段在數據庫表中必須是惟一非空的(簡單理解主鍵就行),這樣此模式才能實現數據庫表中已存在的數據進行更新,不存在的數據進行插入。不然這個模式會將全部數據都以insert語句插入數據庫中。(這是我踩過的一個坑)。

例如:

在MySQL數據庫中建立一個user_test表,語句以下:

CREATE TABLE `user_test` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Sqoop導出語句

sqoop export --connect jdbc:mysql://localhost:3306/test \
--username root \
-P \
--export-dir '/user/hive/warehouse/test.db/user/000000_0' \
--table user\
--update-key id \
--update-mode allowinsert \
--input-fields-terminated-by '|' \
--input-null-non-string '\\N' \
--input-null-string '\\N' \
--lines-terminated-by '\n' \
-m 1

此時,這裏建立的表沒有主鍵,沒有惟一非空字段,那麼在使用allowinsert模式的時候,即便指定了--update-key的字段爲id,那麼在進行導出的時候,Sqoop也不會去檢查id字段,而是直接選擇insert語句進行插入。

若是想要實現數據庫表中已經存在的數據就更新,不存在的數據就插入,那麼就須要更改MySQL數據庫中表字段的屬性,以下:

CREATE TABLE `user_test` (
  `id` int(11) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

此時就能夠實現想要的操做了。

4、導出的相關問題

一、原子性

導出由多個線程並行執行。每一個線程使用一個鏈接,單獨的鏈接到數據庫;這些線程之間有獨立的事務。

Sqoop使用多行INSERT語法爲每一個語句插入最多100條記錄。每100個語句事務提交一次,也就是每10,000行提交一次。這個機制避免了事務緩衝區無限制地增加致使內存不足的狀況。

所以,導出的整個過程不具備原子性,每條數據仍是具備原子性的。在導出完成以前,已經導出的部分是可見的。

二、導出失敗

導出可能因爲多種緣由而失敗:

1.從Hadoop集羣到數據庫的鏈接丟失(因爲硬件故障或服務器軟件崩潰)

2.嘗試INSERT違反一致性約束的行(例如,插入重複的主鍵值)

3.試圖解析HDFS源數據中的不完整或格式不正確的記錄

4.嘗試使用不正確的分隔符分析記錄

5.容量問題(如內存不足或磁盤空間不足)

若是導出mapper任務因這些或其餘緣由而失敗,則會致使導出做業失敗。導出失敗的結果未定義。每一個導出mapper任務都在單獨的事務中運行。此外,個別mapper按期執行提交當前事務。若是任務失敗,當前事務將被回滾。任何先前提交的事務將在數據庫中保持持久,從而致使部分完成的導出。

5、應用示例

一個基本的導出,將數據導出到bar表:

sqoop export --connect jdbc:mysql://db.example.com/foo --table bar  \
    --export-dir /results/bar_data

此示例將/results/bar_data中的文件內容插入到數據庫中的bar表格中。目標表須要先在數據庫中建立。Sqoop執行一組操做不考慮現有內容。若是Sqoop嘗試在數據庫中插入違反約束的行(例如,特定主鍵值已存在),則導出失敗。foodb.example.comINSERT INTO

能夠導出指定列--columns "col1,col2,col3"。

注意:未包含在--columns參數中的列須要定義默認值或容許NULL值。不然,數據庫將拒絕導入的數據,從而致使Sqoop做業失敗。

另外一個基本導出,啓用驗證將數據導入bar表中:

sqoop export --connect jdbc:mysql://db.example.com/foo --table bar  \
    --export-dir /results/bar_data --validate

調用存儲過程barproc導出/results/bar_data以下所示:

sqoop export --connect jdbc:mysql://db.example.com/foo --call barproc \
    --export-dir /results/bar_data

上一篇:Sqoop工具模塊之sqoop-import-all-tables

下一篇:

相關文章
相關標籤/搜索