问题分析

在 MySQL 中,当一个字段同时存在唯一索引和普通索引时,查询优化器通常会优先选择最严格的索引(即能最快缩小结果集的索引)。在你的场景中,优化器选择了唯一索引并将查询视为const类型,这通常是高效的,但实际性能却不理想。

唯一索引导致全索引扫描:如果查询需要返回其他字段,即使使用唯一索引,也可能需要回表或全索引扫描。

问题就是出在这!

事实上走了唯一索引,很慢,我把唯一索引删了,走普通索引就很快,但是我又希望确保这个字段的唯一性,怎么办

解决方案:保留唯一性约束但优化索引使用

你遇到的情况很常见:唯一索引虽然保证了数据唯一性,但在某些查询模式下可能不如普通索引高效。以下是几种保留唯一性约束同时提升查询性能的方法:

方案一:复合索引优化(推荐)

原理:创建包含唯一字段和常用查询字段的复合索引,让优化器选择更合适的索引路径。

示例
假设表结构如下:

sql

CREATE TABLE users (id INT PRIMARY KEY,unique_id VARCHAR(20) UNIQUE,  -- 导致性能问题的唯一索引name VARCHAR(50),age INT,INDEX idx_name_age (name, age)  -- 普通复合索引
);

优化步骤

  1. 删除原唯一索引

    sql

    ALTER TABLE users DROP INDEX unique_id;
    
  2. 创建包含唯一性约束的复合索引

    sql

    CREATE UNIQUE INDEX idx_unique_id_name ON users (unique_id, name);
    
  3. 查询优化

    sql

    -- 原查询(可能变慢)
    SELECT * FROM users WHERE name = 'John';-- 优化后查询(利用复合索引)
    SELECT unique_id, name FROM users WHERE name = 'John';
    

优势

  • 保留了unique_id的唯一性约束
  • 复合索引可同时满足唯一性和查询性能需求
  • 覆盖索引避免回表,提升查询效率
方案二:触发器实现唯一性检查

原理:通过触发器手动检查插入 / 更新操作的唯一性,替代数据库级别的唯一索引。

示例

sql

-- 创建触发器确保唯一性
DELIMITER $$
CREATE TRIGGER check_unique_id
BEFORE INSERT ON users
FOR EACH ROW
BEGINIF EXISTS (SELECT 1 FROM users WHERE unique_id = NEW.unique_id) THENSIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Duplicate entry for unique_id';END IF;
END$$
DELIMITER ;

优势

  • 完全移除唯一索引,释放索引维护开销
  • 查询可自由使用普通索引

注意事项

  • 触发器会增加插入 / 更新的开销
  • 并发写入时可能出现竞态条件(需配合事务)
  • 建议结合应用层唯一性检查使用
方案三:应用层保证唯一性

原理:在应用代码中实现唯一性检查,而非依赖数据库。

示例伪代码

python

运行

# Python示例
def create_user(unique_id, name):# 1. 开始事务with db.transaction():# 2. 检查唯一性existing = User.query.filter_by(unique_id=unique_id).first()if existing:raise ValueError("Unique ID already exists")# 3. 插入数据user = User(unique_id=unique_id, name=name)db.session.add(user)db.session.commit()

优势

  • 数据库完全不维护唯一索引,查询性能最优
  • 灵活性高,可自定义错误处理逻辑

注意事项

  • 需要强事务保证(Serializable 隔离级别或行锁)
  • 高并发场景下性能可能受影响
  • 必须在所有写入路径中统一实现检查
方案四:哈希索引优化

原理:对唯一字段生成哈希值,用哈希值的唯一索引替代原始字段的唯一索引。

示例

sql

-- 添加哈希字段
ALTER TABLE users ADD COLUMN unique_id_hash INT;-- 计算哈希值并创建唯一索引
UPDATE users SET unique_id_hash = CRC32(unique_id);
CREATE UNIQUE INDEX idx_unique_hash ON users (unique_id_hash);-- 触发器自动维护哈希值
DELIMITER $$
CREATE TRIGGER update_hash
BEFORE INSERT ON users
FOR EACH ROW
BEGINSET NEW.unique_id_hash = CRC32(NEW.unique_id);
END$$
DELIMITER ;

查询优化

sql

-- 原始查询(走普通索引)
SELECT * FROM users WHERE name = 'John';-- 唯一性检查(走哈希唯一索引)
SELECT 1 FROM users WHERE unique_id_hash = CRC32('test_id');

优势

  • 哈希索引更小、查询更快
  • 保留了唯一性约束
  • 原始字段可自由使用普通索引

注意事项

  • 哈希碰撞概率(虽然极低,但需处理)
  • 额外存储开销
  • 插入 / 更新性能略有下降

最佳实践建议

  1. 优先选择复合索引:如果查询模式固定,复合索引是最简单有效的方案。

  2. 监控索引使用情况:定期使用EXPLAIN分析关键查询,确保优化器选择预期的索引。

  3. 分区表考虑:如果表数据量极大,可考虑按unique_id进行哈希分区,分散索引负载。

  4. 读写分离:对唯一性要求极高但读多写少的场景,可将唯一性检查放在从库进行。

根据你的具体业务场景选择最合适的方案,通常复合索引能在保留约束的同时提供良好的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/910599.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/910599.shtml
英文地址,请注明出处:http://en.pswp.cn/news/910599.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARCGIS国土超级工具集1.6更新说明

ARCGIS国土超级工具集V1.6版本,功能已增加至60 个。本次更新在V1.5版本的基础上,除修复了使用时发现的若干小问题外,还更新及新增了若干工具。其中勘测定界工具栏更新了界址点西北角重排工具,新增了提示图斑起始点、指定图斑起始点…

零基础学习RabbitMQ(2)--Linux安装RabbitMQ

注意:这里使用的是ubuntu系统 1. 安装Erlang RabbitMQ需要Erlang语言的支持,在安装rabbitMQ之前需要安装Erlang #更新软件包 sudo apt-get update #安装erlang sudo apt-get install erlang 安装后输入 rel可查看Erlang版本: 输入halt().…

Centos进单用户模式

一、开机按E 二、修改里面的linux行 把ro 修改成rw init/sysroot/bin/sh 修改前: 修改后: 三、ctrl x退出,进入单用户模式

RabbitMQ 的工作流程

RabbitMQ 是一个消息中间件,实现了生产者消费者模型,可以用来接收、存储、转发消息。 专有名词介绍 要了解 RabbitMQ 的工作流程,我们需要先了解下面几个关键词: 1、Producer 生产者,即向 RabbitMQ 发送消息。 2…

HTTP——不同版本区别

目录 HTTP1.0和HTTP1.1的区别 HTTP1.1相比HTTP1.0性能上的改进: 但是HTTP1.1还是有性能瓶颈: HTTP/2做了什么优化? HTTP/3的优点 HTTP与HTTPS的区别 HTTPS的工作原理 1.ClientHello 2.ServerHello 3.客户端回应 4.服务器的最后回应…

关于M0+芯片的IAP应用导致延时不准确解释

前言:在给项目中使用的M0芯片做IAP功能时一切一切都是那么的自然水到渠成,但是笔者在实现完IAP功能后,却发现APP端挂载的单总线功能崩溃了,最开始没有怀疑是bootload导致的。因为笔者在使用同一篇代码的时候单总线挂载的设备不同&…

安卓登录学习笔记

1. 背景与目标 (Background and Goal) 背景: 我们要创建一个用户登录界面。用户输入用户名和密码,点击“登录”按钮。应用会显示一个加载中的“圈圈”(ProgressBar),然后模拟一个耗时2秒的网络请求。根据请求结果,界面…

Git(三):分支管理

文章目录 Git(三):分支管理理解分支创建分支切换分支合并分支删除分支合并冲突分支管理策略分支策略Bug分支删除临时分支 Git(三):分支管理 理解分支 本章介绍Git的杀手级功能之一:分支 分支就 是科幻电影里面的平行宇宙,当你正…

电子电气架构 --- 电气架构基础(汽车电子)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

RestClient 功能介绍、完整使用示例演示, 和RestTemplate、WebClient 对比

RestClient功能介绍 RestClient是Spring Framework 6.1版本引入的同步HTTP客户端,旨在替代老旧的RestTemplate,提供更现代、流畅的API设计。其核心特点包括: 流畅API(Fluent API): 支持链式调用&#xff0…

VM经常遇见的运行慢几种情况、以及设置方法

大家好,我是东哥说-MES 启动虚拟机是提示如下内容 “无法打开内核设备“\.\VMCIDev\VMX”: 操作成功完成。是否在安装 VMware Workstation 后重新引导? 模块“DevicePowerOn”启动失败。 未能启动虚拟机。” 2.用记事本打开安装目录下TIA Portal STEP7 Prof Safety WinCC …

【C++语法】类和对象(4)——日期类和const成员函数

6.类和对象&#xff08;4&#xff09; 文章目录 6.类和对象&#xff08;4&#xff09;回顾简单日期类的实现代码补充&#xff1a;前置与后置的重载区别补充&#xff1a;关于流插入运算符&#xff08;<<&#xff09;的解释拓展&#xff1a;仿照流插入操作符(<<)的作…

当凌晨的键盘声,遇见黎明的星光​

地铁玻璃映出你困倦的脸&#xff0c;耳机里的音乐循环到第 17 遍&#xff0c;早高峰的人群像沙丁鱼罐头般挤压着你。这是你每天雷打不动的三小时通勤路&#xff0c;从城市边缘到写字楼林立的 CBD&#xff0c;窗外的风景换了四季&#xff0c;而你始终困在摇晃的车厢里&#xff0…

Web Worker技术详解与应用场景

我们来详细探讨一下 Web Worker。它是现代 Web 开发中解决 JavaScript 单线程限制、提升应用性能和响应能力的关键技术。 核心问题&#xff1a;JavaScript 的单线程模型 浏览器 UI 线程&#xff08;主线程&#xff09;&#xff1a;JavaScript 在浏览器中默认运行在单个线程&a…

React Next快速搭建前后端全栈项目并部署至Vercel

很好&#xff0c;你是想搞清楚Next.js 的后端结构和传统 Node Express 的区别对比&#xff0c;我来整理一套结构化、精准、对面试有说服力的解答&#xff0c;并附示意结构图。 01Next vs Express 、## ⚡️1️⃣ Next.js 后端是怎么构建的 Next.js 在默认情况下本身就集成后…

【T宝客户项目解决过程】01-模型训练

1 项目需求描述 博主自己开了一家T宝店&#xff0c;有一个客户有这个需求&#xff1a;有一大堆图像&#xff0c;大概有10多万张图&#xff0c;都是比较小尺寸的图。各种类型都有&#xff0c;我们想要通过将不同类型发图像进行分开&#xff0c;如何实现呢&#xff1f; 2 思路 …

如何在中将网络改为桥接模式并配置固定IP地址

在使用服务器搭建虚拟机的过程中&#xff0c;我们发现有许多场景需要将虚拟机的网络配置为桥接模式&#xff0c;并为其设置固定的IP地址。为了帮助大家更高效地进行网络配置&#xff0c;提升虚拟机的连接稳定性和管理便捷性&#xff0c;我们总结了这篇指南&#xff0c;介绍如何…

强化学习 - 基于策略的Reinforce算法

&#x1f3af; REINFORCE 策略梯度算法推导&#xff08;完整&#xff09; 1. 目标函数定义 我们希望最大化策略的期望回报&#xff1a; J ( θ ) E τ ∼ π θ [ R ( τ ) ] J(\theta) \mathbb{E}_{\tau \sim \pi_\theta} \left[ R(\tau) \right] J(θ)Eτ∼πθ​​[R(τ…

Windows Sever Core安装及常用命令

一、Windows Sever Core 在安装 Windows Server 的过程中&#xff0c;可以选择“Server Core”&#xff08;核心安装&#xff09;这种没有图形用户界面&#xff08;GUI&#xff09;的安装方式。这种模式下&#xff0c;Windows Server 主要通过命令行或远程管理进行配置和维护&…

Java 单元测试实战:以“两数之和”为例,讲透测试思维

&#x1f31f;Java 单元测试实战&#xff1a;以“两数之和”为例&#xff0c;讲透测试思维 在 Java 开发中&#xff0c;单元测试不仅是验证功能正确的手段&#xff0c;更是衡量开发者是否具备“测试思维”的标志。今天我们通过一个最简单的功能——“两数之和”来系统讲解如何…