問題(1)
Sqoop導入導出Null存儲一緻性問題
Hive中的Null在底層是以“”\N“”來存儲,而mysql中的Null在底層就是Null,為了保證資料兩端的一緻性,在導出資料時采用--input-null-string和--input-null-non-string兩個參數。導入時采用--null-string和--null-non-string
問題(2)
Sqoop資料導出一緻性問題
如sqoop在導出到mysql時,使用4個map任務,過程中有2個任務失敗,此時mysql中存儲了另兩個map任務導入的資料,此時上司正好看到這個報表資料開發工程師發現之後,調試問題重新執行成功後,上司發現這次的資料跟上次不一樣,這是不允許的。
使用--staing-table 參數,使用臨時表,觸發事物,成功後再導入目标表。
問題(3)
Sqoop底層運作的任務隻有Map階段,沒有reduce階段的任務。
問題(4)
在執行并行導入時,Sqoop需要一個可以劃分工作負載的标準。Sqoop使用一個分割列來分割工作負載。預設情況下,Sqoop将辨別表中的主鍵列(如果存在),并将其用作拆分列。從資料庫中檢索分割列的高值和低值,map任務操作整個範圍的大小均勻的元件。例如,如果你有一個表的主鍵列id的最小值是0,最大值是1000,并且Sqoop直接使用4任務,Sqoop将運作四個程序,每個程序運作不同的任務在這個表上執行SQL語句SELECT * FROM sometable WHERE id >= lo AND id < hi,(lo,hi)設定為(0,250),(250,500),(500,750)和(750,1001)。
如果主鍵的實際值在其範圍内不是均勻分布的,那麼這可能導緻任務不平衡。您應該使用參數--split-by顯式地選擇一個不同的列。例如,--split-by employee_id。Sqoop目前不能在多列索引上拆分。如果表沒有索引列,或者有多列鍵,那麼還必須手動選擇就一個拆分列。
如果表沒有定義主鍵,并且沒有提供--split-by
,那麼導入将失敗,除非使用--num-mappers 1選項或--autoreset-to-one-mapper選項顯式地将mapper數量設定為1。autoreset-to-one-mapper選項通常與import-all-tables工具一起使用,用于自動處理schema中沒有主鍵的表。
sqoop導入導出問題
sqoop export --connect jdbc:mysql://ip:3306/eqpt_base_db?characterEncoding=utf8 --username root --password secret_password --table A_JQZ_T_GAS_GET_ORDER_NUM_INFO_S --export-dir /user/hive/warehouse/origin_ennenergy_energytrade.db/a_jqz_t_gas_get_order_num_info_s --input-null-string '\\N' --input-null-non-string '\\N' --fields-terminated-by '\t'
為了避免空值時,沒有資料,需要以下指令:
--input-null-string '\\N' --input-null-non-string '\\N' --fields-terminated-by '\t'
由sqoop導入失敗發現的hive的空值問題
先說基礎知識
hive中空值分兩種
(1)NULL
hive中null實際在HDFS中預設存儲為'\N',通過查詢顯示的是'NULL'。
這時如果查詢為空值的字段可通過語句:aaa is null 或者 aaa ='\N' 實作。
此時可用hive中與null有關的函數,如nvl,coalesce,is null等判斷是否為null是為true。
産生NULL值,一般都是由hive外連結引起的。
(2)''
'' 表示的是字段不為null且為空字元串,此時用 aaa is null 是無法查詢這種值的,必須通過 aaa =='' 或者 length(aaa)=0 查詢
産生''值,一般都是源資料為空。
之前項目中用到sqoop工具從HDFS中往資料庫中導資料時,任務失敗。不得已,用二分法導資料,去排查問題,看看是哪一條資料導緻任務報錯。最後排查到資料檔案中有字段的值為空。但是奇怪的是,在hive sql裡面已經加為null判斷了。再看資料檔案,發現其中的值不是通常的NULL,或者是\N,而是''。
是以得到原因,用判斷null的nvl函數并不能排除''的情況,需要用IF(aaa == '','未知',aaa) AS aaa 來判斷。