一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

为什么MySQL的Decimal类型比Float更适合存储金额数据?

时间:2026-07-04 10:34:52 编辑:袖梨 来源:一聚教程网

Decimal能避免浮点误差,因按十进制定点运算;Float/Double用二进制近似导致0.1+0.2≠0.3;DECIMAL(M,D)须显式指定,否则默认DECIMAL(10,0)会截断小数;电商常用DECIMAL(10,2),高精度场景可选DECIMAL(12,4)等;Float显示格式不约束精度,Decimal则硬性校验;Decimal性能略低但金融场景精度优先;上线后修改Decimal精度需锁表重写。

Decimal能避免0.1 + 0.2 = 0.30000000000000004这类计算误差

Float和Double用二进制近似存储十进制小数,0.1在二进制里是无限循环小数,存进去就失真。MySQL对FLOAT执行SELECT 0.1 + 0.2,结果常是0.30000000000000004;而DECIMAL(10,2)会严格按十进制算,结果就是0.30

这不是显示问题,是底层存储和运算逻辑不同:Float走CPU浮点单元,Decimal由MySQL用定点算法逐位计算。

Decimal(M,D)的M和D必须显式指定,不能依赖默认值

DECIMAL不设参数时默认为DECIMAL(10,0),小数位为0——这意味着INSERT INTO t(amount) VALUES(99.99)会被截断成99,钱直接丢掉两位。

  • 电商价格、订单金额:常用DECIMAL(10,2)(最大99999999.99)
  • 需要更高精度的场景(如汇率、分润):用DECIMAL(12,4)DECIMAL(15,6)
  • M最大65,D最大30,但别盲目设大——DECIMAL(65,30)实际占用约33字节,远超DECIMAL(10,2)的5字节

Float插入时会悄悄四舍五入,且不可控

看这个实操对比:

CREATE TABLE t1 (f FLOAT(10,2), d DECIMAL(10,2));INSERT INTO t1 VALUES (1234567.23, 1234567.23);

查出来f列是1234567.25d列才是1234567.23。原因:Float的FLOAT(10,2)只是显示格式,不约束存储精度;而Decimal的DECIMAL(10,2)是硬性约束,超长直接报错Out of range value for column 'd'

更危险的是,Float在WHERE里用=匹配可能失败——WHERE amount = 99.99查不到刚插进去的99.99,因为存进去的其实是99.98999786376953

Decimal性能略低,但对金额场景影响极小

Decimal比Float慢,主要因为:

  • 存储:Decimal按每9位数字占4字节,内部以字符串或压缩BCD编码存;Float固定占4或8字节
  • 计算:Decimal走MySQL自研定点运算,Float走CPU原生指令

但在真实交易系统中,单条金额字段的读写开销微乎其微。真正拖慢数据库的是索引设计、JOIN逻辑、没走索引的WHERE——而不是多花几纳秒算一个加法。拿精度换性能,在金融场景里是本末倒置。

真正容易被忽略的点是:Decimal的精度定义一旦上线就不能轻易改。比如从DECIMAL(10,2)扩到DECIMAL(12,2)要锁表重写数据,而Float改精度几乎无感。所以建表时就得想清楚业务未来3–5年的金额上限和精度需求。

热门栏目