<Issue> Hive 中的浮点数据类型

<Issue> Float data type in Hive

初始化数据:

CREATE TABLE `test.test_data`(
    user VARCHAR(10),
    amount FLOAT) 
TBLPROPERTIES ('transactional'='true');
INSERT INTO `test.test_data`
SELECT 'sonnh', 300000000000
UNION ALL
SELECT 'sonnh1', 1000000000000
UNION ALL
SELECT 'sonnh2', 900000000000;

获取数据:

SELECT * FROM `test.test_data`

结果:

test.test_data.user    test.test_data.amount
sonnh                  299999986000
sonnh1                 1000000000000
sonnh2                 899999990000

我在使用上面的 float 数据类型时遇到问题。谁给我解释一下。

我认为这可以追溯到 Hive 如何存储浮点数、双精度数和小数点的基础知识。

  • 十进制 - 根据文档 - 配置单元存储准确的数值。但实际上蜂巢存储几乎接近实际值,如果实际值超过比例、精度,则为 null。
  • Double(8 字节,双精度)和 Float(4 字节,单精度)- 两者都是浮点数并存储非常接近的数值近似值。所以,如果它必须存储更高范围的东西,近似就不能正常工作。它可以存储大约从 -10^308 到 10^308.

因此,如果您需要财务应用程序,建议使用小数;如果您不关心舍入问题,请使用浮点数或双精度。

下面是对以上三种数据类型的实验。

CREATE TABLE tmp(   a string,     f FLOAT,    db double,    dc decimal(5,4)    )  ;
    insert into tmp SELECT 'id', 900000000000000000,900000000000000000,123.123 ;
    insert into tmp SELECT 'id', 90000000,99900000000000000000,99.999 ;
    insert into tmp SELECT 'id', 99123.456,9000000123.456,9.9999999 ;
    insert into tmp SELECT 'id', 9999999123.456,500000,123.123 ;
    insert into tmp SELECT 'id', 9999999000.456,99900000000000000000999999999999999.12349,9990.099999 ;
    insert into tmp SELECT 'id', 9999999000.456,9990000000000000000099999999999.12349,90.999 ;
    
    select * from tmp;

tmp.a   tmp.f               tmp.db                      tmp.dc  
id      900000020000000000  900000000000000000          123.12300   -- notice that float column cant handle the data and showing different data.
id      90000000            99900000000000000000        99.99900    -- everything is fine because they are within range.
id      99123.45            9000000123.456              10.00000    -- decimal approximated the data to 10 which is very close to actual value.
id      9999999000          500000                      123.12300   --all good
id      9999999000          9.99e+34                    NULL        --Decimal put null because it cant handle the data. Double approximated the data to E34. 
id      9999999000          9.99e+30                    90.99900    --Decimal is good because data is within range. Double approximated the data to E34.