sqoop 是 apache 下用于 rdbms 和 hdfs 互相導資料的工具。本文以 mysql 資料庫為例,實作關系資料庫導入到 hdfs 和 hive。
使用 rpm 安裝即可。
安裝完之後需要下載下傳 mysql jar 包到 sqoop 的 lib 目錄。
這裡使用 hive 的 metastore 的 mysql 資料庫作為關系資料庫,以 tbls 表為例,該表結構和資料如下:
檢視 sqoop 指令說明:
你也可以檢視某一個指令的使用說明:
你也可以使用别名來代替 <code>sqoop (toolname)</code>:
sqoop import 的一個示例如下:
你還可以使用 <code>--options-file</code> 來傳入一個檔案,使用這種方式可以重用一些配置參數:
/users/homer/work/import.txt 檔案内容如下:
使用 sqoop-import 指令可以從關系資料庫導入資料到 hdfs。
注意:
mysql jdbc url 請使用 ip 位址
如果重複執行,會提示目錄已經存在,可以手動删除
如果不指定 <code>--target-dir</code>,導入到使用者家目錄下的 tbls 目錄
你還可以指定其他的參數:
參數
說明
<code>--append</code>
将資料追加到hdfs中已經存在的dataset中。使用該參數,sqoop将把資料先導入到一個臨時目錄中,然後重新給檔案命名到一個正式的目錄中,以避免和該目錄中已存在的檔案重名。
<code>--as-avrodatafile</code>
将資料導入到一個avro資料檔案中
<code>--as-sequencefile</code>
将資料導入到一個sequence檔案中
<code>--as-textfile</code>
将資料導入到一個普通文本檔案中,生成該文本檔案後,可以在hive中通過sql語句查詢出結果。
<code>--boundary-query <statement></code>
邊界查詢,也就是在導入前先通過sql查詢得到一個結果集,然後導入的資料就是該結果集内的資料,格式如:<code>--boundary-query 'select id,no from t where id = 3'</code>,表示導入的資料為id=3的記錄,或者 <code>select min(<split-by>), max(<split-by>) from <table name></code>,注意查詢的字段中不能有資料類型為字元串的字段,否則會報錯
<code>--columns<col,col></code>
指定要導入的字段值,格式如:<code>--columns id,username</code>
<code>--direct</code>
直接導入模式,使用的是關系資料庫自帶的導入導出工具。官網上是說這樣導入會更快
<code>--direct-split-size</code>
在使用上面direct直接導入的基礎上,對導入的流按位元組數分塊,特别是使用直連模式從postgresql導入資料的時候,可以将一個到達設定大小的檔案分為幾個獨立的檔案。
<code>--inline-lob-limit</code>
設定大對象資料類型的最大值
<code>-m,--num-mappers</code>
啟動n個map來并行導入資料,預設是4個,最好不要将數字設定為高于叢集的節點數
<code>--query,-e <sql></code>
從查詢結果中導入資料,該參數使用時必須指定<code>–target-dir</code>、<code>–hive-table</code>,在查詢語句中一定要有where條件且在where條件中需要包含 <code>\$conditions</code>,示例:<code>--query 'select * from t where \$conditions ' --target-dir /tmp/t –hive-table t</code>
<code>--split-by <column></code>
表的列名,用來切分工作單元,一般後面跟主鍵id
<code>--table <table-name></code>
關系資料庫表名,資料從該表中擷取
<code>--delete-target-dir</code>
删除目标目錄
<code>--target-dir <dir></code>
指定hdfs路徑
<code>--warehouse-dir <dir></code>
與 <code>--target-dir</code> 不能同時使用,指定資料導入的存放目錄,适用于hdfs導入,不适合導入hive目錄
<code>--where</code>
從關系資料庫導入資料時的查詢條件,示例:<code>--where "id = 2"</code>
<code>-z,--compress</code>
壓縮參數,預設情況下資料是沒被壓縮的,通過該參數可以使用gzip壓縮算法對資料進行壓縮,适用于sequencefile, text文本檔案, 和avro檔案
<code>--compression-codec</code>
hadoop壓縮編碼,預設是gzip
<code>--null-string <null-string></code>
可選參數,如果沒有指定,則字元串null将被使用
<code>--null-non-string <null-string></code>
示例程式:
參照上表,使用 sql 語句查詢時,需要指定 <code>$conditions</code>
上面指令通過 <code>-m 1</code> 控制并發的 map 數。
這時候檢視 hdfs 中資料(觀察分隔符是否為制表符):
指定空字元串:
如果需要指定壓縮:
附:可選的檔案參數如下表。
<code>--enclosed-by <char></code>
給字段值前後加上指定的字元,比如雙引号,示例:<code>--enclosed-by '\"'</code>,顯示例子:”3”,”jimsss”,”[email protected]”
<code>--escaped-by <char></code>
給雙引号作轉義處理,如字段值為”測試”,經過 <code>--escaped-by "\\"</code> 處理後,在hdfs中的顯示值為:<code>\"測試\"</code>,對單引号無效
<code>--fields-terminated-by <char></code>
設定每個字段是以什麼符号作為結束的,預設是逗号,也可以改為其它符号,如句号<code>.</code>,示例如:<code>--fields-terminated-by</code>
<code>--lines-terminated-by <char></code>
設定每條記錄行之間的分隔符,預設是換行串,但也可以設定自己所需要的字元串,示例如:<code>--lines-terminated-by "#"</code> 以#号分隔
<code>--mysql-delimiters</code>
mysql預設的分隔符設定,字段之間以<code>,</code>隔開,行之間以換行<code>\n</code>隔開,預設轉義符号是<code>\</code>,字段值以單引号<code>'</code>包含起來。
<code>--optionally-enclosed-by <char></code>
enclosed-by是強制給每個字段值前後都加上指定的符号,而<code>--optionally-enclosed-by</code>隻是給帶有雙引号或單引号的字段值加上指定的符号,故叫可選的
生成與關系資料庫表的表結構對應的hive表:
<code>--hive-home <dir></code>
hive的安裝目錄,可以通過該參數覆寫掉預設的hive目錄
<code>--hive-overwrite</code>
覆寫掉在hive表中已經存在的資料
<code>--create-hive-table</code>
預設是false,如果目标表已經存在了,那麼建立任務會失敗
<code>--hive-table</code>
後面接要建立的hive表
<code>--table</code>
指定關系資料庫表名
執行下面的指令會将 mysql 中的資料導入到 hdfs 中,然後建立一個hive 表,最後再将 hdfs 上的檔案移動到 hive 表的目錄下面。
說明:
可以在 hive 的表名前面指定資料庫名稱
可以通過 <code>--create-hive-table</code> 建立表,如果表已經存在則會執行失敗
接下來可以檢視 hive 中的資料:
直接檢視檔案内容:
從上面可見,資料導入到 hive 中之後分隔符為預設分隔符,參考上文你可以通過設定參數指定其他的分隔符。
另外,sqoop 預設地導入空值(null)為 null 字元串,而 hive 使用 \n 去辨別空值(null),故你在 import 或者 export 時候,需要做相應的處理。在 import 時,使用如下指令:
在導出時,使用下面指令:
一個完整的例子如下:
<code>--check-column (col)</code>
用來作為判斷的列名,如id
<code>--incremental (mode)</code>
append:追加,比如對大于last-value指定的值之後的記錄進行追加導入。lastmodified:最後的修改時間,追加last-value指定的日期之後的記錄
<code>--last-value (value)</code>
指定自從上次導入後列的最大值(大于該指定的值),也可以自己設定某一值
将hdfs中不同目錄下面的資料合在一起,并存放在指定的目錄中,示例如:
其中,<code>–class-name</code> 所指定的 class 名是對應于 person.jar 中的 person 類,而 person.jar 是通過 codegen 生成的
<code>--new-data <path></code>
hdfs中存放資料的一個目錄,該目錄中的資料是希望在合并後能優先保留的,原則上一般是存放越新資料的目錄就對應這個參數。
<code>--onto <path></code>
hdfs中存放資料的一個目錄,該目錄中的資料是希望在合并後能被更新資料替換掉的,原則上一般是存放越舊資料的目錄就對應這個參數。
<code>--merge-key <col></code>
合并鍵,一般是主鍵id
<code>--jar-file <file></code>
合并時引入的jar包,該jar包是通過codegen工具生成的jar包
<code>--class-name <class></code>
對應的表名或對象名,該class類是包含在jar包中的。
<code>--target-dir <path></code>
合并後的資料在hdfs裡的存放目錄