sqoop导入作业失败导致:java.sql.SQLException:数字溢出 我必须加载Oracle表,它在Oracle中具有列类型NUMBER,没有缩放,并且它在hive中转换为DOUBLE。这是Oracle和Hive数值的最大可能大小。问题是如何克服这个错误?
答案 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或BIGINT
或DECIMAL(38,0)
或其他任何内容。
现在,从 Sqoop文档关于&#34; sqoop - import&#34; &gt; &#34; Controlling type mapping&#34; ...
警告#1:根据SQOOP-2103,您需要 Sqoop V1.4.7或更高版本才能将该选项与Decimal一起使用,并且您需要&#34; URL编码&#34;逗号,例如对于Sqoop预先配置为将大多数SQL类型映射到适当的Java或 蜂巢代表。但是,默认映射可能不是 适合所有人,可能会被
DECIMAL(22,7)
覆盖 (用于更改映射到Java)或--map-column-java
(用于更改 Hive mapping)。Sqoop期待逗号分隔的映射列表(...) for 示例
--map-column-hive
$ 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.BigDecimal
或BigDecimal
)
<小时/> 在实践中,由于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
,以使调试变得更加复杂......
最后,您必须使用Oracle function NaNVL
使用free-form query in Sqoop“屏蔽”这些NaN
值:
$ sqoop import --query 'SELECT x, y, NANVL(z, Null) AS z FROM wtf WHERE $CONDITIONS'