mysql创建唯一索引与普通索引的区别与应用

发布时间 - 2026-01-25 00:00:00    点击率:
唯一索引会拒绝重复值插入,普通索引仅加速查询且允许重复;两者均支持多NULL值,联合唯一索引中全NULL行视为可重复;唯一索引写入时需查重,影响高并发性能,但等值查询可触发优化器的const/eq_ref优化。

唯一索引会拒绝重复值插入,普通索引不会

这是最核心的区别。当你在字段上创建 UNIQUE INDEX,MySQL 会在写入时强制校验该字段(或字段组合)的值是否已存在;若存在,直接报错 ERROR

1062 (23000): Duplicate entry ... for key ...。而普通索引(INDEX)只加速查询,对重复值完全放行。

常见踩坑点:

  • 建表时用 UNIQUE 约束比事后加 UNIQUE INDEX 更清晰,语义明确且自动绑定约束名
  • 如果字段允许 NULL,唯一索引允许多个 NULL(MySQL 行为,符合 SQL 标准),但普通索引也一样 —— 这点常被误认为“唯一索引不支持 NULL”
  • 联合唯一索引中,只要任意一列不同,就视为不重复;全为 NULL 的行仍算作可重复(因 NULL != NULL

唯一索引会影响 INSERT/UPDATE 性能,但查询性能与普通索引基本一致

两者底层都使用 B+ 树,查找效率无本质差异。但唯一索引在写入时多了一步“查重”动作:每次 INSERTUPDATE 涉及索引列,MySQL 必须先定位到对应叶子节点,确认无冲突后才写入。这在高并发写入场景下可能成为瓶颈。

实操建议:

  • 不要为了“以后可能去重”提前加 UNIQUE,除非业务逻辑真正需要强唯一性保障
  • 对高频写入、低频查询的字段(如日志表的 trace_id),优先用普通索引;若需去重,改由应用层或异步任务处理
  • 如果已有普通索引,想升级为唯一索引,先用 SELECT COUNT(*) - COUNT(DISTINCT col) 检查是否存在隐性重复,否则 ALTER TABLE ... ADD UNIQUE INDEX 会失败

唯一索引可被优化器当作“等值查询 + 唯一性保证”来优化执行计划

当查询条件命中唯一索引且是等值匹配(如 WHERE user_id = 123),MySQL 优化器知道最多返回一行,因此可能跳过某些检查步骤,甚至在 EXPLAIN 中显示 type: consttype: eq_ref,而普通索引通常只能到 type: ref

这意味着:

  • 主键索引(本质是聚簇唯一索引)和显式 UNIQUE INDEX 都能触发这类优化
  • 如果查询用的是 IN 或范围条件(如 WHERE code >= 'A' AND code ),即使走唯一索引,也不会有 const 优化
  • 复合唯一索引只有满足最左前缀且等值匹配时才生效,例如索引 (a, b)WHERE a = 1 AND b = 2 可用,但 WHERE b = 2 就无法利用

删除重复数据后再建唯一索引的典型操作流程

这是上线前最常见的落地动作。不能直接加唯一索引,必须先清理脏数据。

DELETE t1 FROM users t1
INNER JOIN users t2 
WHERE 
    t1.id > t2.id 
    AND t1.email = t2.email;

然后验证:

SELECT email, COUNT(*) c FROM users GROUP BY email HAVING c > 1;

确认无结果后,再执行:

ALTER TABLE users ADD UNIQUE INDEX uk_email (email);

注意:DELETE ... JOIN 写法比子查询更安全(避免 MySQL 的 “You can't specify target table for update in FROM clause” 错误),且性能更好。

真正麻烦的不是语法,而是如何定义“重复”——比如邮箱大小写是否敏感、空格是否忽略、是否要保留最新/最早的一条。这些逻辑必须在 DELETE 前明确,否则补救成本远高于预防。


# mysql  # ai  # 邮箱  # 异步任务  # 区别  # sql创建  # sql  # NULL  # count  # for  # select  # Error  # const  # 并发  # 异步  # table  # 这是  # 必须先  # 的是  # 也不  # 会有  # 多个  # 最多  # 都能  # 已有  # 你在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 微信小程序 canvas开发实例及注意事项  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?  Laravel如何实现API版本控制_Laravel API版本化路由设计策略  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  Python文本处理实践_日志清洗解析【指导】  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  b2c电商网站制作流程,b2c水平综合的电商平台?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  详解Android——蓝牙技术 带你实现终端间数据传输  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何确保FTP站点访问权限与数据传输安全?  如何用AWS免费套餐快速搭建高效网站?  利用JavaScript实现拖拽改变元素大小  Laravel怎么在Blade中安全地输出原始HTML内容  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  香港服务器WordPress建站指南:SEO优化与高效部署策略  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  Swift中swift中的switch 语句  Laravel如何与Pusher实现实时通信?(WebSocket示例)  手机软键盘弹出时影响布局的解决方法  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  Laravel怎么判断请求类型_Laravel Request isMethod用法  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  JavaScript如何实现继承_有哪些常用方法  如何用花生壳三步快速搭建专属网站?  如何快速上传自定义模板至建站之星?  如何在橙子建站中快速调整背景颜色?  音响网站制作视频教程,隆霸音响官方网站?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  Python函数文档自动校验_规范解析【教程】  Laravel Docker环境搭建教程_Laravel Sail使用指南  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  如何用虚拟主机快速搭建网站?详细步骤解析  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  详解jQuery中基本的动画方法  微信小程序 require机制详解及实例代码  零服务器AI建站解决方案:快速部署与云端平台低成本实践  Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程  网易LOFTER官网链接 老福特网页版登录地址  如何自定义建站之星模板颜色并下载新样式?  北京专业网站制作设计师招聘,北京白云观官方网站?