逃离森林
37.60M · 2026-02-26
DECIMAL 是 MySQL 中专门用于存储精确小数的类型。你可以指定总位数和小数位数,比如 DECIMAL(10,2) 表示一共 10 位数字,其中小数部分占 2 位,整数部分 8 位,范围是 -99999999.99 到 99999999.99。
特点:存储的是精确值,不会像 FLOAT/DOUBLE 那样出现浮点误差。非常适合金额这种需要精确计算的场景。
CREATE TABLE orders (
id INT PRIMARY KEY,
amount DECIMAL(10,2)
);
-- 最多存 99999999.99 元
INSERT INTO orders VALUES (1, 12345.67);
BIGINT 是 64 位整数,范围 -2^63 到 2^63-1(约 -9.22×10^18 到 9.22×10^18)。
如果用它存金额,通常需要约定一个最小单位,比如“分”(1 元 = 100 分)。这样,金额就变成了整数存入数据库,显示时再除以相应的倍数。
特点:整数运算极快,且没有精度丢失(因为就是整数),但需要应用层做单位转换。
CREATE TABLE orders (
id INT PRIMARY KEY,
amount_in_cents BIGINT
);
-- 以“分”为单位,12345.67 元存为 1234567
INSERT INTO orders VALUES (1, 1234567);
我们从几个关键维度来对比一下,看看谁更适合存钱。
结论:两者都能保证精度,平手。
DECIMAL(10,2) 整数部分 8 位 + 小数部分 2 位 ≈ 10 位,占用 4 字节(前 9 位)+ 1 字节(剩余 1 位)= 5 字节左右)。位数越多,占用越大。
DECIMAL(M,D)占用的字节数随 M(总位数)变化;当 M ≤ 18 时,DECIMAL 通常 ≤ 8 字节,当 M ≥ 19 时通常 > 8 字节。结论:阈值大致在 M = 18/19:当 M ≤ 18 时,DECIMAL 的存储通常不会超过 BIGINT 的 8 字节;当 M ≥ 19 时,DECIMAL 会占用更多空间。
结论:BIGINT 性能更优,尤其适合需要大量计算的场景。
-- 直接算税率
SELECT amount * 0.01 AS tax FROM orders;
ROUND 等函数。-- 这样会得到浮点数,可能不精确
SELECT (amount_in_cents * 0.01) FROM orders;
-- 更好的做法:先转换为小数,或者用整数运算再处理单位
结论:DECIMAL 在 SQL 中更方便直观;BIGINT 则需要在应用层多一道转换,稍显麻烦。
结论:DECIMAL 更直观,降低沟通成本。
DECIMAL(65,30),几乎无限大,适合超大金额。结论:两者范围都足够,除非是天文数字,否则无压力。
订单金额一般在几元到几十万元之间,需要两位小数(分)。用 DECIMAL(10,2) 非常直观,开发人员写代码时直接映射到 Java 的 BigDecimal,不会出错。
SQL 统计也很方便:
SELECT SUM(amount) FROM orders WHERE create_date = '2023-01-01';
结果直接就是总金额(元),不需要额外处理。
此时推荐 DECIMAL。
比如股票交易,可能涉及到“厘”(0.001 元)甚至更小的单位。如果用 DECIMAL,可以定义 DECIMAL(20,4) 等。但如果数据量巨大(每天上亿笔交易),统计报表时 DECIMAL 的聚合可能成为瓶颈。
此时可以用 BIGINT 以“毫”或“厘”为单位存储,例如 1 元 = 1000 厘。这样所有运算都是整数,性能极高。
-- 以毫为单位存储 -- 12345.678 元
INSERT INTO trades (amount_in_mill) VALUES (12345678);
-- 统计时,应用层拿到整数除以 1000 得到元
但注意,除法会产生小数,需要在应用层用 BigDecimal 处理,避免精度丢失。
BIGINT 更适合高性能、海量数据的场景。
当数据量极大,需要分库分表时,BIGINT 作为整数更容易做分片键,且跨库聚合时整数运算更快。
此时可以考虑 BIGINT。
很多人新手会用 FLOAT 或 DOUBLE 存金额,结果踩坑。因为浮点数在计算机中无法精确表示十进制小数,比如 0.1 在二进制中是无限循环,存进去再取出来可能变成 0.099999994。
做金融计算时,分毫之差都会导致对账不平。所以 绝对不要用浮点数存金额。
| 因素 | DECIMAL | BIGINT(以最小单位存) |
|---|---|---|
| 精度 | 精确小数,无误差 | 精确整数,需约定单位 |
| 存储空间 | 数字较大时占用的空间大,否则反之 | 固定 8 字节 |
| 性能(运算) | 稍慢 | 极快 |
| SQL 开发便利性 | 直接,直观 | 需要单位转换,易出错 |
| 应用层处理 | 简单(如 Java 用 BigDecimal) | 需要手动转换单位 |
| 推荐场景 | 大部分业务系统,对性能不极端敏感 | 高性能、海量数据、需要整数运算的场景 |
BigDecimal 类,完美匹配。金额存储没有绝对的“银弹”,DECIMAL 和 BIGINT 都能胜任,关键看你的业务场景。
如果是普通项目,选 DECIMAL 省心;如果是追求极致性能的大型系统,选 BIGINT 并做好单位封装。
无论选哪种,记得永远不要用 FLOAT/DOUBLE,这是原则问题。