HR眷恋的数据库高频考题之一 —— 索引

本篇会加入个人的所谓鱼式疯言

❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言

而是理解过并总结出来通俗易懂的大白话,

小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.

🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!

前言

在前几篇文章中,我们主要讲解了关于 数据表的CRUD 的各种 基础操作 , 而本篇文章我们讲继续学习 数据库的索引

索引 很重要, 是我们面试中 HR经常问到的很经典``,很热门`的考题之一 。

所以小伙伴们一定要好好理解消化本篇文章哦,说不定你下一次面试的时候,就会遇到这样的考题哦 💖 💖 💖 💖

目录

  1. 索引的初识

  2. 索引的不足

  3. 如何使用SQL 来操作索引

  4. 索引背后的数据结构

一. 索引的初识

1. 索引的概念

索引的英文名: index

小伙伴们是不是很眼熟,是的,这个英文单词本质上就是我们 Java数组 中常用的 下标 的含义 。
除了这个含义,本质上我们还有一个含义就是 : 目录
是的,索引的认识 ,本质上就是相当于我们 新华词典上的目录

但是索引是针对数据库中的 某一列 来说的,就是说每个不同的列 可以构建 不同的索引
就是我们的新华词典的目录一样,有我们的 拼音目录部首目录生僻字目录 等...

居然 索引 相当于 目录 , 我们设想下目录的作用不就是 方便我们查找吗? 那么数据库索引是不是也是如此呢 ? ? ?

2. 索引的作用

索引作用就是 加快我们查找速度,提高我们 查找的效率
因为索引是针对 某个列 来说的,所以小伙伴使用时,你要查询的 哪个列 要和 索引 对应的 相统一,才能触发 索引 的作用,
对于数据库本身来说,索引是有 自动创建手动创建

<1>. 自动创建索引

当我们 创建表 时, 凡是以下三种情况就会创建 我们的索引

  1. 主键索引
sql 复制代码
-- 创建该表
 create table if not exist   my_table (id int  primary key , name varchar(49));

-- 查看表结构
desc  my_table;

-- 查看该表的索引
show index from my_table;

像上面这样我们创建 主键 时,就会自动生成该 字段的索引

这里的 show index from my_table;

小编在下面会在 . 如何使用 SQL 来操作索引 中,给小伙伴们细细道来哦 ❣️ ❣️ ❣️ ❣️

小伙伴们只需要知道,这是我们 查询表中索引 的 SQL语句即可哦

  1. unique 索引
sql 复制代码
-- 删除前面的表
 drop table if exists my_table;


#  创建该表
create table my_table ( id  int unique , name varchar(45));

-- 查看表结构
 desc my_table;


-- 查看该表中的索引
 show index from my_table;
  1. 外键索引
sql 复制代码
-- 创建父表
create table father ( father_id int primary key , name varchar(23));


-- 创建子表并进行外键连接
 create table son ( son_id  int  primary key   , name varchar(38), 
 father_id int , foreign key(father_id) references  father(father_id));


-- 查看索引
 show index from son;

有个问题想问 小伙伴,为什么我们在创建 主键unique外键 时, MySQL会自动添加索引呢 ?

我们可以回归到 unique主键 自身的作用来看 : 他们有一个 共同的作用 就是保持该 字段的数据唯一 的,
为了保证 唯一性, MySQL的底层是需要 进行查询 ,从查询中返回该数据 是否唯一 , 居然用到了查询,那么我们就需要 索引来加快我们的查询速度
还有一个就是我们的 外键 , 外键的作用就是保证 子表的该字段数据父表的范围 中, 父表的该外键字段数据必须 含有子表 的数据范围

当我们建立好 外键连接 后

如果需要对子表的数据进行 增加修改,MySQL自身就会 查询一遍父表 ,看 子表要新添加的数据在子表中 是否存在 ,存在就添加,不存在就无法添加 。
同样当我们需要对父表的数据进行 删除修改 时, 我们就要 查询子表的数据 ,如果子表中含有该数据,我们就不能对父表和子表中都含有的数据进行 删除和修改
居然都要涉及到 查询 , 所以我们MySQL就会对外键自动添加 索引,以此来加快 查询速度 。

关于程序员自身如何 手动创建索引 ,小编在这里就 不剧透 哦,在如何使用SQL 来操作索引 会详细解释哦 💞 💞 💞 💞

鱼式疯言

关于自动创建索引,小编有两点想和小伙伴分享:

  1. 索引是针对表中 某一个字段 而言的,当我们需要对 某个字段查询 时要和对应 字段索引 相统一
  1. 像我们 主键外键unique 修饰的字段, 他们都涉及到 查询, MySQL都会自动创建 索引 益于 查询速度的加快 。
  2. MySQL 自动创建的索引 是 不允许删除 的,小编下面也会细细讲解哦

二. 索引的不足

世间万物,凡事都 有好的一面 和 不好的一面 ,居然索引能 加快我们的查询速度 ,必然也要付出一定的代价

不足一

创建索引 时,需要占用 额外的空间.

这就好比我们的新华词典中的目录一样,我们目录也是占用 纸张页数的

不足二

可能会加快 数据表增删改 操作的 执行速度 。
可能会 减慢 数据表的 增删改 操作的 执行速度 。
也可能 不会影响 数据表的 增删改 的操作的 执行速度 。

鱼式疯言

小编在这里解释下哈 💥 💥 💥 💥

sql 复制代码
delete from 表名  set 列名=新数据 where 条件 ;
  • 像我们这里涉及到 查询操作 的时候,就会 加快执行速度

  • 像有些 删除 或者 修改 了数据之后, 我们对应的索引就 需要调整 , 就有可能会 触发 多次 硬盘IO , 减慢 执行速度。

  • 也有可能和我们索引无关的,就 不影响 我们的执行速度

三. 如何使用SQL 来操作索引

1. 查看当前索引

<1>. SQL语句

sql 复制代码
show index from 表名 ;

<2>. 语句分析

查询索引的关键标识是 show index 后面再配上表名即可 。

<3>. 注意事项

虽然和我们查询 数据库 和 数据表 中的 show 很像, 但是我们需要注意一点是 查询当前 数据库和数据表 是需要 再后面加上 S 的 ,而我们的 索引 是 不需要的

2. 创建索引

在上面的内容中,小编主要讲解了 数据表中 自动创建索引 的内容, 而这里要重点我们程序员本身用 SQL 手动创建索引 的方式

<1>. SQL语句

sql 复制代码
create index 索引名  on 表名(列名); 

<2>. 语句分析

需要创建索引 时, 标识关键字 create index 跟上索引名, 并用 on 来连接。
这和我们 创建表创建数据库 不同的是, 因为我们的索引是针对 而已的,所以我们需要用 on 指定对应 表中的列 来 创建 我们的索引 。

<3>. 注意事项

对于索引本身来说是 利大于弊 的 ,但是对于 手动创建索引 来说,其实有些情况是一种 危险 的操作 。
当数据表是 表或者是 只有 几千行几万行 数据时, 我们再 创建索引的 影响不大的 。
但是当我们数据表中存放上 百万行千万行数据 时, 如果再去 创建索引 时,就会触发 硬盘上大量的 IO , 这样会导致整个 数据库 直接挂掉 。
这样的操作就相当于给正在飞的飞机换发动机 ,这是一个 非常危险 的操作 。

所以当我们需要在数据表中存储的 数据规模非常大 的时候, 就需要对数据库的用 哪些列 创建索引, 有一个具体的 规划和预测 ,以免出现 大量数据 ,当 创建数据库 就会 触发 大量硬盘 IO

3. 删除索引

<1>. 语句分析

sql 复制代码
drop index 索引名 on 表名;

<2>. 语句分析

删除索引 的标志关键字就是 drop index ,因为 索引名不同表的可能一样 , 所以我们需要注意后面用 on 来指定指定 对应的表

<3>. 注意事项

这里需要 注意的一点 就是 :

  1. 小伙伴们手动自己创建的 索引 是可以删除 的,但是 MySQL自动生成的索引 是 无法删除的
  1. 删除索引也是一个 非常危险 的操作,和我们上面的 创建索引 一样,当 数据规模很大 时,这种操作是相当于给 正在飞的飞机上拆发动机

所以小伙伴一定要考虑好 何时删除索引 才是解决之道

四. 索引背后的数据结构

1. 索引背后数据结构的探讨

小伙伴可以猜想下我们索引背后是哪有一种神秘的 数据结构做支持 ,才能达到像 书的目录 一样 , 能 加快 我们 查询的速度

说到小伙伴学过的关于有查找功能的数据结构无非就是 以下两个 :

二叉搜索树 : 我们知道对于 普通的二叉搜索树 来说, 一般都不是平衡二叉树,这样就会导致我们的时间复杂度最坏能达到 O(N) , 对于硬盘来说 O(N) 级别的时间复杂度 可 比 内存中 O(N) 的时间复杂度还大的多很多 。

并且对于二叉树来说 , 如果数据规模很大,树的高度就 很高 ,经历的 硬盘 IO 次数也是 很大 的 , 就会大幅度 减慢 查询速度 。

所以二叉搜索树是不适合做我们数据结构背后的索引

哈希表 : 哈希表的本质是讲一组 key 值 通过 哈希函数 转化为我们 数组的下标 进行存储 ,但是这个也只能 查找某个值 ,对于 我们 SQL x > m 这种范围查找, Hash(x) > Hash(m) 这种 结果并不成立 的 。 所以也不适合用作我们 索引的数据结构 。

那么会是哪种数据结构呢? 答案就是我们的 B + 树 ...

可以这么说 ,我们的 B + 树 是专门为 数据库索引 量身定做的一种特殊的数据结构

2. B+ 树的特点

  1. B+树 本身是一个N 叉搜索树, 一个节点上 有 N 个度
  2. 每个节点都有 多个 K 值, 而有 多少个 K 就把 划分了 多少段区域 ,就有多少个 子节点 。
  3. K 为父节点 ,下放到 子节点 时,是作为该节点的 最大的 K
  4. B+ 树的叶子节点 ,是该 数据表的全集 ,并且 通过 链式结构 来连接每一个叶子节点
  5. 叶子节点存储的数据表中的每一行 , 非叶子结构存储的是 索引列 的K .

3. B+ 树的优势

  • 因为 B+ 树 本身是 N叉树 ,所以有效的 降低了 树的高度,从而 减少 经历 硬盘IO 次数。

  • B+ 树 中每个节点存储的是多个K , 先让 硬盘读取该节点 ,然后在内存进行比较 ,这样就可以有效的 减少 经历硬盘IO的次数。

  • 叶子节点因为是 数据的全集 ,这样经历硬盘的次数和比较的次数相当,能够更稳定预估结果

  • 一个个叶子节点 是由 链表 来连接的,当我们 查找某个范围 时, 就可以利用链式结构 快速查找 该范围的区间 。

  • 叶子节点 是存储数据表中的 每一行 ,但非叶子节点存储的是 索引列的 K , 就可以 减少 每个节点的 存储空间 ,甚至让内存来读取数据 。

鱼式疯言

在这里小编最后想提及一个小概念

  1. 对于我们平常 学习的 数据库数据表 ,以及本篇文章学习的 索引 , 本质上只是一种逻辑结构,而不是我们真正意义上的 表 或者 目录 .

  2. 真正提的上 物理结构 的,那便是我们的 数据结构 , 所以说我们的数据库的这种 逻辑结构 的背后是需要数据结构这样的物理结构作为支持的

  3. 数据库本身就是一种 "客户端" - "服务器" 结构的程序 。

总结

  • 索引的初识 :

我们知道对于索引就是一本书特殊的 "目录" ,能加快查询的速度

但需要注意的是,我们的索引是针对列而已的,我们指定列查询一定要和索引列一一对应才能, 索引的查询效果才能生效。

并且MySQL会对 主键,unique , 外键 的自动生成索引, 且不能删除 。

  • 索引的不足 :

唯一两点不足就是 :

  1. 占有额外的空间

  2. 可能会影响增删改的速度

  • 如何使用SQL 来操作索引

1.查看当前索引

sql 复制代码
show index from 表名;
  1. 生成索引
sql 复制代码
create index 索引名 on  表名(列名) ;
  1. 删除索引
sql 复制代码
drop index 索引名 on 表名 ;

注意要点:

  1. 生成索引和删除索引在大规模的数据库来说,是危险操作。

  2. 删除索引只能删除自己创建的索引,不能删除MySQL生成的索引。

  • 索引背后的数据结构

本身就是一颗B+树,是一颗为索引而量身定做的一种数据结构。

如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正
希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 💖 💖 💖

相关推荐
sdaxue.com1 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)2 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长2 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_2 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui12 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记3 小时前
MHA binlog server
数据库·mysql
lovelin+v175030409663 小时前
安全性升级:API接口在零信任架构下的安全防护策略
大数据·数据库·人工智能·爬虫·数据分析
DT辰白4 小时前
基于Redis的网关鉴权方案与性能优化
数据库·redis·缓存
2401_871213304 小时前
mysql高阶语句
数据库·mysql