面试必须要知道的MySQL知识--索引

10 索引

10.1 数据页存储结构

10.1.1 数据页的各个部分

在讲索引之前,让我们看看一个单独的数据页是什么样子的

去除掉一些我们不太需要那么关注的部分后,简化如下:

也就是说平时我们在一个表里插入的一行一行的数据会存储在数据页里,然后数据页里的每一行数据都会按照主键大小进行排序存储,同时每一行数据都有指针指向下一行数据的位置,组成单向链表。

10.1.2 页分裂

随着业务的发生,我们的数据页一般会越来越大,当大到一定程度的时候,就需要再搞一个数据页了,如下图所示

但是这一步骤并不是说简简单单多加一个数据页就 OK,还需要保证新加的数据页中的每一行数据的主键值都要比前面的大才行,所以数据行有可能会在数据页中挪动。具体如下图所示:

10.2 索引页存储结构

10.2.1 概念

上一节我们讲了数据页的存储结构,这一节我们继续学习索引页的存储结构。

我们先思考一个问题,如果我们只有一般的数据页,咱们怎么找到自己想要的数据呢?是不是要将数据页全部遍历,再在每一个页中,通过二分查找查询数据。这么做,实在是太慢了!所以 MySQL 抽象出了一个索引页的概念,它和一般的数据页差不多,只不过存放的是最小主键值和页号。然后后续你查询主键值,就可以在目录里二分查找直接定位到那条数据所属的数据页,接着到数据页里二分查找定位那条数据就可以了,如下图所示

但是随着数据页越来越多,索引页也变得越来越多,这个时候怎么办呢?这个时候 MySQL 会抽象出一个更高层级的索引页,它里面记录的是最小主键值和索引页号。

那么现在问题再次来了,假如你最顶层的那个索引页里存放的下层索引页的页号也太多了,怎么办呢?此时可以再次分裂,再加一层索引,最后不断的向上加,索引页看起来就像下面这个样子了,也就是一颗 B+树。

10.2.1 例子

最后我们以最简单最基础的主键索引来举例,当你为一个表的主键建立起来索引之后,其实这个主键的索引就是一颗 B+树,然后当你要根据主键来查数据的时候,直接就是从 B+树的顶层开始二分查找,一层一层往下定位,最终一直定位到一个数据页里,在数据页内部的目录里二分查找,找到那条数据。

10.3 聚簇索引

10.3.1 特点

我们上面介绍的B+树索引,它有两个特点:

  • 使用记录主键值的大小进行记录和页的排序

  • B+树的叶子节点存储的是完整的用户记录

    符合这两个特点的索引,就是聚簇索引。在 InnoDB 存储引擎中,聚簇索引就是数据的存储方式,InnoDB 存储引擎会自动的为我们创建聚簇索引。

10.4 二级索引

10.4.1 概念

聚簇索引,使用记录主键值的大小进行记录和页的排序,他是和主键强关联的。但是如果查询的条件不是主键,而是其他列呢?这个时候,就要请出咱们的二级索引了。

二级索引也是一颗B+树,但是它的数据页里存放的是主键+目标字段值。换句话说,将聚簇索引中的主键值替换成目标值段,且叶子节点仅存储主键+目标字段值这两个列的值,那么他就是二级索引了。

当你要根据目标字段来查数据的时候,直接就是从 B+树的顶层开始二分查找,一层一层往下定位,最终一直定位到一个数据页里,在数据页内部的目录里二分查找,找到那条数据。但是这条数据只有主键+目标字段值。

10.4.2 图解

10.4.3 回表

如果你的查询结果中还需要有其他值,那么你得再根据主键在聚簇索引这个B+树中,再查找一次,得到最终的结果,这个过程叫做回表。

10.5 联合索引

联合索引也是一颗B+树,但是它的数据页里存放的是主键+多个目标字段值。其他和二级索引类似。

10.6 覆盖索引与回表查询

10.6.1 概念

首先我们要明确一点,覆盖索引,并不是真正的索引,他其实是一种基于索引的查询方式。

不管是二级索引,还是联合索引,如果你的查询结果中没有其他值,只有索引值,那么你得不需要再在聚簇索引这个B+树中,再查找一次,只需要扫描当前索引的叶子节点,就能得到结果,这种就叫做覆盖索引。

10.6.2 例子

select xx1,xx2,xx3 from table order by xx1,xx2,xx3

基于xx1,xx2,xx3建立联合索引

这种情况下,你仅仅需要联合索引里的几个字段的值,那么其实就只要扫描联合索引的索引树就可以了,不需要回表去聚簇索引里找其他字段了。

10.7 如何更好的建立索引

通过前文我们知道了索引其实是一颗一颗的B+树,那么接下来我们介绍一下B+树索引适用的条件。

10.7.1 索引适用的条件

首先我们给出一张示例表,如下:

CREATE TABLE `user` (  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',  `name` varchar(32) NOT NULL COMMENT '用户名',  `age` int(3) NOT NULL COMMENT '年龄',  PRIMARY KEY (`id`),  KEY `index_name_age` (`name`,`age`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='user示例表';

这个例子中,有两个索引,一个是根据id排序的聚簇索引,另一个是跟据name和age排序的二级索引。

注意:二级索引,是先跟据name排序,如果name相同,再根据age排序的。

10.7.1.1 全值匹配

例子:

SELECT * FROM user WHERE name = '第七人格' AND age = '29';

解析:

  • 因为B+树的数据页和记录先是按照name列的值进行排序的,所以先可以很快定位name列的值是“第七人格”的记录位置。

  • 在name列相同的记录里又是按照age列的值进行排序的,所以在name列的值是“第七人格”的记录里又可以快速定位age列的值是’29’的记录。

101.7.1.2 匹配左边的列

【例子】:

SELECT * FROM user WHERE name = '第七人格';

解析:

  • 因为B+树的数据页和记录先是按照name列的值进行排序的,所以先可以很快定位name列的值是“第七人格”的记录位置。

【反例】:

SELECT * FROM user WHERE age = '29';

解析:

  • 因为B+树的数据页和记录先是按照name列的值进行排序的,所以先可以很快定位name列的值是“第七人格”的记录位置,但是现在用age去找,你想想能找到吗?当然找不到了,你都没找到第一层排序的name值,怎么能找到下层的age呢?

10.7.1.3 匹配列前缀

【例子】:

SELECT * FROM user WHERE name like '第七%';

解析:

  • 因为B+树的数据页和记录先是按照name列的值进行排序的,那么的值是按照字符串排序的,字符串本质是按照字符排序的,这个例子中“第七”是被排好序了的,也可以很快定位name列的值是“第七…”的记录位置。

【反例】:

SELECT * FROM user WHERE name like '%第七%';

或者

SELECT * FROM user WHERE name like '%第七';

解析:

  • “第七”并没有排好序,所以无法使用索引。

10.7.1.4 匹配范围值

【例子】:

SELECT * FROM user WHERE name > 'Anna' AND name < 'Ziad';

解析:

  • name能用到索引。

【例子】:

SELECT * FROM user WHERE name > 'Anna' AND age < '35';

解析:

  • name能用到索引,age不能。

【思考】:

SELECT * FROM user WHERE name = 'Anna' AND age < '35';

请读者思考上面可以使用到索引吗?为什么?

10.7.1.5 排序

【例子】:

SELECT * FROM user ORDER BY name,age LIMIT 1;

解析:

  • 这个是可以用到索引的,因为他是按照联合索引的字段顺序去进行order by排序的,这样就可以直接利用联合索引树里的数据有序性,到索引树里直接按照字段值的顺序去获取数据。

【反例】:

SELECT * FROM user ORDER BY name ASC,age DESC;

解析:

  • 既有升序又有降序,没办法使用索引。

10.7.1.6 分组

【例子】:

SELECT name,age FROM user GROUP BY name , age;

解析:

  • 这个是可以用到索引的,原因可以类比排序。

10.7.2 阿里巴巴索引规约

  • 【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。

  • 【强制】超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致;多表关联查询时, 保证被关联的字段需要有索引。

  • 【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。

  • 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

  • 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。

  • 【推荐】利用覆盖索引来进行查询操作,避免回表。

  • 【推荐】利用延迟关联或者子查询优化超多分页场景。

  • 【推荐】建组合索引的时候,区分度最高的在最左边。

以上规约摘自阿里巴巴开发手册,通过前面的学习,我相信大家可以从更深层次理解这些规约了,而不是一味的死记硬背。

10.8 执行计划与性能优化浅谈

10.8.1 总览

在生产中我们判断一个SQL写的好不好,一般都是通过EXPLAIN关键字,看他的执行计划的。

首先我们看看执行计划长什么样子,我们执行以下SQL

EXPLAIN SELECT * FROM user WHERE name = '第七人格' AND age = '29';

得到的执行计划如下:

10.8.2 要素

10.8.2.1 id

这个字段对性能优化来说,不太重要,我们只需要知道,在一个大的查询语句中每个SELECT关键字都对应一个唯一的id 就行了。

10.8.2.2 select_type

SELECT关键字对应的那个查询的类型,也不重要。

10.8.2.3 table

表名,意思就是查的哪个表,也不是很重要。

10.8.2.4 partitions

匹配的分区信息,我们接触不到这个知识点,99.9%都是null。

10.8.2.5 type

针对单表的访问方法,这个就非常重要了。

完整的类型如下:system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL 。

这里我们针对比较常见和重要的几种类型介绍一下。

const,常量级,一般出现这个,就表示,你写的SQL非常好,性能非常快。哪些属于const呢?比如select * from user where id=x,或者select * from user where name=x这样的的语句,直接就可以通过聚簇索引或者二级索引+聚簇索引回表,轻松查到你要的数据。

值的一提的是,这里的二级索引必须是唯一索引。如果是普通索引,那么就是ref了,就如我们总览中的执行计划一样。当然,ref也是一种非常快的查询方式。

range也是一种常见的查询方式,一般出现在范围查询中,比如我们前面举的一个例子select * from user where name>=x and name <=x,假设name就是一个普通索引,此时就必然利用索引来进行范围筛选,一旦利用索引做了范围筛选,那么这种方式就是range。

我们再回忆一下这个sql,select name,age from user where age = ‘29’,因为age不是索引最左边的值,所以它是没法从联合索引的根节点二分查找快速跳转的,但是因为他的结果和条件都在索引里,所以MySQL的优化器,会直接扫描这个联合索引,一个个的遍历。也就是说,针对这种只要遍历二级索引就可以拿到你想要的数据,而不需要回源到聚簇索引的访问方式,就叫做index访问方式,这种访问方式相对于前面几种,就要慢的多。

最后再看看ALL,顾名思义,全表扫描,一般属于我们要杜绝的情况。

10.8.2.6 possible_keys

可能用到的索引。

10.8.2.7 key

实际上使用的索引。

10.8.2.8 key_len

实际使用到的索引长度。

10.8.2.9 ref

当使用索引列等值查询时,与索引列进行等值匹配的对象信息。

10.8.2.10 rows

预估的需要读取的记录条数,这个值按道理来说,越小越好。

10.8.2.11 filtered

某个表经过搜索条件过滤后剩余记录条数的百分比,对于单表查询来说,这个值没什么意义,都是100%,但是对于多表查询就有意义了,越小越好。

10.8.2.12 Extra

一些额外的信息。比如Using where,Using index,Using filesort等等。我们用group by、union、distinct之类的语法的时候,要是没法直接利用索引来进行分组聚合,那么MySQL会直接基于临时表来完成,会有大量的磁盘操作,也就是会使用文件排序(Using filesort)。这种情况一般也是需要避免的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL企业版之Firewall(SQL防火墙)

​​​1. 关于Firewall插件 2. Firewall插件的工作方式 3. Firewall插件测试 4. 总结延伸阅读 1. 关于Firewall插件 Friewall是MySQL企业版非常不错的功能插件之一,启用Firewall功能后,SQL的执行流程见下图示意: 2. Firewall插件的工作方式 Firewall插件的工作机制大概是…

FL Studio水果软件21.1新版!新增Hyper Chorus插件及自动更新功能

我们很高兴地宣布在去年12月发布重大版本更新后&#xff0c;FL Studio在2023年8月正式更新到21.1版。本次更新虽然只是维护性质&#xff0c;但我们还是为大家带来了一些全新的功能&#xff0c;包括通过钢琴卷中的音阶捕捉和自定义音符工具&#xff0c;引入更快、更有创意的音符…

4/150:寻找两个正序数组的中位数⭐

题目&#xff1a;寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 题解1&#xff1a;暴力 暴力思路简介&#xff0c;…

实测有效的 8 个顶级Android 数据恢复工具

由于我们现在生活在一个依赖数字数据的时代&#xff0c;当重要文件从我们的 Android 手机中消失时&#xff0c;这将是一场数字噩梦。如果您没有预先备份Android手机上的数据或未能通过备份找到已删除的数据&#xff0c;那么选择最好的Android数据恢复软件是最佳选择。 因此&am…

uniapp中进行地图定位

目录 一、创建map 二、data中声明变量 三、获取当前位置信息&#xff0c;进行定位 四、在methods中写移动图标获取地名地址的方法 五、最终展示效果 一、创建map <!-- 地图展示 --><view class"mymap"><!-- <view class"mymap__map"…

大数据存储技术期中考点梳理

1.CAP理论 分布式系统的CAP理论: 首先将分布式系统中的三个特性进行如下归纳: 口(一致性(C):在分布式系统中的所有数据备份&#xff0c;在同一时刻是否有同样的值。(等于所有节点访问同一份最新的数据副本) 口可用性(A):在集群中一部分节点故障后&#xff0c;集群整体是否还能…

再探Java集合系列—ArrayList

适用于什么场景&#xff1f; 检索比较多的场景&#xff0c;例如学生成绩管理系统&#xff0c;老师对学生的成绩进行排名或查询操作 ArrayList有哪些特点&#xff1f; 1、ArrayList集合底层采用了数组数据结构&#xff0c;是Object类型 2、动态数组。ArrayList的默认初始容量…

西南科技大学(数据结构A)期末自测练习二

一、填空题(每空1分,共10分) 1、在线性表的下列运算中,不改变数据元素之间结构关系的运算是( D ) A、插入 B、删除 C、排序 D、定位 2、顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是( B ) A.110 B.108 C.100 …

爱普生L3153变ET-2710修复

晚上还在加班&#xff0c;老婆发来消息说打印机故障了&#xff0c;通过网络不能访问 回家一下&#xff0c;三个灯&#xff08;电源&#xff0c;网络&#xff0c;墨水&#xff09;闪烁 重启多次没效果&#xff0c;问客服&#xff0c;说是存储错误&#xff0c;要送售后&#xff…

4.4-Docker bridge0详解

在Docker世界中&#xff0c;两个container是通过bridge0连接起来的。 首先&#xff0c;介绍一个命令&#xff1a;docker network ls 这个docker network ls明令会列举出来当前这台机器上docker有哪些网络。 先看一下bridge。 现在有一个容器flask-hello-docker&#xff0c;它是…

接手了一个外包开发的项目,我感觉我的头快要裂开了~

嗨&#xff0c;大家好&#xff0c;我是飘渺。 最近&#xff0c;我和小伙伴一起接手了一个由外包团队开发的微服务项目&#xff0c;这个项目采用了当前流行的Spring Cloud Alibaba微服务架构&#xff0c;并且是基于一个“大名鼎鼎”的微服务开源脚手架&#xff08;附带着模块代…

IDEA编译器的永久试用设置与基本使用

参考视频&#xff1a; 最通俗易懂的JDK、IDEA的安装使用权威指南 2023新版前端Web开发HTML5CSS3移动web视频教程&#xff0c;前端web入门首选黑马程序员 文章目录 一.安装包下载与安装二.设置IDEA永久试用三.IDEA的基本试用0.IDEA管理Java程序的结构1.工程创建2.模块创建3.包创…

Anolis 安装 Conda 和 YoloV8

Anolis 安装 Conda 和 YoloV8 一 Conda 和 YoloV8 安装1.Conda 下载与安装2.YoloV8 安装 二.测试 一 Conda 和 YoloV8 安装 ## 1. anolis 安装 cv2 依赖库 yum install -y mesa-libGL.x86_64 ## Anaconda https://repo.anaconda.com/archive/ ## 重启终端查看版本 conda --ver…

Linux处理文件常见命令

目录 1 cp 2 rm 3 zip与unzip 3.1 zip 3.2 unzip 4 cd 5 ls 6 chmod 7 scp 7.1 文件在你操作的机器上&#xff0c;你要传给另一个机器 7.1.1 文件 7.1.2 文件夹 7.2 文件在另一个机器上&#xff0c;你要把文件搞到你操作的机器上 7.2.1 文件 7.2.…

上海亚商投顾:沪指震荡反弹 汽车产业链掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡反弹&#xff0c;北证50指数跌超4%&#xff0c;近50只北交所个股跌超10%。 新能源车产业链掀…

leetCode 216.组合总和 III + 回溯算法 + 剪枝 + 图解 + 笔记

找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解释…

Istio新架构揭秘:环境化Mesh

自问世以来&#xff0c;Istio因其使用Sidecar&#xff08;可编程代理与应用容器一同部署&#xff09;而备受认可。这种架构选择使Istio用户能够享受其好处&#xff0c;而无需对其应用进行 drast 改变。这些可编程代理&#xff0c;与应用容器紧密部署在一起&#xff0c;因其能够…

Langchain-Chatchat学习

参考&#xff1a;Langchain-Chatchat 阿里通义千问Qwen 保姆级教程 | 次世代知识管理解决方案 - 知乎 (zhihu.com) 中文LLM生态观察 模型 就开源的部分而言&#xff0c;从一开始的MOSS[1] ChatGLM[2] ChatGLM2 [3] 到后来的 baichan [4] 基于LLama2 微调的 中文LLama2 [5] …

Blender学习笔记:小车狂奔动画

文章目录 路旁小树汽车尾气移动 教程地址&#xff1a;八个案例教程带你从0到1入门blender【已完结】 小车建模 路旁小树 1 添加摄像机&#xff0c;在小车下面拉一个平面&#xff0c;覆盖到摄像机的观察视窗。复制一层平面&#xff0c;收窄变成小车两侧的路面&#xff0c;编辑…

项目:基于UDP的网络聊天室

项目需求&#xff1a; 1.如果有用户登录&#xff0c;其他用户可以收到这个人的登录信息 2.如果有人发送信息&#xff0c;其他用户可以收到这个人的群聊信息 3.如果有人下线&#xff0c;其他用户可以收到这个人的下线信息 4.服务器可以发送系统信息 服务器代码&#xff1a; #i…