必须用decimal(m,d):业务需数值相等判断或严格四舍五入时,因float存在二进制精度误差,会导致查询、聚合、对账错误;decimal保障数学正确性,而float仅适用于有测量误差且无需等值查询的场景。

金额、计数、配置值这类字段一旦用错类型,上线后改表代价极高,而且可能已经产生精度误差——DECIMAL 是财务和精确计算的唯一安全选择,FLOAT 只适用于对误差不敏感的场景,比如日志中的耗时毫秒估算、传感器原始读数等。
什么时候必须用 DECIMAL(M,D)
只要业务逻辑依赖“数值相等判断”或“严格四舍五入”,就必须用 DECIMAL。这不是性能取舍,而是数学正确性问题。
-
DECIMAL(10,2)存 99999999.99,查出来还是 99999999.99;而FLOAT(10,2)存同样的值,可能返回99999999.98或100000000.00,因为二进制无法精确表示十进制小数 - 涉及聚合(
SUM、AVG)、比较(WHERE amount = 19.99)、导出对账,FLOAT的累积误差会放大 - MySQL 对
FLOAT的(M,D)仅用于显示宽度和插入截断,不约束存储精度;而DECIMAL(M,D)的M和D直接决定存储精度和范围
FLOAT 唯一能用的几个真实场景
FLOAT 不是“不能用”,而是适用面极窄。它只在以下条件同时满足时才可考虑:
- 数值来自物理设备(如温度探头、GPS 经纬度),本身就有测量误差,软件再算准也没意义
- 不做等值查询(
WHERE value = 36.5),只做范围扫描(WHERE value BETWEEN 36.0 AND 37.0) - 不参与金额类业务逻辑,也不导出给财务系统
- 表数据量极大(亿级),且该字段高频写入,确实需要节省那 4 字节空间(
FLOAT占 4 字节,DECIMAL(10,2)平均占 5 字节)
注意:DOUBLE 虽然精度比 FLOAT 高,但仍是浮点,同样存在二进制表示缺陷,不能替代 DECIMAL 用于精确场景。
DECIMAL 的参数设置常见错误
M 和 D 不是越大越好,设错反而引发隐式截断或溢出。
-
DECIMAL(5,2)最大只能存999.99,插入1000.00会被截成999.99,且默认不报错(取决于 SQL mode) -
D不能大于M,比如DECIMAL(3,5)是非法定义,建表失败 - 小数位数
D决定存储粒度,比如金额用DECIMAL(12,2)就够了,别用DECIMAL(20,6)—— 多余位数不提升精度,只增加存储和计算开销 - 如果业务未来可能支持分币(如比特币 satoshi),需提前规划
D,例如DECIMAL(20,8),改类型要锁表
真正容易被忽略的是:哪怕你所有代码都写了 DECIMAL,只要上游应用传入的是 float 类型(比如 Python 的 float、Java 的 double),在构造 SQL 时就已经丢失精度。入库前必须用字符串或定点数类型传递数值,比如 Python 用 str(Decimal('19.99')),而不是 str(19.99)。











