sqoop导入失败,数字溢出

时间:2017-04-29 22:49:22

标签: sqoop

sqoop导入作业失败导致:java.sql.SQLException:数字溢出  我必须加载Oracle表,它在Oracle中具有列类型NUMBER,没有缩放,并且它在hive中转换为DOUBLE。这是Oracle和Hive数值的最大可能大小。问题是如何克服这个错误?

2 个答案:

答案 0 :(得分:0)

编辑 该答案假设您的Oracle数据良好,而您的Sqoop作业需要特定配置才能应对 NUMBER 值。事实并非如此,请参阅替代答案。

<小时/> 从理论上讲,它可以解决。

Oracle文档关于&#34;将Oracle表复制到Hadoop&#34; (在其大数据设备中),&#34;创建一个Hive表&#34; &gt; &#34; About datatype conversion&#34; ...

  

NUMBER

     
      
  • 当标度为0且精度小于10
  • 时为INT   
  • 当比例为0且精度小于19
  • 时BIGINT   
  • 当比例大于0或精度大于19
  • 时DECIMAL   

因此,必须找出Oracle表中实际值的范围,然后您就可以指定目标Hive列{{1或BIGINTDECIMAL(38,0)或其他任何内容。


现在,从 Sqoop文档关于&#34; sqoop - import&#34; &gt; &#34; Controlling type mapping&#34; ...

  

Sqoop预先配置为将大多数SQL类型映射到适当的Java或   蜂巢代表。但是,默认映射可能不是   适合所有人,可能会被DECIMAL(22,7)覆盖   (用于更改映射到Java)或--map-column-java(用于更改   Hive mapping)。

     

Sqoop期待逗号分隔的映射列表(...) for   示例
--map-column-hive

警告#1:根据SQOOP-2103,您需要 Sqoop V1.4.7或更高版本才能将该选项与Decimal一起使用,并且您需要&#34; URL编码&#34;逗号,例如对于$ sqoop import ... --map-column-java id=String,value=Integer
DECIMAL(22,7)

警告#2:在您的情况下,当将Oracle值读取到Java变量中,或者写入 Java变量时,不清楚是否发生溢出HDFS文件 - 甚至其他地方。因此,--map-column-hive "wtf=Decimal(22%2C7)"可能还不够 同样,根据that post指向SQOOP-1493--map-column-hive不支持Java类型--map-column-java,直到至少Sqoop V1.4.7 (并且&#39;甚至不清楚该特定选项是否支持它,以及它是否应该是java.math.BigDecimalBigDecimal

<小时/> 在实践中,由于Sqoop 1.4.7并非在所有发行版中都可用,并且由于您的问题没有得到很好的诊断,因此可能不太可行。

因此,我建议您通过将您的流氓Oracle列转换为String,在读取时来隐藏问题。
参看有关&#34; sqoop - import&#34; &gt;的文档&#34; Free-form Query Imports&#34; ...

  

您可以使用java.math.BigDecimal--table--columns参数,而不是使用--where--query$ sqoop import --query 'SELECT a.*, b.* FROM a JOIN b ON a.id=b.id WHERE $CONDITIONS' ...参数   使用SELECT x, y, TO_CHAR(z) AS z FROM wtf参数指定一个SQL语句(...)您的查询必须包含令牌$ CONDITIONS (...)例如:
  {{1}}

在您的情况下,{{1}}加上TO_CHAR内的相应格式,这样您就不会因为四舍五入而丢失任何信息。

答案 1 :(得分:0)

好的,我的第一个答案是假设你的Oracle数据很好,而你的Sqoop作业需要特定的配置才能应对 NUMBER 值。

但现在我怀疑您的Oracle数据包含狗屎,特别是 NaN值,因为计算错误
请参阅该帖子,例如:When/Why does Oracle adds NaN to a row in a database table

Oracle甚至还有明确的“非数字”类别来代表"infinity",以使事情变得更加复杂。

但在Java方面,BigDecimal不支持NaN - 来自documentation,在所有转化方法中......

  

抛出:
  NumberFormatException - 如果值为无限或NaN。

请注意,JDBC驱动程序会屏蔽该异常并显示NumericOverflow,以使调试变得更加复杂......


所以你的问题看起来像那个:Solr Numeric Overflow (from Oracle) - 但不幸的是,SolR允许跳过错误,而Sqoop没有;所以你不能使用同样的技巧。

最后,您必须使用Oracle function NaNVL使用free-form query in Sqoop“屏蔽”这些NaN值:

$ sqoop import --query 'SELECT x, y, NANVL(z, Null) AS z FROM wtf WHERE $CONDITIONS'