恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

ENUM 和 SET:方便但有代价

  • 首页
  • 资讯中心
  • /
  • ENUM 和 SET:方便但有代价

相关资讯

第 10 章 Agent 安全与权限控制 2026/10/17 10:44:58
(2026|NAVER AI,推测解码/SD,置信门控,Loop-aware Training,用更多 draft 前向换更少 target 前向)DLoop:循环推测解码 2026/10/17 10:39:58
Hi3861鸿蒙开发入门:从RISC-V物联网芯片到Wi-Fi联网实战 2026/10/17 10:39:58

最新资讯

凸优化入门:从凸函数到全局最优的建模与求解
Spring Boot毕业设计选题:公务员考试知识共享平台完整实现指南
人工智能模型组备赛全流程指南:从微调训练到推理加速
YOLOv11+Streamlit多任务视觉整合:检测、旋转框、分割与姿态估计实践
kimi-free-api 完整指南:零成本 3 分钟部署 OpenAI 兼容 Kimi API
2005-2024年 CEO特征数据CEO基本信息数据 xlsx

今日推荐

Qwen3.5-122B-A10B-singprobe幻觉检测实战:AUC 0.7806,如何实时揪出大模型一本正经的胡话?
NetSpot 实战:用信道分析与频宽优化解决 Wi-Fi 卡顿
C++ split() 字符串分割的五种实现与性能实测

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

ENUM 和 SET:方便但有代价

发布时间:2026/10/17 10:44:58
ENUM 和 SET:方便但有代价 个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录ENUM 和 SET方便但有代价一、ENUM 怎么用二、ENUM 的优点2.1 省空间2.2 数据校验2.3 可读性好三、ENUM 的坑3.1 排序按内部序号不是字符串3.2 修改取值要 ALTER TABLE3.3 空字符串的坑3.4 NULL vs 空字符串3.5 不能和其他表的外键/JOIN 友好共处3.6 迁移麻烦四、SET 是什么SET 的问题五、替代方案方案 1TINYINT 应用层常量方案 2VARCHAR CHECK 约束8.0.16方案 3字典表 外键六、怎么选七、什么时候 ENUM 确实合适八、性能对比九、迁移从 ENUM 改成 TINYINT十、CHECK 约束8.0.16小结ENUM 和 SET方便但有代价状态字段用 ENUM 还是 TINYINT这篇文章讲清楚 ENUM 的优缺点和替代方案。一、ENUM 怎么用CREATETABLEorders(idINTPRIMARYKEY,statusENUM(pending,paid,shipped,done,canceled)NOTNULL);INSERTINTOordersVALUES(1,paid);INSERTINTOordersVALUES(2,unknown);-- 严格模式下报错内部存的是整数1, 2, 3…只占1~2 字节。二、ENUM 的优点2.1 省空间statusENUM(...)-- 1 字节statusVARCHAR(20)-- 实际长度 1 字节utf8mb4 下最多 81 字节statusTINYINT-- 1 字节2.2 数据校验无效值插不进去严格模式下。数据库层保证了取值合法。2.3 可读性好SELECT*FROMordersWHEREstatuspaid;-- 比 WHERE status 2 直观三、ENUM 的坑3.1 排序按内部序号不是字符串INSERTINTOtVALUES(b),(a),(c);-- ENUM 定义ENUM(a,b,c)SELECTvFROMtORDERBYv;-- 结果a, b, c ← 按序号排-- 如果定义是 ENUM(c,b,a)SELECTvFROMtORDERBYv;-- 结果c, b, a ← 序号变了这是最大的坑——排序结果依赖定义顺序改定义的顺序会改变已有查询的结果。字符串列会按字母序排SELECTvFROMtORDERBYv;-- VARCHARa, b, c固定如果业务依赖排序用 CASTORDERBYCAST(vASCHAR)但这样用不了索引。3.2 修改取值要 ALTER TABLE-- 加一个新状态ALTERTABLEordersMODIFYstatusENUM(pending,paid,shipped,done,canceled,refunding);要重建表大表很慢。虽然 appending 到末尾时 MySQL 可能不用重建取决于是否改变存储大小但在中间插入、删除、改顺序都会重建。对比 VARCHAR/TINYINT-- 加一个状态不用改表结构INSERTINTOorder_status_dictVALUES(6,refunding);-- 或者应用层加个常量业务变化时需要加新状态ENUM 的代价不小。3.3 空字符串的坑INSERTINTOorders(status)VALUES(xxx);-- 非严格模式插入空字符串 内部序号为 0SELECTstatusFROMordersWHEREstatus;-- 能查到SELECTstatus0FROMorders;-- 0严格模式下会报错但非严格模式会静默写入。3.4 NULL vs 空字符串statusENUM(a,b)NULL-- 可以有 NULLstatusENUM(a,b)NOTNULL-- 可以有序号 0空字符串两者混淆容易出 bug。3.5 不能和其他表的外键/JOIN 友好共处需要字典表时CREATETABLEstatus_dict(codeVARCHAR(20)PRIMARYKEY,nameVARCHAR(50),sort_orderINT,colorVARCHAR(20));ENUM 没法直接 JOIN 出中文名、颜色这些附加信息。3.6 迁移麻烦从 MySQL 迁到其他数据库时ENUM 的兼容性差。四、SET 是什么SET 是可以多选的 ENUMCREATETABLEusers(idINTPRIMARYKEY,permsSET(read,write,delete,admin));INSERTINTOusersVALUES(1,read,write);INSERTINTOusersVALUES(2,read,delete,admin);内部用位运算存最多 64 个成员。-- 查询有 write 权限的SELECT*FROMusersWHEREFIND_IN_SET(write,perms);SELECT*FROMusersWHEREperms2;-- write 是第 2 位-- 加权限UPDATEusersSETpermsperms|2WHEREid1;SET 的问题同样的坑改定义要 ALTER加上最多 64 个成员查询要用FIND_IN_SET或位运算可读性差FIND_IN_SET用不了索引权限这种场景通常需要更灵活的模型SET 用得更少了权限一般用关联表或多对多表。五、替代方案方案 1TINYINT 应用层常量CREATETABLEorders(idINTPRIMARYKEY,statusTINYINTNOTNULLCOMMENT1待支付 2已支付 3已发货 4完成 5取消);应用层classOrderStatus:PENDING1PAID2SHIPPED3DONE4CANCELED5NAMES{1:待支付,2:已支付,3:已发货,4:完成,5:取消}优点加状态不用改表排序按数值可控跨库兼容好缺点SQL 里是数字可读性差要依赖注释和文档方案 2VARCHAR CHECK 约束8.0.16CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,CONSTRAINTchk_statusCHECK(statusIN(pending,paid,shipped,done,canceled)));优点可读性好数据库层有校验加新值只改约束也要 ALTER但不重建数据实际上改 CHECK 约束也要 ALTER TABLE但通常比改 ENUM 轻。方案 3字典表 外键CREATETABLEorder_status(codeVARCHAR(20)PRIMARYKEY,nameVARCHAR(50)NOTNULL,sort_orderINT,colorVARCHAR(20));CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,KEYidx_status(status)-- 可以不加物理外键应用层保证);优点可以存中文名、排序、颜色等元信息加状态插入一条记录即可可以做权限、流程配置缺点要 JOIN 才能拿到名称或者应用层缓存字典这是最灵活的方案适合状态含义丰富、会变化的场景。六、怎么选场景推荐取值固定不变性别、是否、星期ENUM 可以状态可能增加TINYINT / VARCHAR 字典表需要排序且顺序有意义TINYINT序号即顺序需要存中文名等元信息字典表需要 JOIN 出附加信息字典表跨数据库兼容VARCHAR / TINYINT权限/多选关联表不用 SET一句话取值确定不变、不需要附加信息 → ENUM 挺好状态会变、要存元信息 → 用字典表或 TINYINT七、什么时候 ENUM 确实合适-- 性别genderENUM(unknown,male,female)-- 是否启用其实 TINYINT(1) 更好enabledENUM(Y,N)-- 星期weekdayENUM(Mon,Tue,Wed,Thu,Fri,Sat,Sun)-- 支付渠道如果确定就这几种channelENUM(alipay,wechat,card)这些场景取值几乎不会变ENUM 的简洁性才有价值。但说实话几乎不会变这个判断经常出错——业务一年后加了新渠道你就要改表了。八、性能对比-- 测试表CREATETABLEa(sENUM(p,paid,done,cancel)NOTNULL,KEYidx(s));CREATETABLEb(sTINYINTNOTNULL,KEYidx(s));CREATETABLEc(sVARCHAR(20)NOTNULL,KEYidx(s));各 500 万行类型表大小等值查询索引大小ENUM最小最快最小TINYINT一样小一样快一样小VARCHAR(20)大 30%略慢大 3 倍ENUM 和 TINYINT 性能完全一样都是整数存储。VARCHAR 略差但差距通常可以接受。九、迁移从 ENUM 改成 TINYINT-- 1. 加新列ALTERTABLEordersADDCOLUMNstatus_newTINYINT;-- 2. 迁移数据UPDATEordersSETstatus_newCASEstatusWHENpendingTHEN1WHENpaidTHEN2WHENshippedTHEN3WHENdoneTHEN4WHENcanceledTHEN5END;-- 3. 删旧列重命名ALTERTABLEordersDROPCOLUMNstatus;ALTERTABLEorders CHANGE status_newstatusTINYINTNOTNULL;-- 4. 加索引ALTERTABLEordersADDKEYidx_status(status);大表用pt-online-schema-change或 gh-ost 做在线变更。十、CHECK 约束8.0.16替代 ENUM 的一个好选择CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,amountDECIMAL(10,2),CONSTRAINTchk_statusCHECK(statusIN(pending,paid,done)),CONSTRAINTchk_amountCHECK(amount0));INSERTINTOordersVALUES(1,xxx,10);-- ERROR 3819: Check constraint chk_status is violated优点可读性好SQL 里是字符串数据库层校验修改约束不用重建表通常缺点8.0.16 之前不支持索引不如整数高效迁移到其他库时 CHECK 的兼容性查看约束SELECT*FROMinformation_schema.table_constraintsWHEREconstraint_typeCHECK;小结类型优点缺点适用ENUM省空间、可读、有校验改定义要重建表、排序依赖定义顺序取值真不变SET多选压缩存储同样的坑 查询麻烦基本不用TINYINT快、小、易扩展SQL 里可读性差状态会变VARCHAR CHECK可读、有校验空间略大8.0.16字典表最灵活、可存元信息要 JOIN 或缓存复杂状态我的建议状态字段默认不用 ENUM——业务总会变用 TINYINT或 SMALLINT 应用层常量加状态不用改表需要更多元信息用字典表8.0.16 可以考虑 VARCHAR CHECK兼顾可读性和校验ENUM 不是不能用但要清楚它带来的约束排序依赖定义顺序、加取值要改表。这两个特性在业务演进时很容易成为负担。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号