MySQL经典面试题:谈一谈对于数据库索引的理解~~

news2024/11/26 3:40:12

文章目录

  • 什么是索引?
  • 为什么要引入索引?
  • 引入索引的代价
  • 操作索引的SQL语句
  • 索引背后的数据结构
    • B树
    • B+ 树
  • 回顾思考
  • ☁️结语


什么是索引?

数据库中的索引,就相当于一本书的目录。
什么是书的目录?相信大家都并不陌生,一本书最前面的几页,一般就是目录,如果你想找到某个章节,你就可以通过目录快速定位过去。
同理,在数据库中通过索引,我们就可以快速找到要查询的数据(索引的作用)。

为什么要引入索引?

在数据库中 select 这样的查询操作,默认是按照“遍历”的方式,来完成查询的。

比如,指定where语句,条件查询,遍历每一行,把这一行数据代入到条件中,看是否成立,成立就留下,不成立就pass掉。

遍历的复杂度是O(n),但是要注意,此处的每一次取一行,都是要读硬盘的!!虽然也是O(n),但是它和内存操作的O(n)是有本质区别的~~在硬盘上进行操作,比在内存上进行操作,速度要差了好几个数量级呐!!差距还是非常大的。通过一行一行遍历,这样的操作,就会很慢,非常消耗数据库的资源,这也就使数据库能处理的请求量更少了。因此,为了加快查询速度,就需要在数据库中建立索引。
所谓的“索引”就相当于是在数据库中,构建一个特殊的“目录”(一系列特定的数据结构,在硬盘上的),通过这样的数据结构,加快查询的速度,尽可能避免对数据库的遍历操作。

大家应该都用过everything这个软件吧,everything其实就是针对硬盘文件,进行搜索的,那为啥它能查找的这么快?这是因为everything提前把硬盘上的文件数据,构成了特定的数据结构,查询的时候不必遍历了,直接就能进行快速查询。

引入索引的代价

虽然索引这么好,但是也付出了一点的代价。

  1. 引入索引,需要消耗额外的存储空间。
    举个例子来方便理解:假设你有一本词典,词典特别厚(上千页),查词的时候肯定要通过目录来查,这个时候,你仔细观察一下目录的页数,词典的目录 可能就是厚厚的一打。印目录也需要纸张呀~

  2. 引入索引之后,确实能提高查询的效率,但是可能会影响到增删改的效率。有时候会变慢,比如在进行增删改的时候,需要同步的更新维护索引,更新过程肯定是有额外的开销的;有时候会变快,比如通过条件判断的方式来删除,而删除操作的背后就有查找操作,而索引可以帮我们快速定位;有的时候没有变化。

由此看来,索引这个东西,有利有弊,但是即使如此,我们在实际开发中,还是比较鼓励使用索引的。

原因:

  1. 存储空间(硬盘)往往不是主要矛盾,大不了多加几个。
  2. 索引对于增删改也不一定都是负面影响,也可能会触发一些正面效果,另一方面,很多业务场景,查询的频率比增删改要高很多…

操作索引的SQL语句

  1. 查看索引
show index from 表名;

MySQL会给主键自动生成索引,不需要我们手动创建。
所谓的“索引”是按照 列 的方式来创建的,可以给某个列创建索引,只有在对这个列进行条件查询的时候,索引才能够生效,才能够提升查询速度~~
一个表允许有多个索引(一本词典可能有多种目录(拼音目录、部首目录、笔画目录…))
除了主键之外,unique 和 foreign key 也会自带索引~~这也很容易理解,在子表中插入\修改,需要查询父表;在父表中进行修改\删除,也需要查询子表

  1. 创建索引
create index 索引名 on  表名(列名);

创建索引也是一个“危险操作”
如果是针对空表,或者表中的数据比较少(几千、几万…),此时创建索引就谈不上危险不危险。
一旦表的数据量比较大,千万级别…此时创建索引操作,就可能会触发大量的硬盘IO,直接把机器就搞的卡死住了,所以一定要在最初创建表的时候,提前规划好这个表要有哪些索引。

如果就是要创建呢?
可以再申请一台机器,将旧库的数据导入到新库当中,等数据全都导入完毕之后,再切换我们访问数据库的那个程序,让他从访问旧库,变成访问新库。

  1. 删除索引
drop index 索引名 on 表名;

它只能删除,我们自己创建的索引,不能删除MySQL自动生成的(主键、外键、unique…)。

删除索引也是危险操作!!
要能够慎重对待~

索引背后的数据结构

所谓的“构建索引”其实就是引入一些数据结构,对数据进行存储,从而提高查找的速度。

二叉搜索树和哈希表,都不适合给数据库做索引

  1. 二叉搜索树,最大的问题在于“二叉”要保存的元素多的时候,就会使整个树的高度变的比较高,一旦高度高了,比较次数就会增多~~要知道这是在硬盘上进行的比较,每多比较一次,都是很伤的!!

  2. 哈希表,最大的问题在于,只能进行“相等”查询,无法进行 > < 这样的“范围查询”,也无法进行like模糊查询。哈希表是要通过哈希函数,把查询的key映射成数组下标,不是说key1 < key2 => hash(key1) < hash(key2);

B树

B+树,为数据库量身定制的数据结构。
要想了解B+树,首先要对B树有一定的了解,B树,也可以写作B - 树(这里 - 不是减号,而是连接符)

B树其实就是N叉搜索树,每个节点,可以有多个子树了(树的度是N)
这样就可以降低树的高度了~每个节点上就不是存储一个key值了,而是多个了

在这里插入图片描述

某个节点上保存了N个key就能延伸出N+1个子树了,此时,进行查询的时候,针对每个节点,都需要比较多次,才能确定下一步走哪个区间~~

有人就要问了此时虽然高度降低了,但是每个节点的比较次数变多了,真的能比二叉树有优势吗?
答:其实优势还是很大的!!每个节点,访问的时候是一次硬盘IO就可以了~~
和某个节点进行比较的时候,是先一次硬盘IO,把所有的这个节点上的内容都读取出来,接下来的比较就都是在内存中进行的了

注意:这里的主要目的,不是为了减少比较的次数,而是要减少硬盘IO的次数

B+ 树

B+树是针对B树做出的进一步改进的数据结构~~

在这里插入图片描述

B+树也是N叉搜索树

  1. 不同于B树,B树是有N个key,划分成N+1个区间,B+树是有N个key,划分出N的区间~

  2. 父节点中的key值,会在下面的子节点中再次出现(以子节点中的最大值的身份)~~ 重复出现的做法,看起来好像是浪费空间,实际上非常有用~~所有叶子结点,就构成了整个树数据的全集!!

  3. B+树把叶子节点,像链表一样首尾相连了~~此时,进行“范围查询”就会非常方便!!

B+ 树的优势:

  1. N叉搜索树,高度比较低,此时硬盘IO次数就比较少
  2. 叶子结点是全集,并且用链表结构连接,非常便于进行范围查询~~
  3. B+树,所有的查询都是要落到叶子结点上完成的~~并且任何一次查询,经历的IO次数和比较次数都是差不多的,查询的开销是稳定的~~(稳定其实是一个很大的优势!!稳定意味着,成本是容易被预估出来的~)
  4. 由于B+树,叶子结点是全集,非叶子结点上不必存储“数据行”(数据库中的“表”只是一个逻辑上的结构,在物理上并非是一个真正意义的表~物理上就是通过B+树这样的结构来组织的~),只需要存储索引列的key即可。这使得非叶子结点,消耗的空间较少,甚至这样的数据可以直接全部都加载到内存中~~这样又能进一步减少硬盘IO的次数~~

回顾思考

  1. 索引是啥,它是解决啥问题的?
  2. 索引付出了什么代价?
  3. 如何使用 sql 操作索引,是否又注意事项?
  4. 索引背后的数据结构? => B+树的特点和优势?

解答:

  1. 索引是啥,它是解决啥问题的?
    索引相当于书的目录,能够提高查询的速度

  2. 索引付出了什么代价?

    1. 需要更多的存储空间
    2. 可能会影响增删改的效率(不一定会影响)
      整体来说,索引利大于弊,日常开放中还是会经常使用的
  3. 如何使用 sql 操作索引,是否又注意事项?

    1. show index from 表名;
      查看索引(主键、外键、unique会自动生成索引)
    2. create index 索引名 on 表名(列名);
      给指定列创建索引
    3. drop index 索引名 on 表名;
      删除索引
    4. 索引是针对列来创建的,后续查询的时候,查询条件使用的列和索引列匹配,索引才能生效,才能提高效率。
    5. 针对一个比较大的表,创建\删除索引,是非常危险的,可能会除法大量的硬盘IO,把机器高挂了
  4. 索引背后的数据结构? => B+树的特点和优势?

    1. 特点:
      1. N叉搜索树,每个节点上包含N个 key,划分出N个区间
      2. 每个父节点中的元素,都会下沉到子节点中,作为该子节点中最大值的角色来存在
      3. 叶子结点这一层就构成了数据集合的全集
      4. 使用类似于链表这样的结构,把叶子节点串起来
    2. 优势
      1. N叉搜索树,高度比较低,降低了硬盘IO次数
      2. 范围查询非常方便和高效
      3. 所有的查询都落到叶子节点上,开销非常稳定,容易预估成本
      4. 叶子节点存储数据行,非叶子节点只存储索引列的key值,非叶子节点占据空间小,可以加载到内存中,进一步减少查询时IO的访问次数。

☁️结语

请给自己些耐心,不要急于求成。
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!


最后的最后,推荐一个数据结构可视化网站,很方便、很好用,很直观。
点击直达 => 数据结构可视化网站


都看到这里啦!真棒(*^▽^*)

可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家

如有纰漏或错误,欢迎指正


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

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

相关文章

【数据结构】二叉树专题

前言 本篇博客我们来看一些二叉树的经典题型&#xff0c;也是对上篇博客的补充 &#x1f493; 个人主页&#xff1a;小张同学zkf ⏩ 文章专栏&#xff1a;数据结构 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 ​ 目录 1.单值二叉树 …

算法day24

第一题 1047. 删除字符串中的所有相邻重复项 解法&#xff1a;利用数组来模拟一下栈 对于上述字符串转换为字符数组&#xff0c;通过模拟栈的操作来解决这道题&#xff0c;当栈为空时下一位字符直接进行入栈操作&#xff0c;当当前数组中要入栈的字符和栈顶的字符相同时&#x…

刷代码随想录有感(98):动态规划——爬楼梯

题干&#xff1a; 代码&#xff1a; class Solution { public:int climbStairs(int n) {if(n 1)return 1;if(n 2)return 2;vector<int>dp(n 1);dp[0] 0;dp[1] 1;dp[2] 2;for(int i 3; i < n; i){dp[i] dp[i - 1] dp[i - 2];}return dp[n];} }; 其实就是斐波…

重生之我要精通JAVA--第八周笔记

文章目录 多线程线程的状态线程池自定义线程池最大并行数多线程小练习 网络编程BS架构优缺点CS架构优缺点三要素IP特殊IP常用的CMD命令 InetAddress类端口号协议UDP协议&#xff08;重点&#xff09;UDP三种通信方式 TCP协议&#xff08;重点&#xff09;三次握手四次挥手 反射…

素颜个人引导页源码

源码介绍 素颜个人引导页源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果预览 源码下载 素颜个人引导页源码

Spring boot实现基于注解的aop面向切面编程

Spring boot实现基于注解的aop面向切面编程 背景 从最开始使用Spring&#xff0c;AOP和IOC的理念就深入我心。正好&#xff0c;我需要写一个基于注解的AOP&#xff0c;被这个注解修饰的参数和属性&#xff0c;就会被拿到参数并校验参数。 一&#xff0c;引入依赖 当前sprin…

如何用群晖当异地组网服务器?

在当今信息化时代&#xff0c;远程通信成为了企业和个人之间不可或缺的一部分。特别是对于跨地区的通信需求&#xff0c;一个可靠的异地组网服务器是必不可少的。而群晖&#xff08;Synology&#xff09;作为一款功能强大的网络存储设备&#xff0c;可以被用作办公室或家庭的异…

力扣1712.将数组分成三个子数组的方案数

力扣1712.将数组分成三个子数组的方案数 确定左边界的值 然后二分求右边界的范围 右边界处的前缀和满足 2*s[i] < s[r] < (s[n] s[i]) / 2 int s[100010];const int N 1e97;class Solution {public:int waysToSplit(vector<int>& nums) {int n nums.siz…

Vue12-计算属性

一、姓名案例 1-1、插值语法实现 1、v-bind v-bind的问题&#xff1a; 所以&#xff1a;v-bind是单向绑定。 2、v-model 解决v-bind的问题。 3、输出全名 方式一&#xff1a; 方式二&#xff1a; 需求优化&#xff1a;全名中的姓氏&#xff0c;只取输入框中的前三位&#xf…

MATLAB数学建模——数据拟合

文章目录 一、简介二、多项式拟合&#xff08;一&#xff09;指令介绍&#xff08;二&#xff09;代码 三、指定函数拟合&#xff08;一&#xff09;指令介绍&#xff08;二&#xff09;代码 一、简介 曲线拟合也叫曲线逼近&#xff0c;主要要求拟合的曲线能合理反映数据的基本…

AtCoder Beginner Contest 357 A~E(F更新中...)

A.Sanitize Hands(模拟) 题意 有 n n n个外星人排队对手消毒&#xff0c;其中第 i i i个外星人有 H i H_i Hi​只手需要消毒&#xff0c;已知消毒液共能使用 M M M次&#xff0c;每次可以对一只手消毒&#xff0c;问&#xff1a;总共有多少个外星人的全部手都完成消毒了。 分…

Docker高级篇之Docker网络

文章目录 1. Docker Network简介2. Docker 网络模式3. Docker 网络模式之bridge4. Docker 网络模式之host5. Docker 网络模式之none6. Docker 网络模式之container7. Docker 网络模式之自定义网络模式 1. Docker Network简介 从Docker的架构和运作流程来看&#xff0c;Docker是…

normalizing flows vs 直方图规定化

normalizing flows名字的由来 The base density P ( z ) P(z) P(z) is usually defined as a multivariate standard normal (i.e., with mean zero and identity covariance). Hence, the effect of each subsequent inverse layer is to gradually move or “flow” the da…

【报文数据流中的反压处理】

报文数据流中的反压处理 1 带存储体的反压1.1 原理图1.2 Demo 尤其是在NP芯片中&#xff0c;经常涉及到报文的数据流处理&#xff1b;为了防止数据丢失&#xff0c;和各模块的流水处理&#xff1b;因此需要到反压机制&#xff1b; 反压机制目前接触到的有两种&#xff1a;一是基…

【Python入门与进阶】Anaconda环境配置

目录 1.Conda换源 2.pip换源 3.环境管理 4.可视化界面完成上述操作 1.Conda换源 1.1.打开Anaconda Powershell Prompt 1.2.在界面中输入以下命名&#xff08;加入清华源并设置搜索优先级&#xff09;&#xff1a; conda config --add channels https://mirrors.ustc.edu.…

android集成百度文心一言实现对话功能,实战项目讲解,人人都能拥有一款ai应用

大家好&#xff0c;今天给大家讲解下如何实现一个基于百度文心一言的app功能&#xff0c;app内部同时集成了讯飞的语音识别。本文适用于有android基础的小伙伴阅读&#xff0c;文章末尾放上本项目用到的全部实例代码&#xff0c;在使用前请务必看完本文章。 先来给大家看看效果…

鲜为人知的英伟达创始人:早早退出,身价不如黄仁勋零头

内容提要 普里姆因为婚姻纠纷等个人生活的干扰无法专注在工作上&#xff0c;在成立公司的10年后&#xff0c;也就是2003年宣布退休离开英伟达&#xff0c;并在2006年出售剩余的所有英伟达股份&#xff0c;过上不与外界联系、离群索居的生活&#xff0c;在家中鼓捣着如何“拯救…

【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境

【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境 大家好 我是寸铁&#x1f44a; 总结了一篇【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境✨ 喜欢的小伙伴可以点点关注 &#…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

transformer - 注意力机制

Transformer 的注意力机制 Transformer 是一种用于自然语言处理任务的模型架构&#xff0c;依赖于注意力机制来实现高效的序列建模。注意力机制允许模型在处理一个位置的表示时&#xff0c;考虑输入序列中所有其他位置的信息&#xff0c;而不仅仅是前面的几个位置。这种机制能…