前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >0886-7.1.7-Hive1与Hive3中Decimal数据计算结果精度缺失问题分析

0886-7.1.7-Hive1与Hive3中Decimal数据计算结果精度缺失问题分析

作者头像
Fayson
发布2022-09-27 08:05:38
1.9K0
发布2022-09-27 08:05:38
举报
文章被收录于专栏:Hadoop实操Hadoop实操

1.文档编写目的

将集群从CDH升级到CDP后,Hive1与Hive3在Decimal精度的处理上发生了变化,导致两个版本的Hive在进行Decimal类型的数据计算时存在差异,主要体现在计算结果精度缺失。本篇文章主要从Hive1和Hive3对Decimal类型的处理上进行分析,进而详细解释精度缺失的原因。

Decimal数据类型用于要求非常精确的计算,而 Decimal数据类型允许将数值和计算方法指定为选择参数。在这里精度指的是为这个值保存的有效数字的总数,计数法是指数字在小数点之后的数目。比如,decimal (5,2)规定存储的值不会超过5位数字,并且在小数点后有两个数字。

  • 测试环境说明

1.CDH5.16.2

2.CDP7.1.7

2.测试场景准备

在CDH和CDP集群分别创建相同的表,并初始化相同的数据到表中。

代码语言:javascript
复制
create table decimal_test(a decimal(,), b decimal(,), c decimal(,));

向表中插入测试数据:

代码语言:javascript
复制
insert into decimal_test values(321.333,4.123,1324.855959);
insert into decimal_test values(1.333,1.123,0.12345678912345);

CDP集群查询结果显示如下:

CDH集群查询结果显示如下:

可以看出在CDP中对Decimal类型的精度要求更严格,在小数位不足时会自动补零,以确保数据的精确性。

3.问题现象

在两个集群分别执行如下两个场景SQL1和SQL2:

代码语言:javascript
复制
select -1*c from decimal_test;

CDP集群显示结果如下:

CDH集群显示结果如下:

代码语言:javascript
复制
select a*b*c from decimal_test;

CDP集群显示结果如下:

CDH集群显示结果如下:

计算结果汇总:

SQL

CDH5.16.2

CDP7.1.7

SQL1(-1*c)

-1324.855959

-1324.855959000000

-0.12345678912345

-0.123456789123

SQL2(a*b*c)

NULL

1755243.312098

0.18480975158945058855

0.184810

可以看到CDH和CDP中Hive对Decimal类型数据进行计算时,产生的最终结果存在一定的精度缺失现象。

4.Decimal计算源码分析

在弄清楚Hive处理Decimal数据精度缺失问题上,有必要先熟悉下Hive1和Hive3之间Decimal类型的处理逻辑的差异,在org.apache.hadoop.hive.ql.udf.generic.

GenericUDFOPMultiply类中,可以查看到具体的处理逻辑。

CDH5.16.2版本中Hive的Decimal类型处理逻辑如下截图:

Decimal精度的计算方式比较简单粗暴,两个Decimal类型的数据在进行计算时,precision和scale的值主要是通过传入两个Decimal类型的prec、scale分别进行相加与38相比取最小值,最终得出一个新的Decimal类型。如:decimal(38,14) 与 Decimal(38,14),最终计算的结果为Decimal(38,28)。

CDP7.1.7版本中Hive的Decimal类型处理逻辑:

在CDP的Hive中Decimal的精度计算方式发生了变化,在做精度相加的计算后,还增加了adjustPrecScale的方法,当输入的precision超出了最大值38,则需要对精度进行校准,以确保两个Decimal不会因为精度超出最大值38,造成精度溢出的问题,如下示例:

表格原始数据如下:

a [decimal(38,14)]

b [decimal(38,14)]

c [decimal(38,14)]

321.333

4.123

1324.855959

1.333

1.123

0.12345678912345

  • SQL1场景分析

SQL

CDH5.16.2

CDP7.1.7

SQL1(-1*c)

-1324.855959

-1324.855959000000

-0.12345678912345

-0.123456789123

在SQL1场景中,可以看到字段c的值在乘以-1后,返回的Decimal数值在CDH集群中与预期的结果一致,而在CDP集群中返回的结果精度缺失了2位。

在进行精度计算时,会将-1转化为Decimal(1,0)数据类型,根据Hive1中精度计算公式可以得出-1[decimal(1,0)] * c[decimal(38,14)] = r[decimal(min(38,1+38+1),min(14+0,38))] = r[decimal(38,14)] 结果数据的精度是没有发生变化,因此得出的结果与预期一致;而根据Hive3中的精度计算公式可以得出

-1[decimal(1,0)] * c[decimal(38,14)] = r[Decimal(38, max((38-(1 + 38 +1 - 0 -14), min(0+14,6))))] = r[decimal(38,12)],最终计算后的精度为Decimal(38,12),因此可以看到在CDP集群中计算后精度缺失2位。

  • SQL2场景分析

SQL

CDH5.16.2

CDP7.1.7

SQL2(a*b*c)

NULL

1755243.312098

0.18480975158945058855

0.184810

在SQL2场景中,三个Decimal类型的数据相乘时得到的结果在CDH的Hive1中结果出现了NULL,而在CDP的Hive3中没有输出异常的NULL,但数据的精度再次出现了缺失的现象。

由于精度计算的方法只支持两个Decimal类型的参数,因此在进行超过2个Decimal数据的计算时,会将计算公式进行拆分为((a * b)* c),此时根据这种原则再次套用Hive1的计算公式可以得出:

a[decimal(38,14)] * b[decimal(38,14)] = m[decimal(min(38,38+38+1),min(14+14,38))]

= m[decimal(38,28)]

m[decimal(38,28)]* c[decimal(38,14)] = r[decimal(min(38,38+38+1),min(28+14,38))]

=r[decimal(38,38)]

根据计算得出最终数值的精度为Decimal(38,38),因为precision和scale数值一致该精度则表示计算的最终结果必须小于0,如果大于0的数值,则会导致转换失败显示为NULL的问题,也就是我们上述得到的结果。

Hive3的计算公式可以得出:

a[decimal(38,14)] * b[decimal(38,14)] = m[Decimal(38, max((38-(38 + 38 +1 - 14 -14), min(14+14,6))))] =m[Decimal(38,6)]

m[Decimal(38,6)] * c[decimal(38,14)] = r[Decimal(38, max((38-(38 + 38 +1 - 6 -14), min(6+14,6))))] = r[Decimal(38,6)]

可以看到最终计算出的数据精度为Decimal(38,6),也与最终得到的结果显示的一致,这也就很好的解释了CDH与CDP中计算出来的结果存在一定的差异了。

6.总结

1.在CDP集群中Hive对Decimal类型要求更为严格,在精度不足的情况下会自动补零显示。

2.在CDH的Hive中Decimal类型计算比较简单粗暴,当prec和scale定义的比较大时,在进行计算时会出现precision和scale一致的情况,此时会造成大于0的计算结果返回NULL的现象。

3.CDP集群中的Hive在进行Decimal类型计算时,通过重新校准精度的方式来避免精度溢出而出现异常的计算数据(比如:Hive1中显示的NULL问题)。

4.选择合适的精度来定义自己的Decimal数据,以避免因为过大的设置precision和scale而导致数据在计算的过程中丢失了精度。

5.如果超过两个Decimal数据进行计算时,会自动的根据加减乘除的规则将计算公式拆分,因为deriveResultDecimalTypeInfo方式只支持传入两个Decimal类型进行校准,具体的拆分可以根据Hive的执行计划来查看。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hadoop实操 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
专用宿主机
专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档