Mysql之索引优化

指定索引

当一个字段上既有单列索引,又有复合索引时,我们可以通过以下的SQL提示来要求该SQL语句执行时采用哪个索引:

  • use index(索引名称):建议使用该索引,只是建议,底层mysql会根据实际效率来考虑是否使用你推荐的索引。

  • ignore index(索引名称):忽略该索引

  • force index(索引名称):强行使用该索引

应用场景

  • 当数据库执行计划没有自动选择最优的索引时,开发者可以手动指定使用特定的索引。尤其是在有多个索引的情况下,MySQL 可能选择了一个并不理想的索引,而通过指定索引可以确保查询执行的效率。
/*指定索引use index(索引的名称): 建议使用该索引ignore index(索引名称) :某个索引force index(索引名称) :强行使用某个索引*/
show index from t_customer;
create index idx_t_customer_name on t_customer(name);
explain select *from t_customer where name= 'zhangsan' ; #优先使用复合索引
# 如何建议使用单列索引idx_name:
explain select *from t_customer use index(idx_t_customer_name) where name= 'zhangsan' ; #建议使用单列索引#如何忽略使用复合索引 idx_name_age_gender:
explain select * from t_customer ignore index(idx_name_age_gender) where name='zhangsan';#如何强行使用单列索引idx_name:
explain select * from t_customer force index(idx_t_customer_name) where name='zhangsan';

覆盖索引

覆盖索引强调的是:在select后面写字段的时候,这些字段尽可能是索引所覆盖的字段,这样可以避免回表查询。尽可能避免使用 select *,因为select * 很容易导致回表查询。(本质就是:能在索引上检索的,就不要再次回表查询了。)

覆盖索引是指在一次查询中,所有需要查询的列都能从索引中获取,不需要再访问表中的实际数据行。也就是说,数据库只需要从索引中读取数据即可返回结果,不再需要回表(访问表中的实际数据),从而大大提高了查询效率。

应用场景

  • 查询所需的列全部包含在索引中,不需要访问数据表的记录,这种查询能够通过索引直接返回结果,从而大幅提升性能。
/*覆盖索引:覆盖索引的核心概念就是通过查询所需的所有列都位于索引中,避免回表操作,从而提高查询效率。*/CREATE INDEX idx_emp_name_sal ON t_emp(name, sal);
/*MySQL 可以直接从 idx_emp_name_sal 这个索引中返回结果,而不需要访问表中的数据行,因为 name 和 sal 都包含在索引中。这就是覆盖索引。*/show index from t_emp;
EXPLAIN SELECT name, sal FROM t_emp WHERE name = '张三'; # 使用覆盖索引
EXPLAIN SELECT name, sal, age FROM t_emp WHERE name = '张三'; # 不使用索引:
/*
此时,MySQL 会在索引中找到 name 和 sal,然后还需要访问数据表获取 age 列的值,这被称为 回表 操作*/
DROP INDEX idx_emp_name_sal ON t_emp;

 4d8724d259e349aabeaa2471cbe3b0aa.png

extra为null表示回表了 !!!

面试题:

t_user表字段如下:id,name,password,realname,birth,email。表中数据量500万条,请针对以下SQL语句给出优化方案:

select id,name,realname from t_user where name='鲁智深';

如果只给name添加索引,底层会进行大量的回表查询,效率较低,建议给name和realname两个字段添加联合索引,这样大大减少回表操作,提高查询效率。

前缀索引

 前缀索引(Prefix Index)是指对字符型列的前部分字符进行索引,而不是对整列创建索引。这种索引可以减少索引的大小,节省空间,同时还能提高查询的效率,特别是在需要对长文本或字符串列进行索引时。前缀索引广泛应用于需要索引长字符串列的场景,例如 VARCHARTEXT 类型的列。

使用前缀索引的场景

前缀索引适用于以下情况:

  • 列的数据较长,并且前几个字符就具有较强的区分度。
  • 不需要精确匹配整个字段,而只关心字段的前部分字符的匹配情况。

 前缀索引的语法

CREATE INDEX 索引名 ON 表名(列名(前缀长度));

示例

假设有一张 users 表,包含用户的电子邮件地址(email 列),由于电子邮件可能非常长,我们可以通过前 10 个字符创建前缀索引:

CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(255),email VARCHAR(255)
);-- 创建前缀索引,只对 email 列的前 10 个字符建立索引
CREATE INDEX idx_email ON users(email(10));

此时,MySQL 只对 email 列的前 10 个字符进行索引,而不是对整个 email 列进行索引。当我们执行以下查询时:

SELECT * FROM users WHERE email LIKE 'abc@example%';

MySQL 会利用前 10 个字符的前缀索引来优9查询。这个查询中的 email LIKE 'abc@example%' 会匹配 email 列前 10 个字符中的内容。

如何选择合适的前缀长度? 

使用前缀索引时,需要通过以下公式来确定使用前几个字符作为索引:

select count(distinct substring(ename,1,前几个字符)) / count(*) from emp4;

以上查询结果越接近1,表示索引的效果越好。(原理:做索引值的话,索引值越具有唯一性效率越高)

/*前缀索引
截取前几个字符作为前缀索引呢?使用以下公式
select count(distinct substring(ename,1,前几个字符))/count(*)from emp
这个查询结果越接近1,越具有唯一性*/
select count(distinct substring(name,1,2))/count(*)from t_emp

总结

  • 指定索引 适合开发者手动介入优化查询。
  • 覆盖索引 能够在频繁查询特定列时,避免回表,提升查询效率,是性能优化的重要手段。
  • 前缀索引 适用于长文本字段,能在保证索引效率的同时,减少存储开销。

 

单列索引和复合索引怎么选择:

当查询语句的条件中有多个条件,建议将这几个列创建为复合索引,因为创建单列索引很容易回表查询。

1. 单列索引(Single-column Index)

单列索引是对表中的单个列创建的索引。每个索引只针对一个列进行加速。

使用单列索引的场景:

  • 查询条件只涉及单列

    • 当查询条件只包含一个列时,单列索引是最有效的选择。此时创建复合索引没有意义。
  • 多个单列索引用于不同的查询条件
    • 如果表中的列经常被单独查询,不会经常联合查询,那么为每个列分别创建单列索引更为合适。
  • 频繁更新的表
    • 在一个数据频繁更新的表中,单列索引相对复合索引更新代价较低。如果查询性能可以通过单列索引满足,那么单列索引通常会对性能更加友好。

2. 复合索引(Composite Index)

复合索引(也称为联合索引)是对多个列组合创建的索引。通过复合索引,查询引擎可以在多个列上同时加速查询。

使用复合索引的场景:

  • 查询条件涉及多个列

    • 如果查询条件经常包含多个列,并且这些列频繁联合出现,那么复合索引是最佳选择。复合索引能够同时加速多个列的查询。
  • 遵循最左前缀原则
    • 在复合索引中,查询条件需要从索引的最左边开始使用。如果查询只包含最左边的列,复合索引仍然有效,但如果跳过了左边的列,索引将失效。 主字段并且具有很强唯一性的字段建议排在第一位。
  • 范围查询需要放在复合索引的最后
    • 如果查询条件中包含范围查询(如 >, <, BETWEEN),通常将范围列放在复合索引的最后,因为范围查询会限制复合索引的使用范围。否则会导致索引失效。
    • 例如,如果你有一个查询同时涉及 nameage,并且 age 是一个范围查询:
      SELECT * FROM t_emp WHERE name = '张三' AND age > 20;
      

索引创建原则

1. 表数据量庞大,通常超过百万条数据

  • 解释:当表的数据量非常庞大(如超过百万条记录)时,查询性能会显著下降。没有索引的情况下,数据库必须进行全表扫描,这会导致查询速度非常慢。为了解决这一问题,创建适当的索引非常关键。索引可以极大地减少扫描的行数,从而提高查询性能。

2. 经常出现在 WHERE、ORDER BY、GROUP BY 后面的字段建议添加索引

  • 解释WHEREORDER BYGROUP BY 通常是 SQL 查询中最耗时的部分,因为它们会对表中的大量数据进行筛选、排序或分组。为这些字段添加索引可以加速数据的查找、排序和分组操作。
  • 建议:如果某个字段经常出现在 WHEREORDER BYGROUP BY 中,应该为该字段添加索引,以提高查询性能。

3. 创建索引的字段尽量具有很强的唯一性

  • 解释:索引的效率取决于字段的选择性(区分度)。如果一个字段的值是高度唯一的(如主键或身份证号),索引能够快速缩小查询范围,查找性能更高。而对低选择性的字段(如性别,只有 "男" 和 "女" 两个值)创建索引,作用不大,因为即使使用索引,数据库仍然需要扫描大量数据。
  • 建议:优先为具有高唯一性、选择性强的字段创建索引,例如用户 ID、订单号等。

4. 如果字段存储文本,内容较大,一定要创建前缀索引

  • 解释:对于长文本字段(如 VARCHARTEXT),如果直接对整个字段创建索引,会消耗大量的存储空间并降低索引的效率。因此,可以创建前缀索引,即只索引文本字段的前 N 个字符。这样既节省空间,又能够保持较高的索引效率。
  • 建议:对于存储较长文本的字段(如邮箱、URL、文章标题等),建议使用前缀索引。前缀长度应根据数据分布和区分度合理选择。

5. 尽量使用复合索引,使用单列索引容易回表查询

  • 解释复合索引是对多个列组合起来创建的索引,可以在涉及多个列的查询中显著提高性能。当查询涉及多个条件时,使用复合索引可以避免回表操作(从索引查找到数据后,还需要访问数据表本身)。单列索引只能加速单一条件的查询,对于多条件查询,数据库可能需要多次访问数据表,这会降低查询性能。
  • 建议:对于多列查询,优先考虑复合索引,以提高查询效率和减少回表操作。

6. 如果一个字段中的数据不会为 NULL,建议建表时添加 NOT NULL 约束,这样优化器就知道使用哪个索引列更加有效

  • 解释:如果某个字段的数据永远不会为 NULL,在表设计时应该明确设置 NOT NULL 约束。这不仅能够保持数据的完整性,还可以帮助查询优化器更好地使用索引。因为当字段允许 NULL 值时,索引结构中可能需要额外的逻辑来处理 NULL 值,影响性能。
  • 例如
    CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(255),email VARCHAR(255) NOT NULL,phone VARCHAR(15) NOT NULL
    );
    
    • 此时,数据库优化器不再需要考虑 NULL 值的情况,因为这些列不能存储 NULL 值。因此,在使用索引时,优化器会更高效地利用这些列的索引。 

7. 不要创建太多索引,当对数据进行增删改的时候,索引需要重新排序

  • 解释:虽然索引可以提升查询性能,但它们会增加增删改操作的开销。当对表进行增删改时,索引必须更新,这会导致性能下降。特别是如果表上有大量的索引,每次修改数据时都需要更新这些索引,可能会导致性能问题。

8. 如果很少的查询,经常的增删改不建议加索引

  • 解释:如果表的数据主要是用来频繁增删改,而查询操作很少,那么创建索引的收益可能不大,甚至会影响性能。因为索引的主要作用是加速查询,而在增删改操作中,每次修改数据都需要更新索引,这会增加额外的开销。
  • 建议:在以频繁写操作为主的表中(如日志表、事务表),如果查询操作很少,不建议添加索引。除非某些查询需要优化,否则应优先考虑写入性能。

 

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

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

相关文章

使用豆包MarsCode 实现高可用扫描工具

以下是「 豆包MarsCode 体验官」优秀文章&#xff0c;作者郝同学测开笔记。 前言&#xfeff; 最近接触K8s&#xff0c;了解到K8s提供了非常方便的实现高可用的能力&#xff0c;再加上掘金推出「豆包MarsCode初体验」征文活动&#xff0c;所以打算使用豆包 MarsCode IDE来实现…

LeetCode(Python)-贪心算法

文章目录 买卖股票的最佳时机问题穷举解法贪心解法 物流站的选址&#xff08;一&#xff09;穷举算法贪心算法 物流站的选址&#xff08;二&#xff09;回合制游戏快速包装 买卖股票的最佳时机问题 给定一个数组&#xff0c;它的第 i 个元素是一支给定股票第 i 天的价格。如果你…

Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动

文章目录 1、 buildroot源码获取2、buildroot配置3、buildroot编译4、挂载根文件系统 在上一篇 Qemu开发ARM篇-4、kernel交叉编译运行演示中&#xff0c;我们编译了kernel&#xff0c;并在qemu上进行了运行&#xff0c;但到最后&#xff0c;在挂载根文件系统时候&#xff0c;挂…

python之装饰器、迭代器、生成器

装饰器 什么是装饰器&#xff1f; 用来装饰其他函数&#xff0c;即为其他函数添加特定功能的函数。 装饰器的两个基本原则&#xff1a; 装饰器不能修改被装饰函数的源码 装饰器不能修改被装饰函数的调用方式 什么是可迭代对象&#xff1f; 在python的任意对象中&#xff…

C# DotNetty客户端

1. 引入DotNetty包 我用的开发工具是VS2022&#xff0c;不同工具引入可能会有差异 工具——>NuGet包管理器——>管理解决方案的NuGet程序包 搜索DotNetty 2.新建EchoClientHandler.cs类 用于接收服务器返回数据 public class EchoClientHandler : SimpleChannelIn…

【AD那些事 10 】焊盘如何修改为自己想要的形状!!!!! 焊盘设计规则如何更改??????

左侧为修改前焊盘原图 右侧为修改后焊盘图 ——————————————————————————————————————————— 目录 修改焊盘内侧的大小 修改焊盘外侧的大小 更改焊盘设计规则 ——————————————————————————…

Pencils Protocol 即将登录各大 CEX,依旧看好 $DAPP

近期&#xff0c;Scroll生态头部DeFi协议Pencils Protocol迎来了系列重磅市场进展。自9月18日开始&#xff0c;$DAPP通证分别在Tonkensoft、Bounce以及Coresky等平台陆续开启了IDO&#xff0c;并且在短期内售罄。同时在通证售卖完成后&#xff0c;DAPP 通证又在9月27日陆续登录…

RUST语言的初印象-从一个模拟登陆谈起-slint+reqwest+aes

本文就一个做了三四天的小程序讲第一次学用RUST的感受&#xff0c;内附代码。 了角语言 从一些渠道听说了R&#xff0c;这个字母挺魔性&#xff0c;那个文章说C和R的团体已经上升到了宗教崇拜的高度&#xff0c;然后&#xff0c;我觉得必 有过人之处&#xff0c;大约10年没碰…

通用运维基础

一 网络基础 知识点:网络交换1.1 VLAN1.2VxLAN2.网络路由3.网络常用命令目标:1. 了解网络的基本概念 2. 掌握常用的网络排错命令 1、网络交换 1.1 网络虚拟化 什么是网络虚拟化 网络虚拟化是指虚拟网络节点之间的连接并不使用物理线缆连接,而是依靠特定的虚拟化链路相连…

TCP的第三次握手没有回复,会出现哪些问题现象

从三次握手的一开始来讲&#xff0c;刚开始客户端和服务器都处于close状态 这里不能是2次握手的原因就在于&#xff0c;服务器端即女孩子&#xff0c;无法确认客户端即男孩子&#xff0c;是否已经收到了&#xff0c;我也愿意建立连接即我也爱你&#xff0c;这一条最终确认的信息…

软件对比 | 历史气象数据哪里找?

中国气象网和羲和能源气象大数据平台两个平台当然没有“绝对”哪个好的说法&#xff0c;各自特点都在下图进行总结&#xff0c;到底用哪个还是根据自己需求自己抉择。 希望可以帮助到大家~

DK5V100R15ST1直插TO220F,12V 4A两个引脚同步整流芯片

高性能两个引脚同步整流芯片 DK5V100R15ST1产品 概述DK5V100R15ST1是一款简单高效率的同步整流芯片&#xff0c;只有A&#xff0c;K两个引脚&#xff0c;分别对应肖特基二极管PN管脚。芯片内部集成了100V功率NMOS管&#xff0c;可以大幅降低二极管导通损耗&#xff0c;提高整机…

.NET 6 中,使用 ActionFilterAttribute 实现 AOP(面向切面编程)

AOP概述&#xff1a;AOP&#xff08;面向切面编程&#xff09;是一种编程规范的风格&#xff0c;通过横切的思想&#xff0c;将系统功能和业务功能分离开&#xff0c;以提高代码的可维护性和清晰度。 系统功能模块&#xff1a; 1、缓存模块&#xff1a; 作用&#xff1a;提高…

拥塞控制算法的 rtt 公平性

我强调过&#xff0c;拥塞控制的核心在公平可用性&#xff0c;公平性由 buffer 动力学保证&#xff0c;而 buffer 动力学有两种表现形式&#xff1a; buffer 占比决定带宽占比&#xff0c;以 aimd 为例&#xff1b;带宽越小&#xff0c;buffer 挤兑加速比越大&#xff0c;以 b…

如何选择高品质SD卡

如何选择高品质SD卡 SD卡&#xff08;Secure Digital Memory Card&#xff09;是一种广泛使用的存储器件&#xff0c;因其快速的数据传输速度、可热插拔的特性以及较大的存储容量&#xff0c;广泛应用于各种场景&#xff0c;例如在便携式设备如智能手机、平板电脑、运动相机等…

作者分享|eDNA研究梯级水坝对浮游植物和浮游动物群落变化的影响

研究梯级水坝的影响对于了解和减轻其对环境的负面影响至关重要&#xff0c;浮游植物和浮游动物群落都对梯级水坝引起的变化尤为敏感。凌恩客户重庆师范大学生命科学学院水生态健康与环境安全实验室沈彦君课题组&#xff0c;通过eDNA宏条码技术对梯级水坝河道的浮游植物和浮游动…

uniapp实现在表单中展示多个选项,并且用户可以选择其中的一个或多个选项

前言 uni-data-checkbox是uni-app的一个组件,用于在表单中展示多个选项,并且用户可以选择其中的一个或多个选项。该组件可以通过设置不同的参数来控制选项的样式、布局和行为。 提示:以下是本篇文章正文内容,下面案例可供参考 uni-data-checkbox组件具有以下特点:: 1、跨…

威雅学校:2024线上3D艺术展精彩纷呈,让我们为孩子们的想象力喝彩!

Wycombe Abbey International Imaginarium 2024 IMAGINARIUM&#xff0c;是一个源于拉丁语的词汇&#xff0c;意为“想象的地方”或“幻想的世界”。在艺术和文化的领域中&#xff0c;它代表着展示创意、想象力和幻想的空间。 2024年度的威雅大家庭线上3D艺术展&#xff0c;正以…

ChatGLM-6B 部署与使用——打造你的专属GLM

ChatGLM-6B 部署与使用指南 ChatGLM-6B 是清华大学与智谱 AI 开源的一款对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;参数达到 62 亿&#xff0c;因其卓越的语言理解与生成能力&#xff0c;受到广泛关注。 一、在 DAMODEL 上部署 ChatGLM-6B…

Vue使用axios二次封装、解决跨域问题

1、什么是 axios 在实际开发过程中&#xff0c;浏览器通常需要和服务器端进行数据交互。而 Vue.js 并未提供与服务器端通信的接口。从 Vue.js 2.0 版本之后&#xff0c;官方推荐使用 axios 来实现 Ajax 请求。axios 是一个基于 promise 的 HTTP 客户端。 关于 promise 的详细介…