暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

“劝退篇:MySQL中慎用float类型”




点击上方蓝字关注我们






123457000 + 1 = 123456793?这是什么bug?


1

现象



MySQL的这个“bug”来源于网友的问题,如图:


今天我们这篇文章就从这个问题说起。

有经验的同学第一反应就是这个value字段显然不是整型(MySQL不会犯这么简单的错误),show create table 可以看到,value字段是一个float类型。

而且实际上,这一行是用  insert into demo values(1,123456789); 这个命令插入的。

那么问题来了,float字段这样做,算bug吗?


2

分析



我们从float类型的定义说起:


从这个表格可以看到,float字段占用空间只有4个字节,但是可以表示的数据范围达到10的38次方那么大,这显然不科学。我们都知道4个字节能够表示的不同的数据,就只有2的32次方,即使只表示正数都不可能达到这么大,何况float字段还要能存储小数部分。

为了达到表示这么大的范围的能力,就只能取近似值。

细心的同学会追问,实际存储的是哪个值呢,为什么select出来value和value+1的结果本身也有矛盾。

这就要说到显示问题,由于float理论上长度无限,因此转成字符串类型显示的时候,需要考虑到整数和小数部分分别用用多少字节来显示。

Value字段是float类型,就按照float to string的规则,Value+1计算后的类型是double,就按照double to string的规则。

Double类型的精度更高。

为了验证这个结论,我们可以修改value字段的显示定义,
    alter
    table demo change value value float(100,2);

    再执行查询语句,就得到如下的结果。


    所以实际原因就是,由于float字段存储采用了近似值,因此插入123456789这个值的时候,实际存储的是123456792。

    实际上double字段也有类似的问题,只是因为double有8个字节,要用更大的数字来复现这个“bug”。对于金融等需要精确存储和计算的系统,我们都建议使用decimal字段。


    3

    深究



    以上的结论本就够指导我们平时的使用了。可能有同学还是想再追问一下,float这个用近似值存储的原因是知道了,那这个近似值是怎么算的呢?

    有兴趣的同学可以继续往下看。

    MySQL的浮点数类型(FLOAT和DOUBLE)是用二进制表示的,所以它们不能精确地存储所有的十进制数。当整数部分比较大时,MySQL会用近似值来存储浮点数,这个近似值的取值规则是基于IEEE 754标准的。

    IEEE 754标准定义了浮点数的格式和运算,它将一个浮点数分为三个部分:符号位(S)、指数位(E)和尾数位(M)。符号位表示正负号,指数位表示幂次,尾数位表示有效数字。根据这三个部分,一个浮点数可以表示为:

    其中,M的值是根据尾数位的二进制值和浮点数类型的不同而确定的。对于FLOAT类型,尾数位有23位,所以M的值是:

    其中,bi是第i位的二进制值。对于DOUBLE类型,尾数位有52位,所以M的值是:

    E的值是根据指数位的二进制值和浮点数类型的不同而确定的。对于FLOAT类型,指数位有8位,所以E的值是:

    根据这些公式,我们可以计算出一个浮点数在MySQL中存储时的近似值。例如,假设我们要存储一个十进制数123456789,我们可以先将它转换为二进制形式:

    然后,我们可以将它规范化为以下形式:

    接下来,我们可以根据浮点数类型的不同来确定S、E和M的值。如果我们选择FLOAT类型,那么S、E和M的值分别为:

    注意,由于FLOAT类型只有23位尾数位,所以我们只能保留前23位有效数字,后面的数字被舍弃了。这就导致了精度损失。如果我们将这些值转换回十进制形式,我们得到的近似值就是:




    产品文档
    Klustron 快速入门:
    https://doc.kunlunbase.com/zh/Klustron_Instruction_Manual.html

    Klustron 快速体验指南:
    https://doc.kunlunbase.com/zh/Klustron_Quickly_Guide.html

    Klustron 功能体验范例:
    https://doc.kunlunbase.com/zh/Klustron-function-experience-example.html

    Klustron 产品使用和测评指南:
    https://doc.kunlunbase.com/zh/product-usage-and-evaluation-guidelines.html

    END
    同时欢迎大家扫码👇添加小助手(备注:加入Klustron技术交流群)欢迎大家在交流群共同探讨更多问题及主题。 

     点击👆上方,关注获取源代码及技术信息~


    文章转载自KunlunBase 昆仑数据库,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论