MySQL索引优化一

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL索引优化一

前言

索引优化这四个字说实话我认为其实挺难理解的。看到这四个字我脑门上是:????

索引还要优化吗?调优SQL一般来说不就是看它有没有走索引,没走索引给它加上索引就好了吗?

嗯,所以你是怎么给它加索引的?

看SQL应该怎么走索引撒!

那SQL是怎么走索引的呢?又是怎么判断这条SQL会不会走索引呢?

我:…, 咱今天就来分析分析!

要是你还不了解MySQL底层的数据结构,建议你先看看MySQL数据结构

最左前缀法则

我们一般要优化的都是复杂SQL,而复杂SQL一般走的都是联合索引,说到联合索引的匹配规则,就逃不开这个:最左前缀法则

什么是最左前缀法则?

最左前缀法则即为:索引的匹配从最左边的字段开始,匹配成功才能往右继续匹配下一个字段。

不理解?没关系,我们先来看看这个联合索引:name_age_position

image-20230120150557493

联合索引是以三个字段name,age,position组成,并且创建该索引时字段顺序为name、age、positon。

那么该索引就会以这样的方式排序(索引就是排好序的高效的数据结构)

  • name字段从小到大排序
  • name字段的值相同时,age字段从小到大排序
  • age字段的值相同时,postion字段从小到大排序

如上图所示,从zhangsan18到zhangsan100是顺序的,而name都为zhangsan18的三个结点中,age又是从小到大排序,age相同时position也是从小到大排序。

请你一定要把这个数据结构牢记于心,忘了就看看

现在通过这个联合索引再来解析一下最左前缀法则:在索引匹配时,必须先能够匹配name字段(最左边的),才能继续匹配age字段(下一个), age字段匹配成功了才能匹配position字段。

为什么?

因为联合索引中的最左边字段是有序的,而第二个字段是在第一个字段相同的情况下有序,第三个字段是在第二个字段相同的情况下有序。

如果你想要用age字段直接在联合索引中查找数据,对不起,找不到,因为age字段中联合索引中是无序的。

你把第一行name字段遮掉看看age字段的情况:18,18,20,15,25,16,33。无序的对吧。

还是有点迷惑?没关系,我们再来通过案例分析分析。

什么是走索引?就是看索引会不会起到作用,能够起到作用就叫走了索引,没有起到作用就叫没走索引。

案例分析

表结构:

CREATE TABLE `employees` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
  `age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
  `position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
  `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时\r\n间',
  PRIMARY KEY (`id`),
  KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8 COMMENT='员工记录表';

sql1

explain select * from employees where name > 'zhangsan18'

name字段是联合索引最左边的字段,所以会走索引

image-20230120145946516

sql2

explain select * from employees where age = 18

age字段并非联合索引最左边的字段,在索引中无序,故不走索引,全表扫描

image-20230120150113853

sql3

explain select * from employees where name = 'zhangsan18' and age = 20;

name字段和age字段都会走索引,因为在name字段相同时,age字段是有序的, 所以此时age也可以走索引。

image-20230120150855590

以上图为例,当定位到zhangsan18时,可以直接定位到age=20这条数据,不需要从age=18的地方遍历寻找,所以索引对age字段也起到作用了。

image-20230120151229081

你现在明白什么是最左前缀法则了吧,还不明白就私信我吧[叹气.jpg]。

SQL案例

现在,我们再来通过一些sql继续深挖这最左前缀法则。

sql4

explain select * from employees where age = 20 and name = 'zhangsan18';

和sql3相同,name和age都会走索引,最左前缀和你sql语句的位置无关,mysql在执行时会自动调整位置,也就是改成name = 'zhangsan18' and age = 20

sql5

explain select * from employees where name > 'zhangsan18' and age = 20;

只有name字段会走索引,age不会走索引,因为此时mysql的查询逻辑是定位到name=zhangsan18最右边的一条数据,然后通过叶子结点的指针向右扫描遍历,索引对age字段未起到作用。如图

image-20230120171406509

explain结果:

image-20230120171842732

sql6

explain select * from employees where name >= 'zhangsan18' and age = 20;

和sql5差不多,唯一的区别就是name是大于等于。此时name和age都会走索引。

image-20230120172053144

现在,我估计你一定晕了,网上不是说范围查找会导致索引失效吗?怎么还走了age字段。

这样,我把sql这样写:

explain select * from employees where (name = 'zhangsan18' and age = 20) or (name > 'zhangsan18' and age = 20);

name = 'zhangsan18' and age = 20部分:name和age都会走索引,这个没问题吧?

name > 'zhangsan18' and age = 20部分:name走索引,age不走索引,这个也我没问题吧?

合起来就是name和age都会走索引,因为name = 'zhangsan18' and age = 20时age要走索引。

还是迷惑?那梳理下流程。

mysql执行时先定位到name=zhangsan18, 然后由于后面还有个age=20条件,所以会直接定位到这里

image-20230120172715433

然后再往右扫描name>zhangsan18的记录, 你告诉我这个过程有没有用上age字段的索引?用上了吧,所有age字段也会走索引,也仅仅是这个时候会走索引,后面name>zhangsan18的还是不走索引。

sql7

explain select * from employees where name like 'zhangsan18%' and age = 10

name和age都会走索引,和sql6一样理解就好。

image-20230120172053144

sql8

explain select * from employees where name between 'zhangsan18' and 'zhangsan50' and age = 10

name和age都会走索引

image-20230120172053144

到这里,你对最左前缀法则应该会有个深刻的认识了,更多的想法,就由你自己去探索啦

索引下推

MySQL在5.6之后加了一个优化:索引下推,可以在索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,可以有效的减少回表次数

拿这条sql举例:

explain select * from employees where name > 'zhangsan18' and age = 20;

这条sqlname字段走索引,age不走索引,在没有索引下推时,查询逻辑是这样的:

1、存储引擎通过联合索引找到name > 'zhangsan18'的记录

2、然后使用联合索引存储的主键进行回表操作,查询出所有数据

3、将数据返回给Server层

4、Server层判断这条记录的age是否为20, 是则返回给客户端,否则丢弃

这里就有个优化点,在第一步用联合索引找到name > 'zhangsan18'的记录时,能不能直接判断age是否为20?如果是再进行后面的步骤。

哎,你觉得能不能?

能!age字段本来就在联合索引里面,直接判断就完事了~

所以,这就是索引下推。简单吧~

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5天前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
27天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
9天前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
14天前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
41 3
|
16天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
38 1
|
23天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
61 9
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
85 1
|
23天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
53 5
|
28天前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
58 1
|
28天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
49 1