【MySQL】一文掌握索引事务的核心内容

前言

本文介绍了MySQL的索引和事务,如果你恰好对这方面的知识不了解的话,那么来看看本文吧!!


一、索引

1.1 概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。(具体细节在后续的数据库原理课程讲解)

通俗的讲:我们一本书,最开始有目录,通过目录可以看见相关的情况,比如可以看见有多少个章节,每个章节的大概内容,mysql 的索引也是差不多的。


1.2 索引的作用及核心思想

  • 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。
  • 索引所起的作用类似书籍目录,可用于快速定位、检索数据。
  • 索引对于提高数据库的性能有很大的帮助。

那这个索引有什么用呢??

我们都知道mysql查找主要是select

select基本执行过程,遍历表,依次取出每个记录,根据where字句的条件,决定这个记录要保留还是过滤,像这样的遍历操作,本身是比较低效的(尤其是数据量很大的时候)

为什么特别低效呢?因为把数据存储在硬盘上的,取出每个记录(这个操作都意味访问硬盘) 相比之下,我们更希望访问硬盘的次数尽量少。


怎么样才可以更高效的访问呢?如何提高查找速度,这里就要提到数据结构了,数据库本质上也是基于数据结构来实现的,想要提高查找速度,就需要一些的数据结构来辅助:那么我们要来挑选一个

1.二叉搜索树

二叉搜索树,时间是O(N),因为要一个个遍历,还是比较低效的,虽然说可以提高速度,但是具体提高多少还是要看那一颗树了,也有可能是单支树,为了进一步改进引入AVL树

2.AVL树

AVL本质上是一颗二叉平衡搜索树,什么叫做平衡呢?
平衡:对于这个树的任意节点来说,左子树的高度减去右子树的高度绝对值小于等于1
避免出现单支树,保证了查找效率

但是这里会有新的问题出现: 如果这样设定的话,意味着随着插入/删除的元素的进行,这个AVL树规则就可能被破坏掉,就随时的调整树的结构~,保证这个树始终符合AVL树的要求。
(调整操作就非常频繁了,此时这个树插入删除操作就低效了)

3 .红黑树

为什么进一步的改进AVL树,让查找,插入,删除能比较均衡又引入了红黑树,

本质上是一个放松规则的AVL树,也要求让这个二叉搜索树平衡,但是没有要求的那么严格。(这里的规则更宽松,从而就能保证触发调整的情况没有那么频繁) ,虽然查找可能比AVL树稍微逊色一点,但是差异不大,同时能够保证插入和删除效率更高,在之间取得一个平衡的点,因为它的插入查找删除都是O(logN)

4.哈希表

哈希表相对于上面介绍的数据结构,还是要强一点的,它的插入查找删除时间复杂度,都是O(1),主要是借助了,数组去下标的“随机访问能力”(非常高效),把保存的key转换成数组下标,保存到对应的位置上,下次查找也是先把key转成下标,直接去下标就可以了~

  • 虽然说哈希表有哈希冲突问题但是我们也有解决办法:
  • 1)挂链表的方式
  • 2)往后找一个空位的方式(线性探测 / 二次探测)

如果索引使用哈希表来做,可以行吗?

 可行:确实可以提高查找速度
 不可行:其实还存在很大的局限性

为什么说不可行:

一个哈希表要想查询,有一个关键的事情,必须要比较“相等”,哈希表的查询时候,只能查某个key==具体值,这样的情况~但是我们SQL中存在很多的查询, 比如一些条件,正因如,我们在标准库的HashMap的时候,要求key的类型,必须提供"比较相等(equals)”这样的方法实现。

5.红黑树

红黑树就是普通二叉树的升级版,其实也不太可行,红黑树查找效率直接就是由树的高度决定的~(高度也就相当于比较次数),由于树是二叉的,当元素增加很多之后,高度也会随之增加不少,红黑树坏事就在于它是二叉树,抛开二叉树不说进行范围比较还是可以的


其实,mysql的索引最常用的数据结构,其实就是一个N叉搜索树!! 每一个有很多子节点,使用N叉的目的就是能减少高度~ 高度低了,此时查找时候的比较次数就少了,磁盘io也少了,效率就高了 。

6.B树

MySQL中的索引,其中最常用的结果是B+树(B+树就是一种特殊的N叉搜索树)
要想理解b+树,先了解B树(B树是B加树的前身,B+树就是改进版的B树)
B树也是一个N叉搜索树~(B树在有的资料叫做 B-树,就是B树,不叫B减树

来大概看看B树是什么样的:

在这里插入图片描述

B树的特点:

  1. N叉搜索树,每个节点可能会包含N个子树
  2. 每个节点上存在多个值
  3. 保证类似“二叉搜索树”一样的规则(左子树,小于根节点,小于右子树

来一个流程:
例如:查找一个元素,22
先拿22去跟根节点比较,根节点之间,发现22比30小,于是从最左侧第一个叉出来,继续往下找
在这里插入图片描述
在拿22去和15,20,25这个节点对比,我们就知道22在20 和25之间
在这里插入图片描述
因此就从这个节点的第三个叉,继续往下走,接下来拿22去和“21 ,22 ” 这个节点进行比较,查找和二叉搜索树差不多,不过我们把高度变低了,B树当我们的索引其实挺合适的,不过我们还可以改进空间,引入B+树。

7.B+树

B+树做出的改变:这里大家看见看见重复了最后也是一个8,大家别急着说浪费空间,可能也是一个改进
在这里插入图片描述
我们继续完成这树:下面使用链表连接

这个B+树和B树相比,最明显的变化就是两个方面:

  1. 非叶子节点的值,可能会存在重复的,就可以保证最终的叶子节点的一层,就是完整的数据集合~
  2. 通过类似于链表这样的方式,把所有的叶子节点按照顺序,连接起来~

B+树的优势:

  1. 非常擅长“范围查找” 例如查一个ID<=11 and ID >=6

    我们拿着这两个边界值去,分别去找两个边界值的位置比如 6 9,然后遍历链表比较方便 :

    那么我们和B树相比,我们来看看B树的弊端: 比如我们两个数,我们不知道哪里是中间元素在这里插入图片描述

  2. 所有的查询最终都是落在叶子节点上,查询速度是比较稳定的.

    比如B树,我们找找40 45 一个40 一开始马上找到,一个45还要遍历就比40要慢,所以不太稳 定,我们B+树的查询还是比较稳定的。
    在这里插入图片描述

  3. 由于叶子节点是数据的全集,因此可以把叶子节点存在硬盘上,非叶子节点直接存在内存中,又大大降低了读取硬盘的次数吗,怎么理解这个话呢?

我们要知道每一个节点不只就一个记录,可能一行里面有许多信息,如果像B树那样全部存在硬盘上,才存的下,相比B+树,我们只在它的叶子节点存全部信息,非叶子节点只存部分信息,这个时候非叶子节点整体的空间就少了很多了,在内存也可以存下来,这个是B+树的大杀器,我们把ID这样的重要信息存在内存,把全部信息存在硬盘,这样我们的重复还是很有必要的


1.3 使用场景

我们使用索引,最主要的还是来查询,要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外的磁盘空间
  1. 当然不是说我们什么时候都可以使用索引,新增删除修改多,查找比较少,索引就不太合适,但是这种 查多,修改少的场景我们也是非常常见的,因此索引的用处还是特别多的,像我们去一个论坛,我们大多数是在查看,而不是去进行修改 删除操作。
  2. 索引本身也是占剧一定空间的,如果磁盘空间充裕那还好,如果磁盘空间非常紧张,那就不太适合使用索引了。
  3. 建立索引,是指定某个列来建立的,就是要求这个索引列,得是“区分度比较大的”,这个时候才适合制作索引~~ 类似于 自增主键 ,这种就比较时适合做索引,类似于“性别”这样的列就不合适做索引 ,因为要么男,要么女,区分度很小,非常不适合做索引

满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。

反之, 如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。


1.4 使用

创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。

  • 查看索引

show index from 表名;

案例:查看学生表已有的索引

show index from student;

  • 创建索引

    对于非主键、非唯一约束、非外键的字段,可以创建普通索引

create index 索引名 on 表名(字段名);

案例:创建班级表中,name字段的索引

create index idx_classes_name on classes(name);

  • 删除索引

drop index 索引名 on 表名;

案例:删除班级表中name字段的索引

drop index idx_classes_name on classes;

其实上面这些没有太多好讲的,我们来看一个其他的知识点


聚簇索引 和 非聚簇索引

主要描述是mysql底层是如何组织数据的

  • 聚簇索引: 数据本身就是通过B+树的方式来组织的,比如B+树的每一个叶子节点存一个完整的记录就是聚簇索引
    在这里插入图片描述

  • 非聚簇索引: 先通过 一个"表”这样的结构,把所有的数据都装进去~
    在这里插入图片描述
    然后我们B+树还存在只是这个时候不存全部数据了,而是存行号,我们通过B+树,1 这条记录在表中的行号对应的是 王五 清华大学 这个条数据,这就叫做非聚簇索引
    在这里插入图片描述
    这个两种索引,不能说谁好谁坏,只能说看应用的场景, 一般聚簇索引要更加高效一点,为什么呢,因为非聚簇索引还要查一次表,不过非聚簇索引产生的硬盘垃圾更少~

索引的结构最主要的还是B+树,但是不是说只有B+树,MySQL支持多种不同的“存储引擎”,组织数据使用的数据结构都会存在差异吗,同时索引结构也会存在差异~


二、事务

2.1 介绍事务

事务其实不仅仅是数据库中的概念,是属于计算机中一个非常广泛的概念,主流数据库也是都是对事务是有一定的支持的。

我们来举个事务的列子,倒垃圾:

家里有垃圾桶 ,套一个塑料袋,垃圾往袋子里面丢,垃圾满了就可以把这个袋子一拎,就可以丢了,我们的每一步是有过程的

  1. 把装满的袋子拎出来
  2. 再套一个新袋子

这两步我们应该一气呵成,这样方便我们接下来的使用, 我们把多个动作,打包成为一个整体的操作,就称为事务!

上面的这样的操作其实没有一起完成没有关系,我们来看一下下面一个 银行转账:

如果这个操作没有一起,那么会产生尴尬的情况!这样的打包一起也是事务!


事务特点有下面3个情况:

1.原子性

事务最核心的特点,就是把一系列操作打包在一起 ,构成一个整体,这个整体,要么全部完成,要么一个不做,不会出现“做了一半,另一半没有做的情况”,这个情况称为 原子性

思考:这个原子性是如何保证的呢???

A转账B 500

  1. A的账户减500
  2. B的账户加500

如果我们在转账执行第1步成功了,开始执行第二步的时候,数据库 或者程序崩溃那么怎么办呢?

其实我们这里有个叫做回滚(rollback)的一个机制,就是要么一样不做,指的不是说真的没做,而是把做了的中间状态,给偷偷还原回去了, 回滚针对每个进行的操作,都记住干啥了~保证不会出现中间状态,

2 .一致性

执行事务之前,和 执行事务之后,当前表里面的数据都是合理的状态~~ 比如不可以出现-400这样的数字

3.持久性

事务操作的数据都是直接操作硬盘,硬盘的数据都是持久化存储的.(数据只要改了,那么就会一直存在,就不会说重启了就没了)

4.隔离性

一个事务的执行不能被其他的事务执行,即一个事务的内部操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>