MySQL索引的使用,大大提升你代码的效率

简介: MySQL索引的使用,大大提升你代码的效率

🚀索引使用

验证索引效率

案例:这是一张有1000w的记录的表 (此案例来自黑马,我觉得黑马的案例很详细)

这张表中id为主键有主键索引而其他字段是没有建立索引的先来查询其中的一条记录看里面的字段情况,执行如下SQL

select * from tb_sku where id = 1\G;

可以看到即使有1000w的数据,根据id进行数据查询,性能依然很快0.00sec为主键id是有索引的下来,我们再来根据sn字段进行查询执行如下SQL

SELECT * FROM  tb_sku  WHERE sn = '100000003145001 ';

我们可以看到根据sn字段进行查询查询返回了一条数据结果耗时  20.78sec就是因为sn没有索 引,而造成查询效率很低。

具体原因:首先,它没有使用索引。在没有索引的情况下,MySQL将扫描整个表来查找符合条件的行。这可能会导致性能下降,尤其是当表中的数据量很大时。


我们可以针对于sn字段建立一个索引建立了索引之后我们再次根据sn进行查询再来看一 下查询耗时情况。

create  index  idx_sku_sn  on  tb_sku (sn) ;


然后再次执行相同的SQL语句再次查看SQL的耗时

SELECT * FROM  tb_sku  WHERE sn = '100000003145001 ';


由此可以看出,建立了索引之后,查询的性能极大提升,因为MySQL可以使用索引来快速定位匹配的行,并进一步筛选符合额外条件的行。这将大大提高查询的效率,因为MySQL只需要访问少量的行来获取结果。

需要注意的是,索引并非在所有情况下都能提高查询性能。索引的选择和使用需要根据具体的数据和查询需求进行评估。过多或不必要的索引可能会增加写操作的开销,而且索引也需要占用额外的存储空间。因此,在设计和使用索引时,需要综合考虑查询频率、数据更新频率和存储成本等因素。

🚀最左前缀法则

show index from tb_user ; --显示tb_user表的索引

如果索引了多列(联合索引要遵守最左前缀法则最左前缀法则指的是查询从索引的最左列开始 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(即面的字段索引失效)

这些标记出来的是单链索引,主键id,phone,name,email


在  tb_user 表中,有一个联合索引,这个联合索引涉及到三个字段,顺序分别为:  profession, age,  status。

对于最左前缀法则指的是,查询时,最左变的列,也就是profession必须存在,否则索引全部失效。 而且中间不能跳过某一列,否则该列后面的字段索引将失效.

演示:

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= '5 ';

 explain select * from tb_user where profession = '化工 ' and age = 38;

explain select * from tb_user where profession = '化工 ';    

以上的这三组测试中,我们发现只要联合索引最左边的字段  profession存在,索引就会生效,只不 过索引的长度不同。    而且由以上三组测试,我们也可以推测出profession字段索引长度为47、  age 字段索引长度为2、  status字段索引长度为5。

explain select * from tb_user where age = 38 and status = '5 ';

explain select * from tb_user where status = '5 ';

而通过上面的这两组测试,我们也可以看到索引并未生效,原因是因为不满足最左前缀法则,联合索引 最左边的列profession不存在。

explain select * from tb_user where profession = '化工 ' and status = '5 ';

上述的SQL查询时,存在profession字段,最左边的列是存在的,索引满足最左前缀法则的基本条   件。但是查询时,跳过了age这个列,所以后面的列索引是不会使用的,也就是索引部分生效,所以索 引的长度就是47。

思考题:

当执行SQL语句:

explain select * from tb_user where age = 38 and   status = '0' and profession = '化工 ';

是否满足最左前缀法则,走不走上述的联合索引,索引长度是多少?(也就是顺序换了之后还成不成立了)

可以看到,是完全满足最左前缀法则的,索引长度54联合索引是生效的

注意  :最左前缀法则中指的最左边的列,是指在查询时,联合索引的最左边的字段(即是

第一个字段)必须存在,与我们编写SQL时,条件编写的先后顺序无关。

🚀范围查询

联合索引中,出现范围查询 (>,<)范围查询右侧的列索引失效

explain select * from tb_user where profession = '化工 ' and age > 30 and status
= '5 ';

当范围查询使用>  <走联合索引了,但是索引的长度为49就说明范围查询右边的status段是没有走索引的。

explain select * from tb_user where profession = '化工 ' and age >= 30 and
status = '5 ';

当范围查询使用>=  <= 时,走联合索引但是索引的长度为54就说明所有的字段都是走索引的。所以,在条件允许的情况下,尽可能的使用类似于  >=  <=这类的范围查询而避免使用  >  <

🚀索引失效情况

索引列运算

不要在索引列上进行运算操作,索引将失效

tb_user表中除了前面介绍的联合索引之外还有一个索引phone字段的单列索引

当根据phone字段进行等值匹配查询时,索引生效

explain select * from tb_user where phone = '17799990015 ';


当根据phone段进行函数运算操作之后索引失效

explain  select  *  from  tb_user  where  substring (phone,10,2) = '15 ';


字符串不加引号

字符串类型字段使用时,不加引号,索引将失效。

示例:加单引号与不加单引号的区别

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= '5 ';

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= 5 ;

explain select * from tb_user where phone = '17799990015 ';
explain select * from tb_user where phone = 17799990015;

经过上面两组示例我们会明显的发现如果字符串不加单引号对于查询结果没什么影响但是数 据库存在隐式类型转换,索引将失效。

隐式类型转换是什么?

隐式类型转换是指在比较操作中,MySQL会自动将一个数据类型转换成另一个数据类型,以便进行比较。这种转换是在不明确指定的情况下自动发生的,用户不需要显式地进行类型转换操作。


隐式类型转换的影响

隐式类型转换可能导致索引失效,从而影响查询性能。当查询条件中的数据类型与列的数据类型不匹配时,MySQL会进行隐式类型转换,将查询条件的数据类型转换成列的数据类型进行比较。如果数据类型不匹配,MySQL可能无法充分利用索引,而是需要进行全表扫描来查找符合条件的行,导致性能下降。

举例说明

无隐式类型转换的情况

假设我们有一个名为users的表,包含以下列:

+----+---------+--------+
| id | name    | age    |
+----+---------+--------+
| 1  | Alice   | 25     |
| 2  | Bob     | 30     |
| 3  | Charlie | 35     |
| 4  | David   | 40     |
| 5  | Eve     | 45     |
+----+---------+--------+

如果我们对name列创建了索引,并执行以下查询:

SELECT * FROM users WHERE name = 'Alice';

由于查询条件中的数据类型与列的数据类型完全匹配,MySQL可以充分利用索引来快速定位和访问符合条件的数据,从而提高查询效率。

存在隐式类型转换的情况

现在假设我们对age列创建了索引,并执行以下查询:

SELECT * FROM users WHERE age = 30;

在这个例子中,由于查询条件中的数据类型与列的数据类型完全匹配,MySQL可以充分利用索引。

但是,如果我们执行以下查询:

SELECT * FROM users WHERE age = '30';

在这个例子中,查询条件中的数据类型是字符串,而列的数据类型是整数。MySQL将会进行隐式类型转换,将字符串转换成整数进行比较。这可能导致索引失效,从而影响查询性能。

总结

隐式类型转换可能导致索引失效,影响查询性能。为了避免这种情况,我们应该尽量确保查询条件中的数据类型与列的数据类型完全匹配,以充分利用索引提高查询效率。

🚀模糊查询

如果仅仅是尾部模糊匹配索引不会失效如果是头部模糊匹配索引失效

接下来我们来看一下这三条SQL语句的执行效果查看一下其执行计划

由于下面查询语句中,都是根据profession字段查询,符合最左前缀法则联合索引是可以生效的 我们主要看一下,模糊查询时,%加在关键字之前,和加在关键字之后的影响。

explain  select  *  from  tb_user  where  profession like '金属% '; 
explain  select  *  from  tb_user  where  profession like '%材料  ';
explain  select  *  from  tb_user  where  profession like '%材% ';


经过上述的测试,我们发现,在like模糊查询中,在关键字后面加%,索引可以生效。而如果在关键字前面加了%,索引将会失效。

🚀or连接条件

or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索那么涉及的索引都不会被用到。

explain select * from tb_user where id = 6 or age = 33;
explain select * from tb_user where phone = '15377777775 ' or age = 27;

第二个指令输出的结果很明显,只有phone有索引,后面的age没有索引,所以涉及的索引都不会用到,age没有索引所以即使id  phone有索引索引也会失效所以需要针对于age也要建立索引

然后,我们可以对age字段建立索引

create index idx_user_age on tb_user (age);


建立了索引之后我们再次执行上述的SQL语句看看前后执行计划的变化

最终我们发现or连接的条件左右两侧字段都有索引时索引才会生效

🚀数据分布影响

如果MySQL评估使用索引比全表更慢则不使用索引

select * from tb_user where phone >= '17799990005 ';
select * from tb_user where phone >= '17799990015 ';


经过测试我们发现,相同的SQL语句,只是传入的字段值不同,最终的执行计划也完全不一样,这是为什么呢?

就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃索引,走全表扫描。因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。

我们再来看看  is null 与  is not null 操作是否走索引。

执行如下两条语句  

explain select * from tb_user where profession is null;
explain select * from tb_user where profession is not null;

接下来我们做一个操作将profession字段值全部更新为null

update tb_user set profession = null ;

然后,再次执行上述的两SQL查看SQL语句的执行计划

最终我们看到,一模一样的SQL语句,先后执行了两次,结果查询计划是不一样的,为什么会出现这种现象,这是和数据库的数据分布有关系,查询时MySQL会评估,走索引快,还是全表扫描快,如果全表 扫描更快,则放弃索引走全表扫描. 因此, is null 、is not null是否走索引,得具体情况具体分析,并不是固定的

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
5月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
200 4
|
7月前
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
7月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
8月前
|
消息中间件 缓存 弹性计算
纯PHP+MySQL手搓高性能论坛系统!代码精简,拒绝臃肿
本内容分享了一套经实战验证的社交系统架构设计,支撑从1到100万用户的发展,并历经6次流量洪峰考验。架构涵盖客户端层(App、小程序、公众号)、接入层(API网关、负载均衡、CDN)、业务服务层(用户、内容、关系、消息等服务)、数据层(MySQL、Redis、MongoDB等)及运维监控层(日志、监控、告警)。核心设计包括数据库分库分表、多级缓存体系、消息队列削峰填谷、CQRS模式与热点数据动态缓存。同时提供应对流量洪峰的弹性伸缩方案及降级熔断机制,并通过Prometheus实现全链路监控。开源建议结构清晰,适合大型社交平台构建与优化。
331 11
|
9月前
|
关系型数据库 MySQL 数据库
Mysql的索引
MYSQL索引主要有 : 单列索引 , 组合索引和空间索引 , 用的比较多的就是单列索引和组合索引 , 空间索引我这边没有用到过 单列索引 : 在MYSQL数据库表的某一列上面创建的索引叫单列索引 , 单列索引又分为 ● 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。 ● 唯一索引:索引列中的值必须是唯一的,但是允许为空值 ● 主键索引:是一种特殊的唯一索引,不允许有空值 ● 全文索引: 只有在MyISAM引擎、InnoDB(5.6以后)上才能使⽤用,而且只能在CHAR,VARCHAR,TEXT类型字段上使⽤用全⽂文索引。
|
5月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
146 2
|
6月前
|
存储 关系型数据库 MySQL
MySQL覆盖索引解释
总之,覆盖索引就像是图书馆中那些使得搜索变得极为迅速和简单的工具,一旦正确使用,就会让你的数据库查询飞快而轻便。让数据检索就像是读者在图书目录中以最快速度找到所需信息一样简便。这样的效率和速度,让覆盖索引成为数据库优化师傅们手中的尚方宝剑,既能够提升性能,又能够保持系统的整洁高效。
174 9
|
7月前
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
202 12
|
8月前
|
SQL 存储 关系型数据库
MySQL选错索引了怎么办?
本文探讨了MySQL中因索引选择不当导致查询性能下降的问题。通过创建包含10万行数据的表并插入数据,分析了一条简单SQL语句在不同场景下的执行情况。实验表明,当数据频繁更新时,MySQL可能因统计信息不准确而选错索引,导致全表扫描。文章深入解析了优化器判断扫描行数的机制,指出基数统计误差是主要原因,并提供了通过`analyze table`重新统计索引信息的解决方法。
237 3

推荐镜像

更多