MySQL面试篇章——MySQL索引

文章目录

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

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

通过explain分析SQL

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

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

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

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

相关文章

PRC gRPC 框架

概述 RPC主要目的在于让开发者&#xff0c;能够方便的调用远程服务器上的服务&#xff0c;而不需要关注底层的网络通信细节。其是一种进程间通信技术&#xff0c;允许程序在不同计算机上执行代码。 RPC技术主要用于分布式系统、微服务架构以及需要进行跨网络调用服务的应用中…

项目实战二 HIS项目

目标&#xff1a; 项目的操作流程&#xff1a; 开发体系 前端开发&#xff1a;负责页面的编写 HTML CSS JavaScript 后端开发&#xff1a;看不到 摸不着的功能 常用开发语言 PHP JAVA Python 框架 &#xff1a; 半成品 做好的功能模块 版本控制 Git 分布式版本控…

鼠标连点器:是什么?如何用?鼠标自动点击器好用吗?说明书详细版(国内外6款电脑鼠标连点器分享)值得收藏!

知识科普1&#xff1a;鼠标连点器是什么&#xff1f; ⭕答&#xff1a;鼠标连点器&#xff0c;又称为鼠标点击器或自动点击器&#xff0c;是一种能够模拟鼠标点击操作的计算机软件。 鼠标连点器可以根据用户设定的参数&#xff0c;自动进行连续的鼠标点击操作&#xff0c;从而…

SQL labs-SQL注入(三)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; 盲注简述&#xff1a;是在没有回显得情况下采用的注入方式&#xff0c;分为布尔盲注和时间盲注。 布尔盲注&#xff1a;布尔仅有两种形式&#xff0c;ture&#…

【LLM】-05-提示工程-部署Langchain-Chat

目录 1、软硬件要求 1.1、软件要求 1.2、硬件要求 1.3、个人配置参考 2、创建cuda环境 3、下载源码及模型 4、配置文件修改 5、初始化知识库 5.1、训练自己的知识库 6、启动 7、API接口调用 7.1、使用openai 参考官方wiki&#xff0c;本文以Ubuntu20.04_x64&#xf…

微信小程序数组绑定使用案例(二)

一、数组事件绑定&#xff0c;事件传递数据 1.wxml <text>姓名&#xff1a;{{name}} </text> <block wx:for"{{list}}"><button bind:tap"nameClick2" data-name"{{item}}">修改:{{item}}</button> </block&…

想学习Python爬虫的宝子们可以看过来,从基础开始看这一篇文章就够了!

1. 预备知识 学习者需要预先掌握Python的数字类型、字符串类型、分支、循环、函数、列表类型、字典类型、文件和第三方库使用等概念和编程方法。 2. Python爬虫基本流程 a. 发送请求 使用http库向目标站点发起请求&#xff0c;即发送一个Request&#xff0c;Request包含&am…

单调栈(随缘复习到了,顺手刷了)

也是不知道为什么突然又复习到单调栈了&#xff0c;所以顺手刷了三道题&#xff0c;总结一下 P6503 [COCI2010-2011#3] DIFERENCIJA 思路&#xff1a;这题是要求每个子区间里面的最大值和最小值的差&#xff0c;我们一开始想的必然是纯暴力呀&#xff0c;但是一看这数据&#…

自动驾驶系列—智能巡航辅助功能中的车道变换功能介绍

自动驾驶系列—智能巡航辅助功能中的车道中央保持功能介绍 自动驾驶系列—智能巡航辅助功能中的车道变换功能介绍 自动驾驶系列—智能巡航辅助功能中的横向避让功能介绍 自动驾驶系列—智能巡航辅助功能中的路口通行功能介绍 文章目录 1. 背景介绍2. 功能定义3. 功能原理4. 传感…

MySQL聚合函数(DQL)

先看一下我的表内容和数据&#xff0c;再做接下来的例子和讲解 1.聚合函数的基本语法 SELECT 聚合函数&#xff08;表中的某个字段&#xff09;FROM 表名; 2. 常见的聚合函数 举例 1.统计该企业的数量 select count(idcard) from emp; 2.统计该企业员工的平均年龄 select…

SpringBoot缓存注解使用

背景 除了 RedisTemplate 外&#xff0c; 自Spring3.1开始&#xff0c;Spring自带了对缓存的支持。我们可以直接使用Spring缓存技术将某些数据放入本机的缓存中&#xff1b;Spring缓存技术也可以搭配其他缓存中间件(如Redis等)进行使用&#xff0c;将某些数据写入到缓存中间件…

QSqlRelationalTableModel 增删改查

QSqlRelationalTableModel 可以作为关系数据表的模型类&#xff0c;适用于三范式设计的表&#xff0c;主表中自动加载外键表中的名称。本文实现QSqlRelationalTableModel 为模型类&#xff0c;实现增删改查。 目录 0.表准备 1. 构建表格数据 声明变量 表格、数据模型、选择…

全球价值链贸易核算matlab程序(TIVA与WWZ分解方法大全)以及区域表链接方法

数据来源&#xff1a;基础数据来源于世界银行、国家统计局时间范围&#xff1a;2007年数据范围&#xff1a;国家与行业层面样例数据&#xff1a; 包含内容&#xff1a; 全部数据下载链接&#xff1a;https://download.csdn.net/download/samLi0620/89567902

Redis的操作以及SpringCache框架

目录 一.什么是Redis&#xff1f; 二.Redis的相关知识&#xff1a; 三.如何操作Redis&#xff1f; 1&#xff0c;常用命令&#xff1a; 2.Spring Data Redis &#xff08;1&#xff09; pom.xml 配置&#xff1a; &#xff08;2&#xff09;配置Redis数据源&#xff1a; …

麒麟V10安装nginx、mysql报错缺少包:error while loading shared libraries libssl.so.10

背景 启动nginx报错&#xff1a;error while loading shared libraries libssl.so.10 解决 查看nginx启动文件所依赖的动态链接库&#xff08;即共享库或动态库&#xff09; ldd nginx-1.22.1/sbin/nginx离线安装compat-openssl10包 将依赖包麒麟v10安装openssl10依赖包上…

QT6.6+Opencv 4.6.0完成摄像头显示以及捕获照片的功能

效果图提前展示,想试试再往下看: 在网上找了很久QT的摄像头打开方式,成功了,但是捕获照片一直不成功,我不知道是不是qt6版本的原因:这个多媒体窗口我安装没有效果 QT += multimediawidgets之前使用过python的opencv,于是想到可以使用opencv来显示摄像头以及捕获照片。…

C++完整的学生管理系统

实现功能 添加、删除、修改学生为学生添加、删除、修改成绩将数据保存在students.txt和grades.txt里 效果图&#xff08;部分功能&#xff09; 添加学生 添加成绩 源代码 这里就不分多个文件了 编译时在连接器命令行加入以下命令 -stdc11 #include <ios…

极客天成NVFile全闪存储加速千卡AIGC大模型训练平台

01 中国AI算力核心产业现状 随着人工智能技术的快速发展和广泛应用&#xff0c;AI算力已成为推动数字经济和科技创新的关键基础设施。2024年&#xff0c;中国AI算力核心产业规模持续扩大&#xff0c;在全球AI发展格局中占据重要地位&#xff0c;中国AI算力核心产业规模达到约…

LangChain的数据增强

吾名爱妃&#xff0c;性好静亦好动。好编程&#xff0c;常沉浸于代码之世界&#xff0c;思维纵横&#xff0c;力求逻辑之严密&#xff0c;算法之精妙。亦爱篮球&#xff0c;驰骋球场&#xff0c;尽享挥洒汗水之乐。且喜跑步&#xff0c;尤钟马拉松&#xff0c;长途奔袭&#xf…

Spring事务(1)

目录 一、事务回顾 1、什么是事务&#xff1f; 2、为什么需要事务&#xff1f; 3、事务的操作 二、Spring 中事务的实现 1、代码准备&#xff1a; &#xff08;1&#xff09;创建项目 spring-trans&#xff0c;引入 Spring Web&#xff0c;MyBatis&#xff0c;MySQL等依…