【MySQL】索引|作用|底层数据结构|常见问题

embedded/2025/3/6 16:17:35/

目录

1.概念

2.为何引入

3.使用

(1)查看索引

(2)创建索引(危险操作)

(3)删除索引(危险操作)

4.使用场景

🔥5.底层数据结构(核心)

🔥6.经典问题


1.概念

类似于目录,能够提高查询的速度,会占用更多的空间,也可能会拖慢增删改的速度


2.为何引入

默认情况下,进行条件查询,就是遍历表,一条一条都带入条件

引入索引,引入额外的数据结构,加快查询的速度,减少遍历表的可能性


3.使用

(1)查看索引

show index from 表名;

(2)创建索引(危险操作)

create index 索引名 on 表名(列名);

(3)删除索引(危险操作)

drop index 索引名 on 表名;

Q1:为啥创建和删除索引都是危险操作?

A:因为这里的操作都会涉及大量的IO,就可能把MySQL主机搞挂了

Q2:那怎么给以及包含大量数据的表添加索引?

A:部署新的服务器,用新的代替旧的数据库

MySQL有类似弱类型语言的特性

Q1:什么是强类型和弱类型语言?

A:弱类型:数据类型转换不那么严格(自动转换类型)

      强类型:不能自动转换类型

eg:

 2 + "3" 如果可以直接相加,那么就是弱类型,否则为强类型

Q2:什么是动态语言和静态语言?

A:动态语言:变量的数据类型在运行时才能确定,即变量在声明时不需要指定数据类型,程序在运行过程中会根据变量被赋予的值来确定其类型

      静态语言:编译时就必须确定

eg:int 类型程序运行过程中,变量的类型通常不能改变,那么就是静态语言,否则就是动态语言


4.使用场景

Q1:如果考虑对数据库的某列/某几列创建索引,需要考虑哪些?

A:

(1)数据量大否?经常对这些列进行条件查询否?

(2)数据库是否经常进行插入,修改操作?

(3)索引可能会占用磁盘空间哦~

(4)查询条件是否经常涉及排序?

如果是非条件查询,或者经常做插入,修改操作,或者磁盘空间不足,就不考虑创建索引了

Q2:什么样的查询,能够命中索引?

大前提:查询的条件和创建的索引的列是匹配的


🔥5.底层数据结构(核心)

查询优化,首先想到哈希表

(1)树

Q1:二叉树 / 二叉搜索树?

A1:二叉树

<1>无序:查找特定节点时,需要遍历所有节点

<2>随机排布:最坏情况直接退化成链表,查找效率低O(N)

二叉搜索树:虽然二叉搜索树对节点的排列有一定规则,即左子树的所有节点值小于根节点值,右子树的所有节点值大于根节点值,但是

<1>如果元素有序:直接退化成链表,查找效率低O(N)

<2>树高度越高,IO操作越多数据库的数据通常存储在磁盘上,而磁盘 I/O 操作的速度相对较慢)

Q2:那 AVL树  /  红黑树呢?

首先我们考虑一下

Q3:为啥TreeMap / TreeSet不用AVL树,而用红黑树呢?

A3:

AVL树:是一个非常严格的平衡二叉搜索树(要求任意节点,左右子树高度差不能超过1)

红黑树:本质是一个没有那么严格的平衡二叉搜索树(要求更宽松)

那么显而易见,当你要求非常严格的时候,随便进行一些增删改操作,都可能会破坏平衡,从而触发旋转(每次旋转,都是有开销的)

总结一下就是:红黑树要求更宽松,触发旋转概率低,虽然没有AVL树那么平衡,但是查找速度并没有差多少

A2:那么对于Q2问题,我们out AVL树,再来看红黑树,红黑树相较于哈希表可以进行范围查询,但是还是不太行

<1> 红黑树还是二叉搜索树,那么树的高度越高,查询效率就越低(数的高度每增加一层,比较次数就增加1,数据库的数据/索引都是保存在硬盘上的,上述每一次比较,就需要一次硬盘IO操作)

<2> 在红黑树中,找到中序遍历的下一个后续元素,不高效,很有可能需要往父节点上一系列回溯,才能找到后继(不过这个好解决,可以通过“线索化”的方式解决,简单理解就是每个节点加上后续节点的指针,但是需要付出更多的存储空间)

(2)再来看查询O(1)的哈希表

虽然哈希表最坏时间复杂度为O(M)(M为链表最大长度,即哈希冲突时,把哈希值相同的元素存储在同一个链表中),但是哈希表有个致命的弱点

只能查询相等情况,无法进行范围查询,这样不适合数据库< >这样的范围查询


上面的结构都不是,那么还有什么呢?
还有B树(N叉搜索树):每个节点上可存储多个元素,延伸出多个子数(非常好的解决了红黑树数据多,数的高度变高的问题)

每个方框是一个节点,每个数字代表一个key(或者是数据库中的一行记录),n个key,n+1个子树

Q1:有人就说他每个节点(方框)中还需要拿着key进行比较,不应该效率很低吗?

A1:其实还是很高效的

1)每个节点上的这些key也是有序排列的,比较的时候可以直接二分查找.

2)B树也会控制,某个节点上保存的key不会太多,如果插入更多的元素,使key变多了,就会是节点分裂出更多树出来.

3)多个数据,都是放在一块连续的存储空间上,进行比较的时候,一次硬盘IO就能读出整个节点,就可以直接完成上述比较.(进行多次比较,实际上只有一次硬盘IO)【硬盘IO操作较内存/CPU操作很慢】


但是最终MySQL索引底层还是没有采用B树,而是B+树

 特点:

(1)N叉搜索树

(2)每个父节点中的元素都会在子节点中以最大值的方式存在

(3)叶子节点这一层通过链表连上

Q:为什么不用B树(B+树好处)?

A:

(1)方便遍历和范围查询

好遍历整个表中的所有数据,也方便进行范围查询,叶子节点 即整个数据的全集+链表的链式结构(B树叶子节点没有这种链式节点)

(2)每一次操作都比较稳定

任何一层操作,最终都是要落到叶子节点来完成的,那么查询任何数据,经历的硬盘IO次数都是一样的,查询操作消耗的时间都是一样的(但是B树可能在非叶子节点就查到了,虽然效率更高,但是有点时候查的快,有的时候慢,IO次数很大影响,不稳定)

(3)叶子节点保存全集,非叶子节点能够在内存中进行缓存(主键索引)

由于叶子节点,是数据的全集,对应的,非叶子节点中,都是重复出现的数据.

就可以把表每一行的数据,最终都关联到叶子节点这一层.非叶子节点中只保存一个单纯的key值即可(id)

数据库每一行有很多列:student(id, name, classld, gender, score.......)

此时,比如使用id这一列来做索引.这里B+树的非叶子节点,都只需要保存一个id这样的值就行了

到了叶子节点这里,每个叶子节点不光要保存id,还要把后续的name,classld 等信息也保存起来.

咱们看到的“表格”只是一个逻辑上的结构

实际上底层的结构,就是这个B+树的结构.

就会按照主键的索引的这个B+树的叶子节点来保存每一行的数据~~

如果你的表,创建主键了,自然是通过你创建的主键的索引的B+树来组织所有行.

如果你没创建主键,mysql其实生成了一个隐藏的主键,按照隐藏主键构造的树来组织.这样组织之后,非叶子节点占用的空间就比较小(非叶子节点只存id)此时,非叶子节点就可以缓存到内存中,这样查询速度又大大提高(当然,这份数据必然要在硬盘上也保存一份,为了提高查询速度,就可以把这部分结构放到内存中

总结就是说B+树的非叶子节点只存储主键,可以缓存到内存,查询速度又大大提高,而B树存储就得把非主键信息也保存起来,占据的空间大


针对哪个列创建索引,就是针对哪个列构建B+树(前提是Innodb存储引擎,不同存储引擎,存储的数据结构不同)

(1)主键索引:叶子节点是带有数据行

如果查主键值,就从树根节点往下层一层一层擦查询

如果查非主键值,遍历链表即可

(2)非主键索引:叶子节点,只有主键Id,如果查到了主键id,那么就要回到主键索引再去查询一次(也就是回标)


🔥6.经典问题

(1)为什么使用索引会加快查询?

(2)能简单说一下索引的分类吗?

(3)创建索引有哪些注意点?

(4)索引哪些情况下会失效呢?

(5)索引不适合哪些场景呢?

(6)索引是不是建的越多越好?

(7)为什么InnoDB要使用B+树作为索引?

(8)为什么不用普通二叉树?

(9)为什么用B+树而不用B树呢

(10)Hash 索引和B+树索引区别

(11)聚簇索引与非聚簇索引的区别

(12)回表了解吗?

回答思路:

(1)全表扫描 与 磁盘IO

(2)功能分 ,底层分 ,存储位置分

(3)合适的列 + 不要太多 + 利用前缀索引和索引列的顺序

(4)

(5)数据少 、频繁更新的列

(6)磁盘空间 + 索引可以提高效率,但是更新不方便了 

(7)二叉平衡树,红黑树,B树比较 

(8)退化为链表,无序遍历全表

(9)结构(链表+子节点最大值)方便遍历和范围查询 + 非叶子节点缓存 + 稳定

(10)

(11) 主键索引 VS 非主键索引

(12)同(11)


http://www.ppmy.cn/embedded/170520.html

相关文章

使用300M带宽是否可以流畅地玩原神

本文来自腾讯元宝 ps&#xff1a;搬家了&#xff0c;需要装个路由器打游戏。 根据搜索结果&#xff0c;300M的网络带宽完全可以满足《原神》的流畅游玩需求。以下是具体分析及优化建议&#xff1a; 一、带宽需求与300M网络的适配性 ​带宽要求较低​ 《原神》作为一款开放世界…

《Python百练成仙》31-40章(不定时更新)

第卅一章 函数结丹def开紫府 罗酆山的鬼门关吞吐着猩红的变量阴风&#xff0c;每个风眼都涌动着作用域混乱的灵力乱流。叶军手握薛香遗留的丹田玉简&#xff0c;玉简表面浮现出残缺的函数符文&#xff1a; def 凝聚金丹(灵气):道基 灵气 * 0.618print(金丹品质) # 作用域外变…

iOSUITableVIewCell 自动化点击埋点

iOS 中&#xff0c;经常要实现UITableVIewCell 点击埋点&#xff0c;这里通过自动化埋点的方式进行实现。 思路&#xff1a;通过运行时hook tableViewCell的 setSelected:animated:方法&#xff0c; 在交换的方法中实现埋点逻辑&#xff0c;并调用原来的实现 cell分类 propert…

【摸鱼指南】--- VSCode 使用 Thief-Book 隐形阅读模式配置教程 程序员必备插件

在代码的理性森林里&#xff0c;摸鱼是调试生活的快捷键 —— 我们用Coffee Break的灵感碎片&#xff0c;编译出更高效率的人生程序真正的效率大师&#xff0c;从不在单一线程里耗尽人生 —— 我们在主进程敲打代码&#xff0c;却在后台线程编译星辰大海 【摸鱼指南】--- VSCod…

【踩坑随笔】`npm list axios echarts`查看npm依赖包报错

npm list axios echarts查看npm依赖包出现以下报错&#xff0c;原因就是包的版本匹配问题&#xff0c;按照提示降axios版本或者自己升找合适的got版本&#xff0c;我这里是选择了降版本。本文记录仅做解决思路参考不一定适配大家的实际情况。 weed-detection-system1.0.0 E:\P…

​DeepSeek:如何通过自然语言生成HTML文件与原型图?

在当今快节奏的开发与设计环境中&#xff0c;快速生成HTML文件或原型图是每个开发者与设计师的迫切需求。虽然DeepSeek无法直接生成图片&#xff0c;但它却能够通过自然语言生成流程图、原型图以及交互式页面&#xff0c;甚至可以直接输出HTML代码。本文将详细介绍如何与DeepSe…

【MySQL】 基本查询(上)

欢迎拜访&#xff1a;-CSDN博客 本篇主题&#xff1a;【MySQL】 基本查询(上) 发布时间&#xff1a;2025.2.14 隶属专栏&#xff1a;MySQL CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 目录 Create 基本知识…

各种传参形式

一、QueryString 前端请求&#xff1a;http://localhost:8080/test/user/find?id26&namezhangsan 后端接收&#xff1a; 1.参数接收&#xff1a; RequestMapping("/find") public void find(String id,String name){... }2.对象接收&#xff1a; RequestMa…