连载中 17/22

字段与表设计:钱不用 double,手机号别用 int

2026-05-10 · 5923 阅读 · 0 评论 · 0 赞

对账差了三分钱

老王的对账系统每月差几毛几分,怎么都对不上。最后抓到真凶:金额字段用了 double。浮点数是二进制近似存储,0.1 都表示不精确,千万笔订单的误差累积起来就是一笔糊涂账。表设计的债,上线那天开始计息——这篇把最贵的坑一次列全。

金额:DECIMAL 或整数分

amount DECIMAL(12,2) NOT NULL DEFAULT 0 COMMENT "订单金额"   -- 精确小数
-- 或:amount_cents BIGINT NOT NULL DEFAULT 0 COMMENT "金额(分)"

两条路都行:DECIMAL 精确直观,整数「分」连乘除误差都没有(Java 侧配合 long 或 BigDecimal),核心原则只有一条——float 和 double 别碰金额

手机号与状态字段

  • 手机号用 varchar(20):别用 int(存不下 11 位数字之外还有国际区号),别用 bigint(丢前导零、加不进 +86)。就按字符串存,它本质是标识不是数字;
  • 状态用 tinyint + 字典表:status char(10) 存中文「已支付」是老项目的经典手笔——改文案要改数据、聚合要函数、索引又宽又慢。tinyint 只占 1 字节,语义交给字典与常量枚举;
  • IP 用 varchar(45) 兼容 IPv6,密码哈希 varchar(100+),二维码 token 这类用 varchar 别 char(char 定长有尾部补位行为,存储省的读时还得剥)。

时间与主键

字段推荐理由
业务时间datetime(3)无时区转换歧义;毫秒精度;范围 9999 年,没有 2038 问题
记录创建/更新datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP数据库自己管,应用忘了赋值也有兜底
主键bigint 自增 / 趋势递增雪花 IDB+ 树顺序追加写(第 3 篇);UUID 随机插入引发页分裂,二级索引全部跟着膨胀

timestamp 也能用(4 字节更省 + 自带时区转换),但 2038 上限和时区行为是隐患——跨时区业务慎用,国内单时区业务用着也没毛病,团队统一即可。

字符集:全库 utf8mb4

MySQL 的 utf8 是残废的 three-byte 实现,存不了 emoji 和部分生僻字——用户昵称存个「😀」直接报错或截断。铁律:库、表、连接三层全 utf8mb4,COLLATE 统一(推荐 utf8mb4_0900_ai_ci)。第 5 篇讲过的「JOIN 字符集不一致索引失效」,根子就在建表没对齐。

NULL 的两笔账

能 NOT NULL + 默认值的列就别允许 NULL:一是 NULL 参与比较和聚合的语义反直觉(count(col) 不数 NULL 行、= NULL 永远为假要用 IS NULL);二是 NULL 列让索引统计、优化器估算更复杂,key_len 还要多 1 字节标记(第 2 篇算过)。确实表示「未知」的语义才用 NULL,别拿 NULL 当默认值偷懒。

设计清单

  • 金额 DECIMAL 或整数分,禁 float/double;
  • 手机号、编号、卡号这类标识用字符串;状态用 tinyint + 字典;
  • 时间 datetime(3),主键 bigint 趋势递增,禁 UUID 主键;
  • utf8mb4 三层统一,COLLATE 一致;
  • NOT NULL + 默认值优先;每表必有小整数 status、create_time、update_time 三件套;
  • 字段数控制、大字段(长文本/JSON)拆扩展表,避免行溢出拖累热查询。

表设计规范立完,接下来是查询侧最经典的两大慢性病:深分页和 count 统计——下一篇一并开方。

咖啡凉了,记得趁热喝。

503

10 年全栈工程师 · 503咖啡馆主理人

#MySQL#表设计#DECIMAL#utf8mb4#主键选型

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 5 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞