当前位置: 首页 > news >正文

MySQL InnoDB表必须有主键,并且推荐整型自增

【面试题】为什么建议 MySQL InnoDB 表建一个整型自增主键?

  你如果不了解MySQL索引中数据的存储机制、查询过程和插入过程,请参考《浅析二叉树、B树、B+树、B*树和MySQL索引底层原理》,它介绍了二叉树、AVL树、红黑树、B树、B+树和B*树等六种树的数据结构后,浅析MySQL InnoDB索引选择B+树的原因,并给出一些 MySQL 索引高频面试题。这些知识点对回答上述问题非常非常重要,我简明扼要的归纳与本文密切相关的以下几点索引机制:

  • B+树是一种多路平衡搜索树
  • MySQL InnoDB存储引擎的索引在B+树上维护表数据
  • B+树上的每个节点在计算机中叫做数据页,默认大小为16KB
  • 主键索引的叶子节点存储所有数据行,内部节点只存储用于路由的主键值
  • 辅助索引的叶子存储的是主键值而非数据行地址,查询时需通过主键回表
  • 主键索引的叶子通过双向链表链接,其数据行按主键值升序排列,提升范围查询性能

  我们接下来进入正题,回答为什么主键建议是整型且自增这个面试题。MySQL 建议使用‌自增主键‌主要出于‌性能、存储效率和系统稳定性‌的综合考量。

主键为什么是整型

  主键为什么需要设置为整型?查找操作就是不停的进行数据比较,数据比较是消耗CPU资源的,而不同的数据类型耗时不同,字符串之间的比较涉及字符编码和排序规则,因此比整型直接比较大小更复杂更耗时。

‌  减少索引存储空间。从存储空间来说,长整型bigint主键占用8个字节,字符串索引的大小取决于字符集类型和字符串的长度。长度超过8个字节的字符串(如字符串类型的手机号、UUID或者身份证号码)会占用更多的存储空间,从而影响索引的性能。另一方面,由于辅助索引的叶子节点存储主键值,所以主键越小,辅助索引占用空间就越少。

主键为什么需要自增

  为什么需要自增主键呢?原因也可想而知,避免页分裂和页分裂带来的额外I/O操作,提升插入性能。InnoDB的主键索引是按主键ID大小排好序的,如果插入的新数据是自增的,那么只需要按顺序追加到索引末尾,当一页写满,就会自动开辟一个新的页。写入过程如下图所示:

image

  这样就会形成一个紧凑的索引结构,近似顺序填满,提升了数据页的最大填充率,不浪费数据页。由于新记录不需要为计算插入位置而做出额外的消耗,不需要移动已有数据或触发页分裂,也不需要增加很多开销在维护索引上,因此大幅提高写入效率。如果使用非自增主键,由于每次插入主键的位置近似于随机,使得MySQL不得不移动已有数据,甚至目标可能已经被回写到磁盘上而从缓存中清掉了,此时又要从磁盘上读回来,这增加了很多开销;同时频繁的移动记录、页分裂造成了大量的碎片,使得索引结构不够紧凑,后续不得不通过 OPTIMIZE TABLE来重建表,从而消除碎片、回收空间,并让数据页的填充更高效。

  保持数据有序,优化查询性能‌。自增主键的有序性使得B+ 树支持高效的区间扫描(如 WHERE id > 1000 and id < 1100),即从根节点找到满足条件的第一个叶子节点后,无需再遍历内部节点,直接使用叶子节点之间的链接遍历相邻的叶子节点,并提取出在查询范围内的键值对,直到完成区间扫描。

‌  简化系统设计,增强可维护性‌。自增主键由数据库自动生成,与业务逻辑解耦,避免因业务字段变更(如邮箱、手机号)导致主键更新的高成本操作。‌确保唯一性与非空性‌。主键天然保证每行数据唯一且非空,自增机制进一步自动化该过程,降低应用层复杂度。

  引申一下,主键一定需要自增吗?答案是不。我们都知道在分布式系统或者分库分表时,自增主键就显得捉襟见肘不适用了。比如把订单表分成16个表,如果都使用自增ID的话,肯定会造成订单id重复,所以此时的解决方案就是分布式id(如雪花算法、美团Leaf、Redis生成ID等),保证趋势递增即可。

  总之,不应该使用一个具有业务含义的列作为主键,并且一个表必须有一个整型自增主键,为方便扩展、松耦合、高可用的系统做铺垫。

自增主键的缺点

自增ID有那么多好处,有缺点吗?肯定有。下面简单枚举几个:

  • 高并发性能瓶颈:innodb在高并发写入场景下,主键的上界会成为争抢的热点,造成剧烈的锁竞争,导致性能下降。
  • 分布式系统难题:在分布式架构中,自增ID无法实现跨数据库或跨系统的唯一标识,因而难以分布式存储,而且数据迁移和分库分表时会出现ID冲突问题。
  • 安全隐患:自增ID具有可预测性,比如可根据自增来判断订单量。
  • 业务灵活性不足:当业务需要根据特定规则生成ID时,自增ID无法满足需求,缺乏灵活性。

小结

  今天我通过讲解MySQL数据的存储方式以及数据查找与插入过程,从MySQL的底层机制了解了MySQL主键为什么建议使用整型并且自增,最后我们引申了一个分布式id的问题,此时并不强制严格自增,保证趋势递增即可。

  好了,今天的文章就到这里了。快去翻阅一下你写的SQL语句,看看在哪些地方重构可以提升性能吧!

Reference

  • https://cloud.tencent.com/developer/article/2512204
  • MySQL 整数索引与字符串索引的区别
http://www.jsqmd.com/news/480508/

相关文章:

  • 2026冲刺用!8个降AIGC工具全领域适配测评,降AI率一网打尽
  • 2026年羊绒衫厂家深度测评:基于原料、工艺与研发创新的四维对比解析 - 品牌推荐
  • 温柔护孕产,舒适养身心|武汉孕产瑜伽课程,禧悦陪伴全阶段安心练习 - 冠顶工业设备
  • 网联时代下纯电动汽车经济性车速规划探索
  • 2026年羊绒衫厂家合作指南与核心能力适配分析 - 品牌推荐
  • 第0014课 - 用小纸条记方向(定义常量)
  • 【开源】基于51单片机的简易智能楼道照明设计 - 少年
  • 化妆品源头厂家广州悟真产品价格怎样值得选吗 - 工业推荐榜
  • 聊聊那些超实用的切割设备程序
  • Python-flask大学生课表查询和上课提醒系统小程序
  • 聊聊2026年厦门实力强的砖烟囱加固品牌企业,怎么选择? - myqiye
  • 2026年靠谱的酒店宴会桌椅制造商排名,商务酒店宴会桌椅深度剖析 - myqiye
  • 2026回收乙醇市场,哪些源头厂家口碑佳?一文揭晓,回收异丙醇/乙醇/回收废酒精/酒精/回收酒精,回收乙醇供应商排行 - 品牌推荐师
  • Python-flask家庭食谱菜谱食材网上商城系统小程序ko137-vue
  • 第0010课 - 控制速度
  • 聊聊化妆品源头厂家推荐,广州悟真费用多少钱? - 工业品牌热点
  • 第0011课 - 把画坦克也装进魔法盒子
  • 2026年羊绒衫厂家权威榜单发布:十大供应商综合实力深度排位赛 - 品牌推荐
  • Python-flask校园论坛留言系统 微信小程序
  • 第0012课 - 让坦克可以转向
  • MySQL不推荐使用UUID等字符串做主键
  • Python-flask讲师学习视频课程知识题库小程序
  • 19712数字接龙
  • uniapp-vue-微信小程序Python-flask基于微信小程序的摄影作品展览app
  • 第0013课 - 把键盘控制也装进魔法盒子
  • Day38日期对象的使用
  • 大型有机肥生产线服务商费用多少钱,河南建丰价格合理吗? - mypinpai
  • 【笔试真题】- 米哈游-2026.03.14
  • 分析2026年全自动有机肥生产线生产商哪家好,费用情况大揭秘 - 工业设备
  • RV1126 摄像头图像精度BSP调试全景分析