在MySQL的性能优化中,索引是最常用且有效的手段之一。但“索引不是万能药”——盲目添加索引可能导致写操作变慢、存储空间浪费,甚至引发索引失效问题。本文将结合原理与实战场景,帮你理清​​“何时该用索引”​​的核心判断逻辑。


一、先理解索引的本质:用空间换时间的“查询加速器”

MySQL的索引本质上是一种​​数据结构​​(最常用的是B+树),它通过预先排序字段值,将全表扫描的O(n)复杂度降低到O(log n)。但索引的维护需要成本:

  • ​写入时​​:每次INSERT/UPDATE/DELETE都需要更新索引树(尤其是主键索引,InnoDB的聚簇索引结构会直接关联数据页);
  • ​存储时​​:每个索引都会占用额外的磁盘空间(相当于复制一份字段数据并按规则排序);
  • ​查询时​​:复杂的联合索引或错误的索引顺序可能导致“索引失效”,反而需要回表扫描。

因此,​​索引的价值仅体现在“高频查询场景”​​——当某个字段的查询频率远高于写入频率时,添加索引才划算。


二、必须添加索引的4类典型场景

场景1:高频过滤条件(WHERE子句核心字段)

如果某条SQL语句每天执行10万次,而其中WHERE user_id = 123的条件占80%,那么user_id字段必须加索引。
​原理​​:没有索引时,MySQL需要扫描全表(假设表有1000万行,扫描需要约1秒);添加索引后,通过B+树快速定位到目标行(耗时约1ms)。

​示例​​:

-- 高频查询:按用户ID查询订单
SELECT * FROM orders WHERE user_id = 1001 AND status = 'paid';

此时,user_id是核心过滤条件,必须添加索引(单独索引或联合索引)。


场景2:多表关联的JOIN字段

当两张表通过某个字段关联(如orders.user_id = users.id),且关联操作频繁时,​​关联字段必须加索引​​。否则,MySQL可能需要对其中一张表做全表扫描,再逐行匹配另一张表的数据,时间复杂度会爆炸式增长。

​示例​​:

-- 关联查询:获取用户及其订单
SELECT u.name, o.amount FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.age > 18;

此时,users.id(主键,已有索引)和orders.user_id都需要索引。若orders.user_id无索引,MySQL需要遍历orders表所有行,逐行对比user_id是否匹配,效率极低。


场景3:排序或分组的字段(ORDER BY/GROUP BY)

如果SQL中包含ORDER BYGROUP BY,且排序/分组的字段无索引,MySQL需要对结果集进行全量排序(文件排序,Filesort),这在数据量大时(如10万行)会导致严重的性能问题。

​原理​​:索引本身是有序的,若排序字段有索引,MySQL可以直接通过索引顺序获取数据,避免额外的排序操作。

​示例​​:

-- 按下单时间倒序查询最近100条订单
SELECT * FROM orders 
WHERE user_id = 1001 
ORDER BY create_time DESC 
LIMIT 100;

此时,若create_time无索引,MySQL需要先过滤出user_id=1001的所有行(假设10000条),再对这10000行按create_time排序(耗时约100ms);添加索引(user_id, create_time)后,可直接通过索引定位到user_id=1001的有序数据,取最后100条即可(耗时约1ms)。


场景4:唯一性约束的字段(UNIQUE INDEX)

如果某个字段需要保证​​全局唯一​​(如用户的手机号、邮箱),必须添加唯一索引(UNIQUE INDEX)。唯一索引既能保证数据唯一性,又能加速查询(原理与普通索引类似,但额外校验唯一性)。

​反例​​:若不用唯一索引,需在应用层通过SELECT COUNT(*) FROM users WHERE phone='13800138000'校验唯一性,这会带来额外的查询开销,且存在并发冲突风险。


三、谨慎添加索引的3类场景

场景1:低区分度的字段(如性别、状态)

如果字段的取值范围很小(如gender只有男/女,status只有0/1/2),即使频繁查询,索引的效果也会很差。
​原因​​:B+树的叶子节点是按索引值排序的,低区分度字段的索引树高度低,但每个节点的子节点数量多,查询时可能需要扫描大量分支。例如,一个1000万行的表,gender字段的索引可能只能将查询优化到“扫描500万行”,而全表扫描可能更快(因为无需维护索引树)。

​验证方法​​:通过SHOW INDEX FROM table查看字段的Cardinality(基数,即不同值的数量)。若Cardinality远小于表总行数(如小于10%),说明区分度低,不建议单独加索引。


场景2:频繁更新的字段

如果某个字段被频繁修改(如update_time每次更新记录都会变化),为其添加索引会增加写操作的开销。
​原理​​:每次更新字段值时,MySQL需要同步更新索引树的结构(删除旧值,插入新值)。对于写密集型表(如日志表),过多索引会导致写性能下降。

​权衡建议​​:若更新频率远低于查询频率(如每天更新100次,查询10万次),仍可添加索引;反之则需谨慎。


场景3:大字段或不常用的查询条件

如果字段是大文本(如content)或大二进制(如image),即使偶尔查询,也不建议添加索引。因为B+树索引对大字段的支持效率很低(索引值过大,节点存储效率低,且无法有效缩小查询范围)。

​替代方案​​:对于大文本的模糊查询(如LIKE '%关键词%'),可使用全文索引(FULLTEXT INDEX);对于偶尔查询的大字段,可通过覆盖索引(见下文)或应用层缓存优化。


四、索引设计的进阶技巧:让索引“更高效”

技巧1:联合索引的最左匹配法则

联合索引(a, b, c)的查询条件需满足​​从左到右的顺序​​才能充分利用索引:

  • ✅ 有效:WHERE a=1WHERE a=1 AND b=2WHERE a=1 AND b=2 AND c=3
  • ❌ 无效:WHERE b=2(跳过了a)、WHERE a=1 AND c=3(跳过了b)。

​最佳实践​​:将高频查询的字段放在联合索引的最左边,且尽量覆盖查询所需的所有字段(避免回表)。


技巧2:覆盖索引(Covering Index)

如果查询所需的所有字段都包含在索引中,MySQL可以直接通过索引返回结果,无需回表查询数据页(称为“覆盖索引”)。
​示例​​:

-- 索引为 (user_id, create_time)
SELECT user_id, create_time FROM orders WHERE user_id = 1001;

此时,索引已包含查询所需的所有字段,无需访问数据行,性能大幅提升。


技巧3:避免冗余索引

冗余索引是指功能被其他索引完全覆盖的索引。例如:

  • 已有主键索引(id),再添加(id, name)是冗余的(主键索引已包含id);
  • 已有联合索引(a, b),再添加(a)是冗余的(前者已覆盖a的查询)。

​工具辅助​​:通过pt-index-usage(Percona Toolkit)或MySQL 8.0的sys.schema_unused_indexes视图,定期清理冗余索引。


五、总结:索引使用的黄金法则

索引的核心价值是​​加速高频查询​​,但需平衡写性能和存储成本。判断是否添加索引时,可参考以下步骤:

  1. ​分析查询模式​​:通过慢查询日志(slow_query_log)或pt-query-digest工具,找出高频执行的SQL;
  2. ​定位关键字段​​:提取SQL中的WHERE/JOIN/ORDER BY/GROUP BY字段;
  3. ​评估区分度​​:通过SHOW INDEX查看字段的Cardinality,排除低区分度字段;
  4. ​权衡读写比例​​:若字段的读频率远高于写频率(如100:1),则添加索引;
  5. ​设计最优索引​​:优先使用联合索引(覆盖高频条件),避免冗余,利用覆盖索引减少回表。

记住:​​没有绝对正确的索引策略,只有适合业务场景的索引设计​​。定期监控索引的使用情况(如EXPLAIN分析执行计划),及时调整,才能让索引真正为性能赋能。

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

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

相关文章

AI时代关键词SEO优化

内容概要 在人工智能(AI)驱动的时代浪潮下,搜索引擎优化(SEO)正迎来深刻变革,关键词策略已成为流量获取的核心战场。本文将系统剖析AI时代关键词优化的前沿方法,涵盖语义分析的精准研究、用户意…

GO 语言学习 之 代码风格

1. 命名规范 字母数字和下划线组成 以小写字母、大写字母或下划线开头 不允许包含标点符号、运算符、空白字符(空格、TAB、换行)等 采用驼峰命名法 (大驼峰、小驼峰) 见名知义:命名要有实际意义,易读性&am…

【软考高级系统架构论文】论云上自动化运维及其应用

论文真题 云上自动化运维是传统IT运维和 DevOps的延伸,通过云原生架构实现运维的再进化。云上自动化运维可以有效帮助企业降低IT运维成本,提升系统的灵活度,以及系统的交付速度,增强系统的可靠性,构建更加安全、可信、开放的业务平台。 请围绕“云上自动化运维及其应用”…

错误: 程序包androidx.fragment.app不存在 import android

错误: 程序包androidx.fragment.app不存在 import androidx.fragment.app.FragmentActivity; 这个是什么错?dependencies { //implementation fileTree(dir: libs, include: [*.jar]) implementation project(path: :libscan) //noinspection GradleCompatible implementation…

Java UDP Socket 实时在线刷卡扫码POS消费机门禁控制板服务端示例源码

本示例使用的设备&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bYG0BuO&ftt&id17021194999 一、获取本电脑所有网卡IP public static String getIP() {Enumeration<NetworkInterface> netInterfaces;ArrayList<String>…

MATLAB基础应用精讲-【数模应用】层次分析法(AHP)(附MATLAB和python代码实现)

目录 前言 算法原理 什么是层次分析法(AHP) 注意事项 基本原理 算法步骤 1建立层次结构 2构建判断矩阵 3计算权重向量 4一致性检验 SPSSAU AHP层次分析案例 1、背景 2、理论 3、操作 4、SPSSAU输出结果 5、文字分析 6、剖析 疑难解惑 数据如何录入? 如何…

Macintosh小电脑、小手机 | openKylin最新硬件创意形态首次亮相!

近期&#xff0c;OpenAtom openKylin&#xff08;简称 “openKylin”&#xff09;社区与嘉立创旗下的立创开发板团队展开深度技术合作&#xff0c;成功完成立创・泰山派1开发板与openKylin 2.0操作系统的兼容适配。5月24日&#xff0c;嘉立创“第三届开源硬件星火会”在深圳盛大…

基于Spring Boot的计算机考研交流系统的设计与实现

基于Spring Boot的计算机考研交流系统的设计与实现 随着计算机科学的发展&#xff0c;越来越多的学生选择考研来提高自己的专业水平。然而&#xff0c;考研的过程中&#xff0c;学生们面临着各种问题&#xff0c;如学习资料的获取、交流平台的缺乏等。为了更好地满足这些需求&…

技术逐梦之旅:从C语言到Vue的成长之路

董翔&#xff0c;一个对软件技术充满热忱的00后。从初次在屏幕上敲出"Hello World"的激动&#xff0c;到如今能够独立开发完整Web应用的从容&#xff0c;我的编程之路见证了技术的迭代与自我的蜕变。 作为软件专业的学生&#xff0c;我始终坚信"技术是解决问题…

Qt QMap数据清除测试(验证QMap内存正确释放方法)

环境 Qt C (msvc编译环境) 测试代码 //定义 动子信息 &#xff08;可放在.cpp文件 中&#xff09; struct MoverInfo{uint32_t ID;double PartPosition;uint16_t ModuleID;uint32_t PartID;uint32_t TrackID;uint32_t TrackID2; };//使用Windows任务管理器查看内存使用情况//…

【安全咨询】

安全咨询服务是一个专业领域&#xff0c;旨在帮助个人和组织识别、评估和管理各种安全风险&#xff0c;保护其人员、资产、信息和运营安全。 一、安全咨询 1.1 服务的核心目标 ​识别风险&#xff1a;​​ 发现潜在的、可能对组织或个人造成损害的威胁和漏洞。​评估威胁&am…

vue+elementUI实现固定table超过设定高度显示下拉条

解决方案&#xff1a; 在表格上添加了style"height: px;"和:max-height""&#xff0c;这两个设置共同作用使表格在内容超过 设定高度时显示滚动条配合css使用 高度值可根据实际需求调整 <el-table:data"biddData"style"width: 100%;…

UNet改进(5):线性注意力机制(Linear Attention)-原理详解与代码实现

引言 在计算机视觉领域&#xff0c;UNet架构因其在图像分割任务中的卓越表现而广受欢迎。近年来&#xff0c;注意力机制的引入进一步提升了UNet的性能。本文将深入分析一个结合了线性注意力机制的UNet实现&#xff0c;探讨其设计原理、代码实现以及在医学图像分割等任务中的应…

Unity技能编辑器深度构建指南:打造专业级战斗系统

本文为技术团队提供完整的技能编辑器开发指南&#xff0c;涵盖核心架构设计、资源管线搭建和协作工作流实现&#xff0c;帮助您构建专业级的战斗技能系统。 一、核心架构设计 1. 基础框架搭建 专用场景模板&#xff1a; 创建SkillEditorTemplate.unity场景 核心节点&#xff…

《游戏工业级CI/CD实战:Jenkins+Node.js自动化构建与本地网盘部署方案》

核心架构图 一、游戏开发CI/CD全流程设计 工作流时序图 二、Jenkins分布式构建配置 1. 节点管理&#xff08;支持Win/Linux/macOS&#xff09; // Jenkinsfile 分布式配置示例 pipeline {agent {label game-builder // 匹配带标签的构建节点}triggers {pollSCM(H/5 * * * *)…

Python内存使用分析工具深度解析与实践指南(上篇)

文章目录 引言1. sys.getsizeof()功能程序示例适用场景 2. pandas.Series.memory_usage()功能程序示例适用场景 3. pandas.Series.memory_usage(deepTrue)功能程序示例适用场景注意事项 4. pympler.asizeof()功能安装程序示例适用场景 5. tracemalloc&#xff08;标准库&#x…

Python 使用 Requests 模块进行爬虫

目录 一、请求数据二、获取并解析数据四、保存数据1. 保存为 CSV 文件2. 保存为 Excel 文件打开网页图片并将其插入到 Excel 文件中 五、加密参数逆向分析1. 定位加密位置2. 断点调试分析3. 复制相关 js 加密代码&#xff0c;在本地进行调试&#xff08;难&#xff09;4. 获取 …

MySQL行转列、列转行

要达到的效果&#xff1a; MySQL不支持动态行转列 原始数据&#xff1a; 以行的方式存储 CREATE TABLE product_sales (id INT AUTO_INCREMENT PRIMARY KEY,product_name VARCHAR(50) NOT NULL,category VARCHAR(50) NOT NULL,sales_volume INT NOT NULL,sales_date DATE N…

云创智称YunCharge充电桩互联互通平台使用说明讲解

云创智称YunCharge充电桩互联互通平台使用说明讲解 一、云创智称YunCharge互联互通平台简介 云创智称YunCharge&#xff08;YunCharge&#xff09;互联互通平台&#xff0c;旨在整合全国充电桩资源&#xff0c;实现多运营商、多平台、多用户的统一接入和管理&#xff0c;打造开…

HTML+JS实现类型excel的纯静态页面表格,同时单元格内容可编辑

<!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>在线表格</title><style>table {border…