MySQL面试篇章——MySQL索引

news2024/11/14 20:15:29

文章目录

  • MySQL 索引
    • 索引分类
    • 索引创建和删除
    • 索引的执行过程
      • explain 查看执行计划
      • explain 结果字段分析
    • 索引的底层实现原理
      • B-树
      • B+树
      • 哈希索引
    • 聚集和非聚集索引
      • MyISAM(\*.MYD,*.MYI)
        • 主键索引
        • 辅助索引(二级索引)
      • InnoDB(*.IBD)
        • 主键索引
        • 辅助索引(二级索引)
    • 自适应哈希索引

MySQL 索引

当表中的数据量到达几十万甚至上百万的时候,SQL查询所花费的时间会很长,导致业务超时出错,此时就需要用索引来加速SQL查询。

由于索引也是需要存储成索引文件的,因此对索引的使用也会涉及到磁盘I/O操作。如果索引创建过多,使用不当,会造成SQL查询时,进行大量无用的磁盘I/O操作,降低了SQL的查询效率,适得其反,因此需要掌握良好的索引创建原则!

索引分类

索引是创建在表上的,是对数据库表中的一列或者多列的值进行排序的一种结果。索引的核心是提高查询的速度!

物理上(聚集索引 & 非聚集索引)/ 逻辑上(…)

索引的优缺点:

优点:提高查询效率

缺点:索引并非越多越好,过多的索引会导致CPU使用率居高不下,由于数据的改变,会造成索引文件的改动,过多的磁盘I/O会造成CPU负荷太重

  • 普通索引:没有任何限制条件,可以给任何类型的字段创建普通索引(创建新表 & 已创建表,数量是不限的,一张表的一次SQL查询只能用一个索引 where a = 1 and b = ‘M’)
  • 唯一性索引:使用 UNIQUE 修饰的字段,值不能够重复,主键索引就隶属于唯一性索引
  • 主键索引:使用 PRIMARY KEY 修饰的字段会自动创建索引(MyISAM、InnoDB)
  • 单列索引:在一个字段上创建索引
  • 多列索引:在表的多个字段上创建索引(uid + cid,多列索引必须使用到第一列,才能够用到多列索引,否则索引用不上)
  • 全文索引:使用 FULLTEXT 参数可以设置全文索引,只支持 CHAR、VARCHAR、TEXT 类型的字段上,常用于数据量较大的字符串类型上,可以提高查询速度(线上项目支持专门的搜索功能,给后台服务器增加专门的搜索引擎支持快速高效的搜索 elesticsearch 简称 es;C++开源的搜索引擎;搜狗的workflow)

索引创建和删除

  • 创建表的时候指定索引字段
CREATE TABLE index1(
	id INT,
    name VARCHAR(20),
    sex ENUM('male', 'female'),
    INDEX(id, name),
    INDEX `index name` (sex) # 没有名字,会默认会生成
    # show create table 进行查看创建SQL语句
)

# Create Table: CREATE TABLE `student` (
#  `uid` int unsigned NOT NULL AUTO_INCREMENT,
#  `name` varchar(50) NOT NULL,
#  `age` tinyint unsigned NOT NULL,
#  `sex` enum('M','W') NOT NULL,
#  PRIMARY KEY (`uid`),
#  KEY `nameidx` (`name`)
#) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 #COLLATE=utf8mb4_0900_ai_ci
  • 在已经创建的表上添加索引
CREATE [UNIQUE] INDEX 索引名 ON 表明 (属性名 (length) [ASC | DESC]);

# create index nameidx on student(name); // 默认btree索引

# 添加 hash 索引
# create index ageidx on studetn(age) using hash;
  • 删除索引
DROP INDEX 索引名 ON 表名;
  • 查看所有索引
show indexes from 表明;

1、经常作为 where 条件过滤的字段考虑添加索引

2、字符串列创建索引时,尽量规定索引的长度,而不能让索引值的长度 key_len 过长

3、索引字段涉及类型强转、mysql函数调用、表达式计算等,索引就用不上了(索引失效)

在这里插入图片描述

索引的执行过程

explain 查看执行计划

使用explain查看SQL的执行计划,分析索引的执行过程,mysql的user权限示例如下:
在这里插入图片描述

可以看到使用了主键索引,共扫描了1行,Using index 表示直接从索引树上查询到结果,不需要回表

在这里插入图片描述

  • 由于Host和User设立了联合索引,也就是多列索引,而多列索引只有第一列的索引使用了,才能进行索引查询,不然不会进行索引查询

在这里插入图片描述

explain 结果字段分析

  • select_type

    simple:表示不需要union操作或者不包含子查询的简单select语句。有连接查询时,外层的查询为simple且只有一个

    primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary且只有一个

    union:union连接的两个select查询,除了第一个表外,第二个以后的表的select_type都是union

    union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为null

  • table

    显示查询的表明;

    如果不涉及对数据库的操作,这里就显示null

    如果显示为尖括号就表示这是个临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生的

    如果是尖括号括起来<union M, N>也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集

  • type

    const:使用唯一索引或者主键,返回记录一定是1行已经的等值where条件时,通常type就是const

    ref:常见于辅助索引的等值查找,或者多列主键,唯一索引中,使用第一个列之外的列作为等值查找会出现;返回数据不唯一的等值查找也会出现

    range:索引范围扫描,常见于使用<,>,is null,between,in,like等运算符的查询中

    index:索引全表扫描,把索引从头到尾扫一遍;常见于使用索引列就可以处理不需要读取数据文件的查询,可以使用索引排序或者分组的查询

    all:全表扫描数据文件,然后在server层进行过滤返回符合要求的记录

  • ref

    如果使用常数等值查询,这里显示const

    如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段

  • Extra

    • using filesort:排序时无法用到索引,常见于 order by 和 group by 语句中
    • using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据

索引的底层实现原理

数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘块(对应索引树的节点),索引树越低,越”矮胖“,磁盘I/O次数就越少

MySQL支持两种索引,一种是B-树索引,一种是哈希索引,两者在数据查询的效率是非常高的

主要对于InnoDB存储引擎进行讨论,基于B-树的索引结构(MySQL实际采用的是B+树结构

B-树

B-树是一种m阶平衡树(一般来说m=300~500),叶子节点都在同一层,由于每一个节点存储的数据量比较大,索引整个B-树的层数是比较低的,基本上不超时三层。

二分查找:时间复杂度O(logn)

由于磁盘的读取也是按block块操作的(内存是按page页面操作的),因此B-树的节点大小一般设置为和磁盘块大小一致,这样一个B-树节点,就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写效率,主要集中在磁盘I/O上)

select * from student where uid = 5(uid添加了索引);

uid 有索引 ==> 存储引擎 ==> kernel(操作系统) > 磁盘I/O(读索引文件)> 内存上 ==> 用索引的数据构建B-树加速搜索

在这里插入图片描述

一次磁盘I/O读取的磁盘块的内容,刚好存储在B树的一个节点中

因为非叶子节点都有左右子树,所以指针域 = 数据域 + 1

假设有2000W条数据,用AVL存储2000W条数据,构建下来有25层(计算器以log10为底,所以得这么除)

在这里插入图片描述

如果 m = 500,最多三层,也就是最多花费三次的磁盘I/O,大大减少了速率

扩展:B-树的缺点

  • 每个节点中有key,也有data,但是每一个节点的存储空间是有限的,如果data数据较大时会导致每个节点能存储的key的数据很小
  • 当存储的数据量很大时同样会导致B-树的高度较大,磁盘I/O次数花费增大,导致效率降低

面试考点:为什么MySQL(MyISAM和InnoDB)索引底层采用B+树,而不是B-树?

1、索引 + 数据内容分散在不同的节点上,离根节点近的,搜索就快;离根节点远的,搜索就慢!

2、每一个非叶子节点上,不仅仅要存储索引(key),还要存储索引值所在的那一行的data数据。一个节点所能存放的索引key的个数,比只存储key值的节点的个数要少得多。(例如,索引key要存4个字节,对应data数据也要4个字节,那就是8个字节,每一块数据,但是如果只存索引key,那就可以存两个,数据最后去叶子节点上找)

3、这棵树不方便做范围搜索,整表遍历看起来也不方便

例如:where age > 11 and age < 18,相当于17的左右子树都要去查,然后12的左右子树也要去查。很不方便(看上图)

因此由于以上的三个原因 ==> MySQL采用B+树来构建索引树

B+树

一句话:B+树最后其实就是一个循环链表,串起来了,所以说最后的查询就是在循环链表中进行查询

特点:

  • 每一个非叶子几点,只存放索引key,不存放数据data,好处就是一个节点存放的索引key更多,B+树在理论上来说,层数会更低一些,搜索的效率会更好一些
  • 叶子节点上存储了所有的索引值(数据data),搜索每一个索引对应的值data,都需要在叶子节点上,这样子每一行记录搜索的时间是平均的
  • 叶子节点被串在一个链表当中,形成一个有序的链表,如果要进行索引树的搜索&整表搜索,直接遍历叶子节点的有序链表即可!或者做范围查询的时候,直接遍历叶子节点的有序链表即可

在这里插入图片描述

面试考点:B-树和B+树在存储结构上有什么不同?

1、B-树的非叶子节点,存了索引key和对应的数据地址,而B+树的非叶子节点只存了索引key,不存数据data,因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的,因此,从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,因此查询的会快一些

2、B-树由于每个节点都存储了索引key和对应的数据,因此离根节点近的数据,查询的就快,离根节点远的数据,查询的就慢;而B+树所有的数据都存储在叶子节点上,因此在B+树上搜索索引key,找到对应数据的时间是比较平均的,没有快慢之分

3、在B-树上如果做区间查找,遍历的节点是非常多的;B+树所有的叶子节点被连结成了有序链表结构,因此做整表遍历和区间查找是非常容易的

哈希索引

哈希索引由哈希表实现的,哈希表对数据并不排序,因此不适合做区间查找,效率非常低,需要搜索整个哈希表结构

时间复杂度O(1),链式哈希表

优点:搜索的效率更好、磁盘I/O花费要少

hash(name) = hashkey % bucket_num (哈希冲突)

在这里插入图片描述

哈希表中的元素没有任何顺序可言!只能进行等值比较

select * from student where name = 'zhangsan';

select * from student where name like 'zhang%'; error
  • 范围搜索,前缀搜索,order by 排序这些操作,哈希索引都不适合!!!
  • 它没办法处理磁盘上的数据,加载到内存上构建高效的搜索数据结构,因为它没有办法减少磁盘I/O的次数

聚集和非聚集索引

MyISAM(*.MYD,*.MYI)

select * from student where name = 'zhangsan';

没有索引:直接会在整张表中进行全查(整表搜索)

有索引:进行*.MYI的索引文件的查询,生成B树,然后进行二分查找

主键索引
  • MyISAM引擎使用B+树作为索引结构,叶节点的data域存放的是数据记录的地址(通过这个地址去查找数据data)。

在这里插入图片描述

  • 即主键对应的data是数据的地址(具体的数据都需要去寻址,在一个data数据表中)
辅助索引(二级索引)
  • 在MyISAM中,主键索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯 一的,而辅助索引的key可以重复,如果给其它字段创建辅助索引,结构图如下:

在这里插入图片描述

总结:MyISAM存储引擎,索引结构叶子节点存储关键字和数据地址,也就是说索引关键字和数据 没有在一起存放,体现在磁盘上,就是索引在一个文件存储,数据在另一个文件存储,例如一个user 表,会在磁盘上存储三个文件 user.frm(表结构文件) user.MYD(表的数据文件) user.MYI(表的索引文件)。

MyISAM的索引方式也叫做非聚集索引

InnoDB(*.IBD)

  • InnoDB存储引擎的索引关键字和数据是存放在一起的
select * from student where name = 'zhangsan';

没有索引:会自动生成B树

有索引:会根据索引数据生成一张新的B树

主键索引
  • uid 是主键
  • 主键索引树:

在这里插入图片描述

  • 每个索引下面对应的是对应的数据(例如:15 => 34 Bob)
辅助索引(二级索引)
  • InnoDB的辅助索引,叶子节点上存放的是索引关键字和对应的主键(即如果要获取数据,需要通过主键进行回表查询主键索引树,进行获取到数据)

在这里插入图片描述

select * from student where name = 'Alice';

1、先搜索name的二级索引树,找到Alice对应的主键uid=18

2、再拿uid=18回表在书简索引树搜索uid那一行记录

问题:select * from student where age = 20 order by name;如果只给age添加索引,行不行?还有什么没有考虑到?

不行,如果只有age键索引,会有using filesort!,因此需要创建age、name的多列索引

先按照age进行排序,再按照name进行排序;age相同,按name进行排序

在这里插入图片描述

总结:辅助索引的B+树,先根据关键字找到对应的主键,再去主键索引树上找到对应的行记录数据。从索引树上可以看到,InnoDB的索引关键字和数据都是在一起存放的,体现在磁盘存储上,例如创建一个user 表,在磁盘上只存储两种文件,user.frm(存储表的结构),user.ibd(存储索引和数据)。

InnoDB的索引树叶节点包含了完整的数据记录,这种索引叫做聚集索引

两者的区别:MyISAM比InnoDB多了磁盘I/O的使用,它需要读取*.MYI文件获取索引数据,进行生成B树(相当于多了一部I/O操作,两个文件)

自适应哈希索引

InnoDB存储引擎监测到同样的二级索引不断被使用;那么它会根据这个二级索引,在内存上根据二级索引树(B+树)上的二级索引值,在内存上构建一个哈希索引,来进行加索引搜索

在这里插入图片描述

  • 自适应哈希索引本身的数据维护也是要耗费性能的,并不是说自适应哈希索引在任何情况下都会提升二级索引的查询性能!我们需要根据参数指标,来具体分析是否打开或者关闭自适应哈希索引
show engine innodb status\G

1、RW-latch等待的线程数量(自适应哈希索引默认分配了8个分区),同一个分区等待的线程数量过多
2、走自适应哈希索引的频率(低)和二级索引树搜索的频率(高)

面试考点:SQL和索引的优化问题

通过explain分析SQL

项目 ==> 业务 ==> 千条、万条SQL

流程:从什么地方能够获取哪些运行时间长,耗性能的SQL,然后再通过explain去分析它

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线程的中互斥锁和条件变量的运用

第一题&#xff1a;使用互斥锁或者信号量&#xff0c;实现一个简单的生产者消费者模型 一个线程每秒生产3个苹果&#xff0c;另一个线程每秒消费8个苹果 #include <myhead.h>pthread_mutex_t m1,m2;int apple 0; void* usrapp(void* data) {while(1){pthread_mutex_lock…

旋转差分,以及曼哈顿距离转换切比雪夫距离

拿到这个问题我们要怎么去想呢&#xff0c;如果是暴力的修改的话&#xff0c;我们的复杂度为 m * 2r*r 的复杂度&#xff0c;这也太暴力了&#xff0c;我们要怎么办呢&#xff0c;我们能不能用差分数组来实现呢&#xff1f; 我们首先要看如何实现公式的转换 很显然我们可以利用…

<数据集>pcb板缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;693张 标注数量(xml文件个数)&#xff1a;693 标注数量(txt文件个数)&#xff1a;693 标注类别数&#xff1a;6 标注类别名称&#xff1a;[missing_hole, mouse_bite, open_circuit, short, spurious_copper, spur…

物联网与区块链技术的跨界融合:智能城市的建设与管理

随着科技的迅猛发展&#xff0c;物联网&#xff08;IoT&#xff09;和区块链技术逐渐成为推动智能城市发展的重要技术支柱。本文将探讨物联网和区块链技术在智能城市建设与管理中的跨界融合&#xff0c;分析其应用场景和潜力。 什么是智能城市&#xff1f; 智能城市利用先进的…

(35)远程识别(又称无人机识别)(一)

文章目录 前言 1 更改 2 可用的设备 3 开放式无人机ID 4 ArduRemoteID 5 终端用户数据的设置和使用 6 测试 7 为OEMs添加远程ID到ArduPilot系统的视频教程 前言 在一些国家&#xff0c;远程 ID 正在成为一项法律要求。以下是与 ArduPilot 兼容的设备列表。这里(here)有…

深度刨析C语言中的动态内存管理

文章目录 1.为什么会存在动态内存分配2.动态内存函数介绍2.1 [malloc](https://legacy.cplusplus.com/reference/cstdlib/malloc/?kwmalloc)与[free](https://legacy.cplusplus.com/reference/cstdlib/free/?kwfree)2.2 [calloc](https://legacy.cplusplus.com/reference/cst…

Redis - SpringDataRedis - RedisTemplate

目录 概述 创建项目 引入依赖 配置文件 测试代码 测试结果 数据序列化器 自定义RedisTemplate的序列化方式 测试报错 添加依赖后测试 存入一个 String 类型的数据 测试存入一个对象 优化 -- 手动序列化 测试存入一个Hash 总结&#xff1a; 概述 SpringData 是 S…

浏览器【WebKit内核】渲染原理【QUESTION-1】

浏览器【WebKit内核】渲染原理【QUESTION】 1.浏览器输入一个网址&#xff08;域名之后&#xff09;,浏览器会呈现一个新的页面&#xff0c;中间的过程是怎么实现的&#xff1f; 输入一个网址之后&#xff0c;首先DNS服务器会解析这个域名&#xff0c;将这个域名解析成IP地址&…

SAP 贷项销售订单简介

SAP 贷项销售订单简介 1. 什么是销售贷方销售订单?2. 创建销售贷方销售订单的场景3. 销售贷方销售订单的创建流程直接创建发票---VF01将会计凭证过账到会计核算查看贷项销售订单凭证流查看客户明细---FBL5N贷项后台配置SAP销售贷方销售订单(Sales Credit Memo Request)是销售…

北醒单点激光雷达更改id和波特率以及Ubuntu20.04下CAN驱动

序言&#xff1a; 需要的硬件以及软件 1、USB-CAN分析仪使用顶配pro版本&#xff0c;带有支持ubuntu下的驱动包的&#xff0c;可以读取数据。 2、电源自备24V电源 3、单点激光雷达接线使用can线可以组网。 一、更改北醒单点激光雷达的id号和波特率 安装并运行USB-CAN分析仪自带…

pdf压缩在线免费 pdf压缩在线免费网页版 在线pdf压缩在线免费 pdf压缩工具在线免费

在数字化时代&#xff0c;pdf文件已经成为我们工作、学习和生活中的重要组成部分。然而&#xff0c;体积庞大的pdf文件往往给我们的存储空间、传输速度带来不小的压力。本文将为您揭秘几种简单有效的pdf文件压缩方法&#xff0c;让您轻松应对文件体积过大带来的困扰。 方法一、…

C++从入门到起飞之——const成员函数Date类实现 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 代码链接&#xff1a;这篇文章代码的所有代码都在我的gitee仓库里面啦&#xff0c;需要的小伙伴点击自取哦…

【论文解读】大模型算法发展

一、简要介绍 论文研究了自深度学习出现以来&#xff0c;预训练语言模型的算法的改进速度。使用Wikitext和Penn Treebank上超过200个语言模型评估的数据集(2012-2023年)&#xff0c;论文发现达到设定性能阈值所需的计算大约每8个月减半一次&#xff0c;95%置信区间约为5到14个月…

React中的无状态组件:简约之美

&#x1f389; 博客主页&#xff1a;【剑九 六千里-CSDN博客】 &#x1f3a8; 上一篇文章&#xff1a;【掌握浏览器版本检测&#xff1a;从代码到用户界面】 &#x1f3a0; 系列专栏&#xff1a;【面试题-八股系列】 &#x1f496; 感谢大家点赞&#x1f44d;收藏⭐评论✍ 引言…

OS:处理机进程调度

1.BackGround&#xff1a;为什么要进行进程调度&#xff1f; 在多进程环境下&#xff0c;内存中存在着多个进程&#xff0c;其数目往往多于处理机核心数目。这就要求系统可以按照某种算法&#xff0c;动态的将处理机CPU资源分配给处于就绪状态的进程。调度算法的实质其实是一种…

使用 ComfyUI 跑 SD 图,就两个字:惊艳!

大家好&#xff0c;我是想象&#xff0c;AI 破局 9 颗 AI 之心持有者。ComfyUI 已经出来有一段时间了&#xff0c;一直没有深入去学习过&#xff0c;今天花了点时间跑了一下。体验下来&#xff0c;就两个字&#xff1a;惊艳&#xff01; 这张 3 个小丑的图&#xff0c;很真实吧…

MT6816磁编码IC在自动缩口机中的应用

随着工业自动化的快速发展&#xff0c;各种智能传感器与执行器在制造业中发挥着越来越重要的作用。其中&#xff0c;磁编码IC以其高精度、高可靠性以及优秀的环境适应性&#xff0c;成为了工业自动化控制中不可或缺的一部分。本文将详细介绍MT6816磁编码IC在自动缩口机中的应用…

【数字】三态门,双向端口,HDL描述

#工作记录# 之前工作的时候&#xff0c;负责GPIO的同事被负责人问“三态的en开启的时候是直通的吗&#xff1f;” 他支支吾吾的回答“是的吧”&#xff0c;负责人又问了一句&#xff0c;他就有点不自信了&#xff0c;顺手记录一下这个在SoC设计中非常常见的逻辑。 目录 一、…

Python爬虫 instagram API获取instagram帖子数据信息

这个instagram接口可以通过url链接直接获取相关帖子信息。如有需求&#xff0c;可点击文末链接联系我们。 详细采集页面 https://www.instagram.com/p/CqIbCzYMi5C/ 请求参数 返回示例 { "__typename": "GraphSidecar", "accessibility_caption&qu…

STM32H7串口中断服务函数会禁止中断

STM32H7 在中断服务函数HAL_UART_IRQHandler中&#xff0c;会禁止接收中断 同时也会禁止发送完成中断&#xff0c;调用UART_EndTransmit_IT来进行操作