使用Sqoop,最終導入到hive中的數據和原數據庫中數據不一致解決辦法


        Sqoop是一款開源的工具,主要用於在Hadoop(Hive)與傳統的數據庫(mysql、postgresql...)間進行數據的傳遞,可以將一個關系型數據庫(例如 : MySQL ,Oracle ,Postgres等)中的數據導進到Hadoop的HDFS中,也可以將HDFS的數據導進到關系型數據庫中。

1.問題背景

  使用Sqoop把oracle數據庫中的一張表,這里假定為student,當中的數據導入到hdfs中,然后再創建hive的external表,location到剛才保存到hdfs中數據的位置。最后發現對hive中表特定條件進行count時結果和oracle中結果不一致。

1.1 導入數據到hdfs中/user/hadoop/student路徑下     

sqoop import --connect "jdbc:oracle:thin:@//localhost:1521/student" --password "***" --username "***" --query "select * from student where name='zhangsan' and class_id='003' and \$CONDITIONS" --target-dir "/user/hadoop/student" --verbose -m 1

這個時候hdfs上/user/hadoop/student下就保存了從oracle上導入的表數據。

表數據在hdfs上是如何存儲的呢?注意這一點,造成了最后產生結果不一致的錯誤。

我們來看一看在hdfs上數據是如何存儲的。我們運行hadoop fs -cat /user/hadoop/student/part-m-00000,可以看到原來字段與字段之間都用‘,’分隔開,這是sqoop默認的,這時候,如果一個字段值當中包含‘,’,再向hive中插入數據時分隔就會出錯。因為hive也是用‘,’分隔的。

 

2.分析問題

  對hive中表select count(*) from student的結果和oracle中select count(*) from studeng的結果進行比較,發現條數是一樣的,說明沒有少load數據。那為什么對特定條件結果就會不一致,而且hive中條數比oracle中少。也就是同時運行select count(*) from student where class_id='003'

  最后,發現hive用逗號分隔數據時,有幾條數據字段內值包含有逗號,所以字段與值對應起來就亂套了,所以得不到正確結果。

我們建議用‘\001'來進行sqoop 導入數據時的 分割。也就是--fields-terminated-by <char>參數。參考:http://sqoop.apache.org/docs/1.4.2/SqoopUserGuide.html#_large_objects

最后優化后的sqoop語句為:

sqoop import --connect "jdbc:oracle:thin:@//localhost:1521/student" --password "***" --username "***" --query "select * from student where name='zhangsan' and class_id='003' and \$CONDITIONS" --target-dir "/user/hadoop/student" --fields-terminated-by "\001" --verbose -m 1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM