MySQL索引(二)索引优化方案有哪些

article/2025/11/7 6:41:27

在上一篇文章中,我们介绍了MySQL中常见的索引类型以及每种索引的各自特点,那么这篇文章带你来与我一起看一下聚集索引与二级索引的关系,最后在附上常见的索引优化方案。首先我们还是看一下聚集索引和二级索引的区别

MySQL索引(一)

聚集索引和二级索引区别

首先,每个Innodb引擎的表都有一个聚集索引,用于存储行数据,通常情况下,聚集索引也叫做主键索引。

  • 如果一个表定义了主键,Innodb就使用它作为聚集索引。因此我们要尽可能的为表添加一个主键,如果实在没有一个列是非空且唯一的可以作为主键列,建议添加一个自动递增的列作为主键列

  • 如果表没有主键,Innodb会选择第一个非空且唯一的列作为聚集索引

  • 如果表既没有主键,也没有非空且唯一的索引,则Innodb生成一个隐藏的聚集索引,GEN_CLUST_INDEX 包含rowid值的列,数据行根据rowid排序,rowid是一个6字节的字段,随着数据插入而单调递增,也就是说,数据行根据rowid排序也就是根据插入顺序排序的

在上面,我们知道了主键索引也就是聚集索引,而且我们的日常工作中,查询如果根据主键查询都是很快的,那么聚集索引是如何提升查询效率的呢?

聚集索引如何提升查询效率

通过聚集索引访问一条数据是很快的,这是因为所有的行数据和索引保存在同一个页上。如果表数据特别大,相较于数据和索引保存在不同的页上的存储结构相比,Innodb大大节省了磁盘IO操作

现在我们知道了聚集索引之所以查询的快是因为要查询的行数据和索引都保存在同一个页上,也就减少了去磁盘查找数据的过程,那么二级索引呢,二级索引是如何与聚集索引关联的呢?

二级索引如何与聚集索引关联

聚集索引之外的其它索引全部被称为二级索引。在Innodb中,二级索引中的每条记录都包含主键列以及本身二级索引指定的索引列,在聚集索引中,Innodb使用此主键值查询该行的数据

如果主键较长的话,那么我们二级索引保存主键列时就会占用更多的空间,所以主键尽可能的短是有利的

读到这,我们应该已经知道了,聚集索引中所有记录与索引都保存在同一个页中,所以这也是聚集索引查询快的原因。二级索引没有保存当前记录的数据,只保存了主键列,所以在使用二级索引的时候会涉及到两步操作,即根据二级索引先定位主键列,然后根据主键列在聚集索引中查询数据返回。现在我们也知道了,通过二级索引查找会涉及到多一次交互的问题,那么这个点也是我们后文将要讨论的一个点,也就是所谓的回表。目前我们常用的索引优化方式有覆盖索引、最左前缀、索引下推,现在我们一起来详细看下索引的优化方式是怎么工作的

常用的索引优化方式

覆盖索引

首先我们还是新建一张表t,在k列建立索引,建表语句如下

create table t(id int primary key,k int not null default 0,s varchar(16) not null default '',index k(k)
)engine=Innodb;
# 加入测试数据
insert into t values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

在上文中,我们已经知道了聚集索引与二级索引的区别,所以在执行完上面的插入语句之后,数据的存储结构为两棵索引树,一棵主键索引树包含数据,一棵二级索引k的索引树

此处借鉴一下极客时间丁奇老师的索引结构图,此处放个不同数据结构存储图,这个网站不错,可以模拟数据结构的存储过程,给大家推荐一下,这块网站模拟的和丁奇老师的还是不一样,这块原因还不了解,对这块还不是很熟悉,有了解的可以评论区说一下,互相学习一下。本文还是以丁奇老师讲解的图为主

Arts and Sciences - Computer Science | myUSFicon-default.png?t=M276https://www.cs.usfca.edu/

首先我们执行一条查询语句

select * from t where k between 3 and 5;

执行过程是这样的,首先到k索引树取到值为3的到主键索引树获取主键等于300的R3记录返回,然后取k索引树下一值5的主键500到主键索引树取500的记录R5,然后取k索引树下一个值6的主键600到主键树查询,发现6不符合条件,不再去主键树查询,返回结果

通过上面的分析,那么什么是覆盖索引呢,很简单,我们看下面两条sql语句

1、explain select * from t where k between 3 and 5;
2、explain select id from t where k between 3 and 5;

两条语句的执行分析结果如下

两条sql唯一的区别就是第一条sql会获取所有的字段,而第二条sql只获取id这个字段,而k索引树上已经保存了id的值,所以此时也就不用回表查询了,这种方式就是覆盖索引。因为覆盖索引可以大大减少搜索树的次数,所以使用覆盖索引是常用的优化手段

下面我们在看另一个使用覆盖索引的例子首先还是创建一张用户表,建表语句如下

​
CREATE TABLE `tuser` (`id` int(11) NOT NULL,`id_card` varchar(32) DEFAULT NULL,`name` varchar(32) DEFAULT NULL,`age` int(11) DEFAULT NULL,`ismale` tinyint(1) DEFAULT NULL,PRIMARY KEY (`id`),KEY `id_card` (`id_card`),KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB
# 加入数据
insert into tuser values(1,'123456789012345678','test1','18',1),(2,'123456879012345677','test2','19',1),(3,'123456987012345676','test3','20',1),(4,'123456986012345675','user1','21',0),(5,'123456985012345674','user2','22',1),(6,'123456787012345673','user3','23',1),(7,'123456788012345672','admin1','24',0);

现在我们在表上建立了两个索引,身份证上一个索引,姓名和年龄一个索引。如果我们根据身份证获取用户信息,那么一个身份证索引就可以满足了,但是要是有一个高频的请求,根据身份证获取用户姓名,那么我们可以再创建一个身份证和姓名的联合索引,这样这些所有的根据身份证获取用户名的请求都可以在身份证姓名的联合索引上使用覆盖索引,那么这个索引也就是有意义的。

explain select * from tuser where id_card = '123456789012345678';

下面是根据身份证索引查询信息的执行结果

借助name,age的联合索引我们来分析一下最左前缀和索引下推

最左前缀

在上面的测试数据中,如果我们有以下查询语句

1、explain select * from tuser where name like 'test%';
2、explain select * from tuser where name = 'test1';

第一条语句会在查询时获取name,age索引树上test开头的数据,是可以用到name_age的联合索引的(possible_keys),但是在这次查询中优化器没有选择使用索引(key是null)

第二条语句也是可以走name,age索引树的,而且选择走name_age的联合索引(possible_keys和key都是name_age)

 

通过上面两条sql语句,我们可以知道,不只是索引的全部定义,只要满足索引的最左前缀也是可以加速访问的。这个最左前缀可以是字符串索引的前n个字节,也可以是联合索引的 最左n个字段。

索引下推

开启关闭索引下推功能,默认情况下是开启的

SET optimizer_switch = 'index_condition_pushdown=off';
SET optimizer_switch = 'index_condition_pushdown=on';

那么什么是索引下推呢,还是上SQL语句

SET optimizer_switch = 'index_condition_pushdown=off';
explain select * from tuser where name like 'test%' and age = '18';
SET optimizer_switch = 'index_condition_pushdown=on';
explain select * from tuser where age = '18' and name like 'test%';

那么怎么看是否使用了索引下推呢,引用下官网 的一句话,Extra列显示Using index condition即使用了索引下推

  • EXPLAIN output shows Using index condition in the Extra column when Index Condition Pushdown is used. It does not show Using index because that does not apply when full table rows must be read.

所以,到底什么是索引下推呢,来看我分析

  • 关闭索引下推优化时

    首先或者所有name是test开头的数据,然后回表,判断age等于18的数据,然后返回数据

  • 开启索引下推优化时

    获取name是test开头的数据,并判断age等于18 的数据,然后剩余的数据拿到主键索引树回表查询返回

两者的区别就是回表的次数明显变少,在索引下推优化关闭时,会拿所有的主键去主键树获取数据,而开启之后,提前做判断,减少回表次数,这就是索引下推,也是工作中常用到的优化方式

_rowid 查看示例

非空,唯一,主键

create table test(a int primary key,b varchar(5));
insert into test values(1,'a'),(2,'b'),(3,'c'),(4,'c'),(5,'d');
select _rowid from test;

原文链接

MySQL索引(二)常见的索引优化方案有哪些icon-default.png?t=M276https://mp.weixin.qq.com/s?__biz=MzIwNzYzODIxMw==&mid=2247484816&idx=1&sn=cea8bf2c5d5ddcdcb473a86aac6e8b77&chksm=970e1e3aa079972cc437afd1f745bbae3eeaa226e4134b8b69e7f57e86e70b789e6753ec22f0#rd

参考链接

MySQL :: MySQL 8.0 Reference Manual :: 15.6.2.1 Clustered and Secondary Indexes

有不同索引类型之间的描述

MySQL :: MySQL 8.0 Reference Manual :: 13.1.15 CREATE INDEX Statement

b树索引与hash索引的对比

MySQL :: MySQL 8.0 Reference Manual :: 8.3.9 Comparison of B-Tree and Hash Indexes

index

MySQL :: MySQL 8.0 Reference Manual :: MySQL Glossary

geek

05 | 深入浅出索引(下)-极客时间


http://chatgpt.dhexx.cn/article/V6TPRMG9.shtml

相关文章

【MySQL】索引优化原则

前面几篇博文谈到索引使用场景和explain命令帮助我们分析索引的执行情况,今天进入正题,来谈谈索引优化的原则。 1、全值匹配 查询语句尽量使用全值匹配。 2、左前缀原则 如果一个索引是组合索引,索引了多列,要遵循左前缀原则…

MySQL:索引优化、查询优化

一、哪些情况适合创建索引 1、字段的数值有唯一性的限制; 业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引; 说明:创建唯一索引会影响添加的速度(在添加的时候会维护索引)&…

Mysql-索引优化

一、索引基本知识 1、索引的优点 很大程度上减少服务器扫描的数据量很大程度上避免服务器排序和临时表将随机IO变成顺序IO 2、索引的用处 使用索引列可以快速查找Where条件的行数据 mysql> explain select * from emp where empno 7469; ----------------------------…

MySQL索引优化总结

前言:相信大家都知道索引可以大大提高MySQL的检索速度,但是真正在平时工作中写SQL,真的会考虑到这条SQL如何能够用上索引提升执行效率?本篇博客详细的介绍了索引优化的20个原则,只要在工作中能够随时应用到&#xff0c…

【MySQL】深入理解MySQL索引优化器原理(MySQL专栏启动)

📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

mysql 索引优化

一、mysql索引建立原则 二、通过 EXPLAIN 分析 SQL 执行计划 可以知道以下内容: 假设现在我们使用 EXPLAIN 命令查看当前 SQL 是否使用了索引,先通过 SQL EXPLAIN 导出相应的执行计划如下: 下面对图示中的每一个字段进行一个说明&#x…

【MySQL】MySQL索引优化——从原理分析到实践对比

目录 使用TRACE分析MySQL优化 开启TRACE TRACE 结果集 ORDER BY & GROUP BY 优化 优化方式 分页优化 不同场景的优化方式 JOIN关联优化 算法介绍 优化方式 COUNT优化 优化方式 使用TRACE分析MySQL优化 某些情况下,MySQL是否走索引是不确定的[,,_,,…

MySQL索引常见面试题(2022版)

目录 为什么要建立索引? 哪些情况适合建立索引? 哪些情况下不适合建索引? 为什么索引是使用B树?(重点) 索引分为那几类? 什么是聚簇索引?(重点) 使用聚…

mysql数据库索引优化【建议收藏】

在我们程序员玩数据库的时候,经常会写sql,但是决定一个sql的好坏往往是效率,于是我们需要不断的去优化我们的sql,写一句让人称赞的sql是非常不容易的,也是需要大家有非常深厚的功底,所以优化路漫漫&#xf…

MySQL索引优化

MySQL索引优化 一、优化索引的方法二、优化步骤前缀索引优化覆盖索引优化主键索引最好是自增的索引最好设置为NOT NULL防止索引失效 总结 一、优化索引的方法 这里说一下几种常见优化索引的方法: 前缀索引优化; 覆盖索引优化; 主键索引最好是…

Android底层到上层的开发流程

安卓系统整体框架图如下: 简单总结如下: 1、在kernel层编写你的驱动程序:生成设备文件节点跟上一层传输数据,主要调用函数copy_to_user和copy_from_user,注意赋节点权限问题。 2、在HAL层封装对上提供的函数接口&…

【Android】Android底层开发实战

本书分为四个部分:第一部分为预备知识篇,简要介绍嵌入式系统的定义与软硬件开发以及Android开发环境的搭建。第二部分为系统结构篇,主要介绍Android系统的源码结构、内核与相关工具以及环境库。第三部分为驱动设计篇,主要介绍Andr…

我做了几年的Android应用层开发,为什么还要去学习安卓系统知识?

作为一个工作了好几年的Android应用层开发者,我准备在工作之余干一件事情,那就是学习Android系统知识,为什么要做这个决定呢? 其主要原因是想在Android应用层开发进阶 这个说起来并非易事,可能在很多人的认知里&…

一个Android应用层开发如何转型深入Android Framework?

作为一个工作了好几年的Android应用层开发者,准备在工作之余干一件事情,那就是分享一些Android系统知识,为什么决定要做这个呢,理由如下: 帮助更多人转型Android系统开发 不知何时起,单纯的Android应用层…

android底层开发-android基础架构

android architecture 在安卓中,最经典的架构就是分四层,分别是application、framework、libraries、kernel四层,通过这四层将android的整个架构都丰满起来 其架构图如下 android 系统组成 Process FW: android 系统固件&#…

Android Framework 开发揭解密,移动开发者必须掌握的底层原理

作为过来人,发现很多学习者和实践者都在 Android Framework上面临着很多的困扰,比如: 工作场景中遇到难题,往往只能靠盲猜和感觉,用临时性的补救措施去掩盖,看似解决了问题,但下次同样的问题又会…

Android系统底层架构【译】

Android系统底层架构 转载请注明来源:http://blog.csdn.net/lifeshow 设备移植 Android提供了设备移植和支持方面有较大的自由度,可以制定自有的设备规范和驱动。通过硬件抽象层(HAL-Hardware Abstraction Layer),可以…

嵌入式Android底层开发

嵌入式Linux主要有这几部分&#xff1a; Bootloader&#xff1a;主要用于引导Linux内核到内存中&#xff0c;让内核进行自解压并运行 zImage&#xff1a;带自解压的Linux内核 <Board>.dtb&#xff1a;每个型号的主板都有对应的设备树(保存对应的设备型号等信息&#x…

android 底层系统开发,Android底层

概述-Android系统架构 Android系统架构 概述-Application Application Android平台不仅仅是操作系统&#xff0c;同时也包含了许多应用&#xff0c;如桌面&#xff0c;浏览器&#xff0c;视频客户端&#xff0c;摄像头等。用JAVA编写&#xff0c;可以被开发人员开发的其他应用程…

Android 开发之 ---- 底层驱动开发(二)

Android 设备驱动&#xff08;下&#xff09; MTD 驱动 Flash 驱动通常使用 MTD &#xff08;memory technology device )&#xff0c;内存技术设备。 MTD 的字符设备&#xff1a; /dev/mtdX 主设备号 90. MTD 的块设备&#xff1a; /dev/block/mtdblockX 主设备号 13. MTD 驱…