1. 程式人生 > 資料庫 >解決sqoop import 匯入到hive後資料量變多的問題

解決sqoop import 匯入到hive後資料量變多的問題

使用sqoop import 命令從postgresql匯入資料到hive中,發現數據行數變多了,但是任務沒有跑錯,非常奇怪。

匯入語句為:

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資料量為3698條,但是匯入後再hive中的資料量為3938,資料竟然變多了。最後發現將引數-m5,改為-m1即可解決問題。

為什麼呢?

我們先來了解一下引數-m的含義以及sqoop匯入的原理。

首先使用者輸入一個 Sqoop import 命令,Sqoop 會從關係型資料庫中獲取元資料資訊,比如要操作資料庫表的 schema是什麼樣子,這個表有哪些欄位,這些欄位都是什麼資料型別等。它獲取這些資訊之後,會將輸入命令轉化為基於 Map 的 MapReduce作業,這樣 MapReduce作業中有很多 Map 任務,每個 Map 任務從資料庫中讀取一片資料,這樣多個 Map 任務實現併發的拷貝,把整個資料快速的拷貝到 HDFS 上。

而決定切分成多少個map就是引數-m的作用,-m5代表切分為5個map,-m1代表切分為1個map,即不用切分。

而決定用什麼欄位來切分,就是用--split-by來制定的。當sqoop import 沒有定義--split-by時,預設使用源資料表的key作為切分欄位。

split-by 根據不同的引數型別有不同的切分方法,如int型,Sqoop會取最大和最小split-by欄位值,然後根據傳入的num-mappers來 確定劃分幾個區域。比如select max(split_by),min(split-by) from得到的max(split-by)和min(split-by)分別為1000和1,而num-mappers(-m)為2的話,則會分成兩個區域 (1,500)和(501-1000),同時也會分成2個sql給2個map去進行匯入操作,分別為select XXX from table where split-by>=1 and split-by<500和select XXX from table where split-by>=501 and split-by<=1000.最後每個map各自獲取各自SQL中的資料進行匯入工作。

解決sqoop import 匯入到hive後資料量變多的問題

那回到最開始的問題,為什麼切分數目不一樣,結果就不一樣呢?理論上無論怎麼切分,匯入的資料都應該是一樣的,但現在甚至還多了?這是因為,用來切分的欄位不友好,不是int型或者有排序規律的。

解決sqoop import 匯入到hive後資料量變多的問題

這種id內容是沒有排序規則的,比如本來10條id切兩份得到(5,5),現在切出來時(5,6),有一個id重複了,就導致數量變多了。

所以解決辦法有兩個:

一是將 -m5 改成 -m1 直接不切分;

二是 --split-by制定另外的欄位,換一個int型的或者有明確排序順序的欄位。

除了以上這種原因導致資料變多,語句缺少 --hive-drop-import-delims 也可能導致問題的出現,解決如下:

關於在sqoop匯入資料的時候,資料量變多的解決方案。

今天使用sqoop匯入一張表,我去查資料庫當中的資料量為650條資料,但是我將資料匯入到hive表當中的時候出現了563條資料,這就很奇怪了,我以為是資料錯了,然後多匯入了幾次資料發現還是一樣的問題。

然後我去查資料欄位ID的值然後發現建了主鍵的資料怎麼可能為空的那。然後我去看資料庫當中的資料發現,資料在存入的時候不知道加入了什麼鬼東西,導致資料從哪一行截斷了,導致多出現了三條資料。下面是有問題的欄位。

解決sqoop import 匯入到hive後資料量變多的問題

這裡我也不知道資料為啥會是這樣,我猜想是在匯入資料的時候hive預設行的分割符號是按照\n的形式匯入進來的,到這裡遇到了這樣的字元就對其按照下一行進行對待將資料截斷了。

然後我測試了一直自定義的去指定hive的行的分割符號,使用--lines-terminated-by 指定hive的行的分割符號,但是不幸的是好像這個是不能改的。他會報下面的錯誤:

FAILED: SemanticException 1:424 LINES TERMINATED BY only supports newline '\n' right now. Error encountered near token ''\164'' 於是上網找資料,然後發現可以使用一個配置清除掉hive當中預設的分割符號,然後匯入資料,配置如下: --hive-drop-import-delims 這個引數是去掉hive預設的分割符號,加上這個引數然後在使用--fields-terminated-by 指定hive的行的分割符號 最終資料匯入成功,資料量和原來數庫當中的資料一致。

解決sqoop import 匯入到hive後資料量變多的問題

解決sqoop import 匯入到hive後資料量變多的問題

上面是sqoop指令碼的部分內容,下面是執行完hive之後,hive建立的表,欄位之間預設的分割符號。

至此問題得到了解決。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。