使用sqoop import 命令從postgresql導入數(shù)據到hive中,發(fā)現(xiàn)數(shù)據行數(shù)變多了,但是任務沒有跑錯,非常奇怪。
導入語句為:
sqoop import
--connect jdbc:postgresql://*.*.*.*:5432/database_name
--username name111
--password password111
--table table111
--hive-import
--hive-database database111
--hive-table hive_table111
--hive-overwrite
--delete-target-dir
--hive-drop-import-delims
--null-string ''
--null-non-string ''
-m5
導入前pgsql數(shù)據量為3698條,但是導入后再hive中的數(shù)據量為3938,數(shù)據竟然變多了。最后發(fā)現(xiàn)將參數(shù)-m5,改為-m1即可解決問題。
為什么呢?
我們先來了解一下參數(shù)-m的含義以及sqoop導入的原理。
首先用戶輸入一個 Sqoop import 命令,Sqoop 會從關系型數(shù)據庫中獲取元數(shù)據信息,比如要操作數(shù)據庫表的 schema是什么樣子,這個表有哪些字段,這些字段都是什么數(shù)據類型等。它獲取這些信息之后,會將輸入命令轉化為基于 Map 的 MapReduce作業(yè),這樣 MapReduce作業(yè)中有很多 Map 任務,每個 Map 任務從數(shù)據庫中讀取一片數(shù)據,這樣多個 Map 任務實現(xiàn)并發(fā)的拷貝,把整個數(shù)據快速的拷貝到 HDFS 上。
而決定切分成多少個map就是參數(shù)-m的作用,-m5代表切分為5個map,-m1代表切分為1個map,即不用切分。
而決定用什么字段來切分,就是用--split-by來制定的。當sqoop import 沒有定義--split-by時,默認使用源數(shù)據表的key作為切分字段。
split-by 根據不同的參數(shù)類型有不同的切分方法,如int型,Sqoop會取最大和最小split-by字段值,然后根據傳入的num-mappers來 確定劃分幾個區(qū)域。比如select max(split_by),min(split-by) from得到的max(split-by)和min(split-by)分別為1000和1,而num-mappers(-m)為2的話,則會分成兩個區(qū)域 (1,500)和(501-1000),同時也會分成2個sql給2個map去進行導入操作,分別為select XXX from table where split-by>=1 and split-by500和select XXX from table where split-by>=501 and split-by=1000.最后每個map各自獲取各自SQL中的數(shù)據進行導入工作。
那回到最開始的問題,為什么切分數(shù)目不一樣,結果就不一樣呢?理論上無論怎么切分,導入的數(shù)據都應該是一樣的,但現(xiàn)在甚至還多了?這是因為,用來切分的字段不友好,不是int型或者有排序規(guī)律的。
這種id內容是沒有排序規(guī)則的,比如本來10條id切兩份得到(5,5),現(xiàn)在切出來時(5,6),有一個id重復了,就導致數(shù)量變多了。
所以解決辦法有兩個:
一是將 -m5 改成 -m1 直接不切分;
二是 --split-by制定另外的字段,換一個int型的或者有明確排序順序的字段。
除了以上這種原因導致數(shù)據變多,語句缺少 --hive-drop-import-delims 也可能導致問題的出現(xiàn),解決如下:
關于在sqoop導入數(shù)據的時候,數(shù)據量變多的解決方案。
今天使用sqoop導入一張表,我去查數(shù)據庫當中的數(shù)據量為650條數(shù)據,但是我將數(shù)據導入到hive表當中的時候出現(xiàn)了563條數(shù)據,這就很奇怪了,我以為是數(shù)據錯了,然后多導入了幾次數(shù)據發(fā)現(xiàn)還是一樣的問題。
然后我去查數(shù)據字段ID的值然后發(fā)現(xiàn)建了主鍵的數(shù)據怎么可能為空的那。然后我去看數(shù)據庫當中的數(shù)據發(fā)現(xiàn),數(shù)據在存入的時候不知道加入了什么鬼東西,導致數(shù)據從哪一行截斷了,導致多出現(xiàn)了三條數(shù)據。下面是有問題的字段。
這里我也不知道數(shù)據為啥會是這樣,我猜想是在導入數(shù)據的時候hive默認行的分割符號是按照\n的形式導入進來的,到這里遇到了這樣的字符就對其按照下一行進行對待將數(shù)據截斷了。
然后我測試了一直自定義的去指定hive的行的分割符號,使用--lines-terminated-by 指定hive的行的分割符號,但是不幸的是好像這個是不能改的。他會報下面的錯誤:
FAILED: SemanticException 1:424 LINES TERMINATED BY only supports newline '\n' right now. Error encountered near token ''\164'' 于是上網找資料,然后發(fā)現(xiàn)可以使用一個配置清除掉hive當中默認的分割符號,然后導入數(shù)據,配置如下: --hive-drop-import-delims 這個參數(shù)是去掉hive默認的分割符號,加上這個參數(shù)然后在使用--fields-terminated-by 指定hive的行的分割符號 最終數(shù)據導入成功,數(shù)據量和原來數(shù)庫當中的數(shù)據一致。
上面是sqoop腳本的部分內容,下面是執(zhí)行完hive之后,hive創(chuàng)建的表,字段之間默認的分割符號。
至此問題得到了解決。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
您可能感興趣的文章:- 在Hadoop集群環(huán)境中為MySQL安裝配置Sqoop的教程
- sqoop export導出 map100% reduce0% 卡住的多種原因及解決
- 解決sqoop從postgresql拉數(shù)據,報錯TCP/IP連接的問題
- sqoop讀取postgresql數(shù)據庫表格導入到hdfs中的實現(xiàn)
- sqoop 實現(xiàn)將postgresql表導入hive表
- 使用shell腳本執(zhí)行hive、sqoop命令的方法
- Sqoop的安裝與使用詳細教程