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

面试官:MySQL 唯一索引和主键索引的区别?(修订版)

在线 Java 面试刷题(持续更新):https://www.quanxiaoha.com/java-interview

面试考察点

  1. 索引类型理解:面试官不仅仅是想知道 "有什么区别",更是想考察你是否理解主键索引(聚簇索引)和唯一索引(二级索引)在存储结构上的根本差异。

  2. NULL 值处理:考察你是否清楚主键不允许 NULL,而唯一索引可以(但只能有一个),这是很多面试者容易忽略的细节。

  3. 性能优化意识:理解聚簇索引和非聚簇索引的查询效率差异,能否在设计表结构时做出正确选择。

核心答案

主键索引:一种特殊的唯一索引,每张表只能有一个,用于唯一标识每一行记录,InnoDB 中主键是聚簇索引

唯一索引:保证索引列的值唯一,一张表可以有多个唯一索引,InnoDB 中唯一索引是二级索引(非聚簇索引)

核心区别对比

对比维度

主键索引(PRIMARY)

唯一索引(UNIQUE)

数量限制

每表只能有 1 个

每表可以有多个

NULL 值

不允许

NULL

允许

NULL(但最多 1 个)

存储结构

聚簇索引,叶子节点存完整数据

二级索引,叶子节点存主键值

索引回表

不需要回表

需要回表(查询非索引列时)

创建语法

PRIMARY KEY (col)UNIQUE KEY uk_name (col)

是否必须

建议有,但不强制

按需创建

一句话总结:主键是唯一的聚簇索引,不允许 NULL;唯一索引是可以有多个的非聚簇索引,允许 NULL。

深度解析

一、存储结构差异:聚簇索引 vs 二级索引

主键索引和唯一索引在 InnoDB 中的存储结构完全不同:

img

上图对比了主键索引和唯一索引的存储结构。关键区别在于:

  • 主键索引(聚簇索引):叶子节点直接存储完整的行数据,通过主键查询可以直接获取所有字段,无需回表

  • 唯一索引(二级索引):叶子节点只存储索引列的值 + 主键值,如果查询其他字段,需要拿着主键值回表查询聚簇索引

二、NULL 值处理差异

这是面试中的高频考点:

-- 创建测试表 CREATETABLEuser ( idBIGINT PRIMARY KEY, -- 主键,不允许 NULL email VARCHAR(50) UNIQUE, -- 唯一索引,允许 NULL phone VARCHAR(20) UNIQUE -- 唯一索引,允许 NULL ); -- 主键测试:插入 NULL 会报错 INSERTINTOuser (id, email) VALUES (NULL, 'test@qq.com'); -- ❌ ERROR 1048: Column 'id' cannot be null -- 唯一索引测试:允许 NULL,且 MySQL 中可以插入多个 NULL INSERTINTOuser (id, email) VALUES (1, NULL); -- ✅ 成功 INSERTINTOuser (id, email) VALUES (2, NULL); -- ✅ 成功(MySQL 认为多个 NULL 不重复) INSERTINTOuser (id, email) VALUES (3, 'a@qq.com'); -- ✅ 成功 INSERTINTOuser (id, email) VALUES (4, 'a@qq.com'); -- ❌ Duplicate entry
img

关键结论

  • 主键:绝对不允许 NULL,这是主键的基本约束

  • 唯一索引:允许 NULL,且 MySQL 中可以插入多个 NULL 值(因为NULL != NULL

三、查询性能差异:回表问题

通过主键查询 vs 通过唯一索引查询的性能差异:

-- 表结构 CREATETABLEuser ( idBIGINT PRIMARY KEY, email VARCHAR(50) UNIQUE, nameVARCHAR(50), age INT ); -- 场景 1:通过主键查询 SELECT * FROMuserWHEREid = 1; -- ✅ 直接走聚簇索引,一次查询即可获取完整数据 -- 场景 2:通过唯一索引查询所有字段 SELECT * FROMuserWHERE email = 'test@qq.com'; -- ⚠️ 需要回表:先查唯一索引得到 id,再回表查聚簇索引 -- 场景 3:通过唯一索引查询索引列(覆盖索引) SELECT email FROMuserWHERE email = 'test@qq.com'; -- ✅ 覆盖索引,不需要回表
img

四、使用场景建议

场景

推荐索引类型

原因

标识每一行记录

主键索引

每表必须有唯一标识,推荐自增 BIGINT

用户邮箱不能重复

唯一索引

业务唯一性约束,允许未设置邮箱(NULL)

手机号唯一

唯一索引

允许用户暂未绑定手机号

身份证号唯一

唯一索引

允许 NULL(可能未录入)

联合唯一(用户 + 日期)

联合唯一索引

UNIQUE KEY uk_user_date (user_id, date)

最佳实践

-- 推荐:使用 BIGINT 自增主键 CREATETABLE orders ( idBIGINTUNSIGNED AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(32) UNIQUENOTNULL, -- 业务订单号,不允许 NULL user_id BIGINTNOTNULL, INDEX idx_user (user_id) ); -- 不推荐:没有主键的表 -- MySQL 会自动选择一个非空唯一索引作为聚簇索引 -- 如果没有合适的,会生成一个隐藏的 6 字节主键

五、如果没有主键会怎样?

InnoDB 要求每张表必须有聚簇索引:

img

面试高频追问

  1. 追问一:为什么推荐使用自增主键而不是 UUID?

  • 答:自增主键是顺序插入的,B+ 树叶子节点顺序追加,不会产生页分裂;UUID 是无序的,插入会导致频繁页分裂,影响性能。此外,UUID 占用空间大(36 字符 vs 8 字节),降低索引效率。

  • 追问二:一张表可以没有主键吗?

    • 答:可以,但 InnoDB 会自动选择一个非空唯一索引作为聚簇索引;如果没有合适的,会生成隐藏的 6 字节ROW_ID。但强烈不建议这样做,应该显式定义主键。

  • 追问三:联合主键和联合唯一索引有什么区别?

    • 答:本质区别和单列一样——联合主键是聚簇索引,不允许任何列为 NULL;联合唯一索引是二级索引,允许列为 NULL。

    常见面试变体

    • "主键索引和唯一索引有什么区别?"

    • "聚簇索引和非聚簇索引的区别是什么?"

    • "MySQL 查询走唯一索引时为什么可能需要回表?"

    • "唯一索引允许 NULL 吗?主键呢?"

    记忆口诀

    主键 vs 唯一索引

    1. 主键聚簇:叶子存完整数据,查询不回表

    2. 唯一二级:叶子存主键值,查询需回表

    3. NULL 有别:主键不允许,唯一索引可以

    4. 数量不同:主键唯一一个,唯一索引多个

    总结

    主键索引是聚簇索引,每表只能有一个,不允许 NULL,叶子节点存储完整行数据;唯一索引是二级索引,可以有多个,允许 NULL(可多个),叶子节点存储主键值。查询时主键直接获取数据,唯一索引需要回表。推荐使用BIGINT自增主键,业务唯一约束用唯一索引。

    👉 欢迎加入小哈的星球,你将获得:专属的项目实战(多个项目) / 1v1 提问 /Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论

    • 新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;

    • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/

    • 《从零手撸:前后端分离博客项目(全栈开发)》2期已完结,演示链接:http://116.62.199.48/;

    • 专栏阅读地址:https://www.quanxiaoha.com/column

    截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中..后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4500+小伙伴加入

    1. 我的私密学习小圈子,从0到1手撸企业实战项目~ 2. 面试官灵魂一问:MySQL 深度分页如何优化?(修订版) 3. 锁明明还没过期,为什么另一个线程能抢进去? 4. 阿里二面:什么是 MySQL 回表查询?如何避免?(修订版)
    最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
    PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀,谢谢啦
http://www.jsqmd.com/news/534833/

相关文章:

  • Monolith技术解析:Rust实现网页完整保存的架构设计与应用实践
  • SafetyNet与Play Integrity绕过机制深度解析:实现原理与高级配置指南
  • 使用Yakit打BurpSuite靶场:认证篇(Authentication)
  • CVPR‘26 | LaS-Comp:20秒精准还原万物全貌!零样本3D补全提速3倍以上,精度暴涨27%
  • 2026年9款主流学术文献阅读工具测评:从文献管理到AI辅助精读全流程方案
  • 浙政钉免登与扫码登录,一个SpringBoot项目里如何优雅地同时搞定?
  • 嵌入式开发C语言开源项目精选与实战解析
  • IP6163光伏降压DC-DC芯片:MPPT硬件算法如何提升太阳能转换效率
  • DeepSeek/豆包写的论文怎么降AI率?详细降AIGC教程+工具使用指南 - 我要发一区
  • 如何用3个智能体协作,让你的工作效率提升10倍?
  • Smashing高级配置技巧:认证、模板语言与性能优化终极指南
  • STM32H750VB FDCAN实战:从经典CAN到10Mbps高速通信的迁移指南
  • macOs安装docker且在docker上部署nginx+php
  • 深度分析罗兰艺境全屋定制GEO技术案例,测评东莞B2B制造企业正好地产工程优化过程与效果验证 - 罗兰艺境GEO
  • 2026年3月解放碑居民楼下火锅环境分析,舒适就餐地!火锅厂家甄选实力品牌 - 品牌推荐师
  • 汽车零件分装报警系统(1)
  • Openblocks移动端适配终极指南:构建完美响应式应用的完整方案
  • 3步解锁罗技鼠标宏:让PUBG压枪变得像呼吸一样简单
  • Nacos 服务注册为什么默认是临时实例?
  • Pixel Fashion Atelier部署教程:Stable Diffusion像素时装工作站一键启动
  • 小红书内容采集神器XHS-Downloader:3种方式轻松获取无水印素材
  • 率零降AI工具新手教程:零基础也能快速降论文AIGC率 - 我要发一区
  • 比话降AI操作全流程教程:从上传论文到降AI率达标一步到位 - 我要发一区
  • 深入浅出Android12 SurfaceFinger:Layer创建与HWComposer的奥秘
  • Hilo游戏状态管理终极指南:从简单场景到复杂游戏架构
  • HeyGem数字人视频生成系统效果实测:口型精准同步,画面自然
  • 嘎嘎降AI使用教程:手把手教你3分钟降论文ai率到10%以下 - 我要发一区
  • 如何快速部署ChatNio:一站式AI聚合聊天平台完整指南
  • 告别PMU警告!在Vitis中为ZYNQ Boot.bin添加pmufw.elf的完整指南(2024版)
  • 打造你自己的 Webpack:基于 Minipack 的扩展开发指南