MySQL 索引事务 · 讨论适合索引的数据结构 · N叉搜索树 · B+树 · 聚簇索引与非聚簇索引 · 事务的四个核心特性

news2024/11/20 4:53:18

  • 一、索引
    • 1.1 概念
    • 1.2 作用
    • 1.3 讨论-如何提高查询的速度
      • 合适的数据结构:
      • 二叉搜索树
      • AVL 树
      • 红黑树
      • 哈希表
      • 以上数据结构的问题:
      • N 叉搜索树
      • B 树
      • B+ 树
    • 1.4 索引的使用场景
    • 1.5 索引的使用
    • 1.6 聚簇索引与非聚簇索引
      • 聚簇索引
      • 非聚簇索引
    • 1.7 索引 - 小结
  • 二、事务
    • 2.1 为什么使用事务
    • 2.2 事务的概念
    • 2.3 事务的四个核心特性

一、索引

1.1 概念

索引是一种特殊的文件,包含对数据表中所有记录的引用指针。
可以对表中的一列或者多列创建索引,并且指定索引的类型,各类索引有各自的数据结构来实现。


1.2 作用

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

1.3 讨论-如何提高查询的速度

MySQL 查找主要是 select.
select 的基本执行过程,遍历表,依次取出每个记录,根据 where 子句的条件,决定这个记录要保留还是过滤。
这样的遍历操作,本身是比较低效的(尤其是数据量很大的情况下).

MySQL 是把数据存储在硬盘上,取出每个记录(意味着都需要访问硬盘),相比之下,就更希望访问硬盘的次数能尽量少,才能节省资源。

现在的数据库,要想提高查找的速度,就需要一定的数据结构来辅助,数据库本质上也是基于数据结构来实现的~


合适的数据结构:

二叉搜索树

我们能最先想到的数据结构就是二叉搜索树

二叉搜索树的特殊结构,让数据在树中的排序是有序的,这样要查找指定数据,就很快很方便。

例如:我们要查询 12,根节点与 12 相比,12 大就进入右子树。
与 15 相比,12 小就进入左子树,最后找到 12 这个元素所在的位置。

但这二叉搜索树的时间复杂度是 O(N)。因为,在最坏的情况下,二叉搜索树可能是一个单枝树。

AVL 树

为了进一步改进二叉搜索树,便引入了 AVL 树。

AVL 树本质上也是一个二叉平衡搜索树,为了防止出现单枝树,会有一个限定条件:| 左子树的高度 - 右子树的高度 | <= 1。从而保证了查找的效率~

但是!如果这样设定,意味着随着插入 / 删除元素的操作,这个 AVL 树的规则就可能被破坏掉,需要随时的检测和调整树的结构,保证整个树始终符合 AVL 树的规则。

调整操作很频繁,此时该树的插入删除操作就导致低效了。插入查找删除的时间复杂度为 O(logN).


红黑树

为了进一步改进 AVL 树,让插入删除查找能比较均衡,不至于插入删除太拉跨。
又引入了红黑树~

红黑树本质上是一个放松了规则的 AVL 树~也是要求让二叉搜索树平衡,但是没要求那么严格。
规则更加宽松,从而保证触发调整整个树的情况没有那么频繁~

虽然查找可能比 AVL 树逊色一筹,但是差异不大,还能保证插入和删除的效率更高。时间复杂度为 O(logN)。


哈希表

还有一个比较厉害的结构,哈希表~
能够做到插入查找删除的时间复杂度都是 O(1).

主要是借助了数组取下标的 “随机访问” 能力,把要保存的 key 转化为数组下标,保存到对应的数组位置上。

可是,哈希表有哈希冲突问题~



以上数据结构的问题:

以上的数据结构,做成索引来使用,是否可行?

哈希表可行又不太行,确实能大大提高查找的速度,但是还是有很大的局限性。
哈希表想要查询,有一个很关键的事情,就是必须要比较 “相等”。哈希查询的时候,只能查某个 key == 的具体值,SQL 中存在的其它查询 < <= > >= 操作不了。

那么红黑树 / AVL 树呢?
也不太行。
红黑树和 AVL 树查找效率直接由树的高度决定了,由于两个数都是 “二叉的”,当元素增加很多之后,高度也会随之增加不少。


N 叉搜索树

其实,MySQL 的索引中最常用的数据结构,就是一个 N 叉搜索树!
用 N 叉的目的就是能够减少高度,高度低了,此时查找的时候的比较次数就少了,磁盘 IO 少了,效率就提高了。

B 树

MySQL 中的索引,其中最常用的结构,就是 B+ 树(一种特殊的 N 叉搜索树)。
想要理解 B+ 树,还需要先了解 B 树(B 树是 B+ 树的前身,B+ 树就是改进版的 B 树)。

B 树的特点

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

B 树的使用
查询元素过程,例如找元素 22

  1. 先拿着 22 去和根节点中元素比较,发现 22 比 30 小,于是从最左侧第一个叉继续向下找。
  2. 再拿 22 去和 “15,20,25” 这个节点对比,此时 22 就在 20 和 25 之间,因此就从这个节点的第三个叉,继续向下走。
  3. 最后再拿 22 去和 “21 22” 这个节点进行比较,找到元素 22 的位置了。

通过 B 树其实能够更好的完成查找过程了,但是还可以进一步改进~
接下来,B+ 树又进一步做出了改进~


B+ 树

B+ 树相比于 B 树,最明显的变化在于两个方面:

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

B+ 树的优势

  • 非常擅长进行 “范围查找”,例如查一个 id<=11 and id>=6,拿着这两个边界值,分别去找这两个边界值的位置。
  • 所有的查询最终都是落在叶子节点上,查询速度还是比较稳定的。
  • 由于叶子节点是数据的全集,因此就可以把叶子节点存储在硬盘上,非叶子节点直接存储到内存中。进一步大大减低了读取硬盘的次数~~ (B+ 树的大杀器!)

1.4 索引的使用场景

要考虑对数据库表的某列或某几列建立索引,需要考虑以下几点:

  • 数据量比较大,而且经常对这些列进行条件查询。
  • 该数据库表的插入操作,对列的修改操作频率比较低。
  • 索引会额外占用磁盘空间。

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

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


1.5 索引的使用

创建主键约束(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;

1.6 聚簇索引与非聚簇索引

聚簇索引

数据本身就是通过 B+ 树的方式来组织的。
每个叶子节点,都直接存在一条完整的记录~

非聚簇索引

先通过一个 “表” 这样的结构,把所有数据都装进去。

再通过 “表” 的下标,和树的叶子节点一一对应。

聚簇索引和非聚簇索引,也不能说谁好谁坏。

聚簇索引更高效~
非聚簇索引产生的硬盘碎片更少~


1.7 索引 - 小结

索引的结构最重要是 B+ 树,但也不是只有 B+ 树。

MySQL 支持多种不同的 “存储引擎”,不同的存储引擎,组织数据使用的数据结构都会存在差异,同时索引结构也会存在差异~


二、事务

2.1 为什么使用事务

准备测试表

drop table if exists accout;
create table accout(
	id int primary key auto_increment,
	name varchar(20) comment '账户名称',
	money decimal(11,2) comment '金额'
);

insert into accout(name, money) values
('阿里巴巴', 5000),
('四十大盗', 1000);

比如说,四十大盗把从阿里巴巴的账户上偷盗了2000元。

-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';

假如在执行以上第一句 SQL 时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少 2000 ,但是四十大盗的账户上就没有了增加的金额。

解决方案:使用事务来控制,保证以上两句 SQL 要么全部执行成功,要么全部执行失败。

2.2 事务的概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。

在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

事务最核心的特点,就是把一系列操作打包到一起~~构成一个整体。这个整体要么全部做完,要么就一个都不做。这也称为事务的原子性。

那么,事务要怎么保证原子性呢?
如果是全部做完那还好,但是做了的中间状态,事务会将此状态偷偷还原回去~(例如:转账500块钱,卡里已经扣钱了,但是钱没有到账;事务就会回滚,把卡里扣的钱再添加回去)。

2.3 事务的四个核心特性

事务除了原子性之外,还有其它特性~
称为事务的四个核心特性:

  1. 原子性
    把一组操作打包在一起,要么全部做完,要么一件不做~
  2. 一致性
    执行事务之前,和执行事务之后,表里的数据都是合理的状态~
  3. 持久性
    事务操作的数据都是直接操作硬盘,硬盘的数据都是持久化存储的。
  4. 隔离性
    多个事务,并发执行的时候,产生的相关问题可以隔离。

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

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

相关文章

小程序-会议OA项目-首页

目录 一&#xff0c;flex弹性布局 什么是flex布局&#xff1f; flex属性 flex-direction属性 学习地址&#xff1a; OA项目搭建以及flex布局演示 二&#xff0c;轮播图--组件的使用 1.先去官方文档中查看轮播图组件如何使 2.在开发工具中查看演示及修改代码 3. 使用mock…

异步通信技术AJAX | 基于JSON、XML的数据交换

目录 一&#xff1a;快速搞定AJAX&#xff08;第二篇&#xff09; 1、JS中如何创建和访问JSON对象 2、基于JSON的数据交换&#xff08;重点&#xff09; 3、基于XML的数据交换&#xff08;了解&#xff09; 一&#xff1a;快速搞定AJAX&#xff08;第二篇&#xff09; 1、…

-source1.5中不支持diamond运算符解决办法

写了几年代码了&#xff0c; 回到最初了遇到了bug了&#xff0c;没有仔细思考&#xff0c;以为很容易&#xff0c;起始走到了误区&#xff0c;有种打了一辈子鹰&#xff0c;最后被麻雀啄了眼 de 感觉 首先来看一下我们的错误信息&#xff0c;如下&#xff1a; [ERROR] Failed…

相机标定笔记(2) -- 标定实践

标定板 为什么需要标定板? 相机标定的第一篇笔记中提到了相机标定所使用的模型&#xff0c;标定算法中我们需要一些可靠的样本点&#xff0c;这些样本点由世界坐标系中的3D点和其在图像上的2D像点组成。用这些2D和3D点对来求解标定参数。为了构建更高精度的3D和2D点&#xff0…

对于系统架构来说,要么进化,要么死亡

在亚马逊云科技年度re:Invent&#xff0c;亚马逊首席技术官Dr. Werner Vogels的主题演讲历来涵盖大量科学和技术领域&#xff0c;今年的演讲也不例外&#xff0c;座无虚席。现在&#xff0c;亚马逊云科技 2022 re:Invent 中国区 recap 正式也开始了&#xff0c;欢迎大家积极参与…

单例模式之饿汉模式懒汉模式

前言 单例模式能保证某个类在程序中只存在唯一一份实例&#xff0c;而不会创建出多个实例&#xff0c;比如 JDBC 中的 DataSource 实例就只需要一个。单例模式具体的实现方式有"饿汉" 和 "懒汉" 两种。 1.饿汉模式&#xff08;类加载的同时创建实例&…

SOLIDWORKS装配体如何快速导出BOM丨慧德敏学

BOM作为产品数据的组成部分&#xff0c;它的重要性不言而喻。采购需要BOM、成本核算需要BOM、领料加工和装配需要BOM、录入ERP需要BOM……可以说&#xff0c;BOM与图纸同样重要&#xff0c;有些产品&#xff0c;可以没有图纸&#xff0c;但是不能没有BOM。借助SOLIDWORKS BOM插…

带你打开C语言的大门

最近有刚开始学习编程的同学问我&#xff1a;“C语言是什么&#xff1f;C语言是怎么来的&#xff1f;C语言用来干什么&#xff1f;”。对&#xff0c;在学习C语言之前&#xff0c;首先了解C语言的发展例程&#xff0c;这应该是每一个刚刚开始学习C语言的人应该了解的&#xff0…

什么是"文件表项"

从Linux的层次角度来说&#xff0c;在用户空间是存在这样的概念的&#xff0c;这个概念是存在内核空间的&#xff0c;而且是针对打开的文件的&#xff01; 内核用三种数据结构来描述一个打开的文件。 数据结构一: 文件描述符表(descriptor table): 每个进程都有它独立的描述符表…

【代码调试】《FSCE: Few-Shot Object Detection via Contrastive Proposal Encoding》

论文地址&#xff1a;https://arxiv.org/pdf/2103.05950.pdf 代码地址&#xff1a;https://github.com/megvii-research/FSCE 论文阅读&#xff1a;https://blog.csdn.net/qiankendeNMY/article/details/128390284 我的配置&#xff1a; Python &#xff1a;3.8(ubuntu18.04) …

小程序发布体验版流程

一、微信开发者工具操作 1. 点击 工具 -> 上传&#xff08;或 直接点击右上角“上传”按钮&#xff09; 【注意】 如果使用的测试 appid 则【上传】按钮不能点击&#xff0c;必须使用真实 appid 2. 如果之前有发布过体验版&#xff0c;会提示继续操作将会覆盖之前的体验版…

MyBatisPlus ---- 基本CRUD

MyBatisPlus ---- 基本CRUD1. BaseMapper2. 插入3. 删除a>通过id删除记录b>通过id批量删除记录c>通过map条件删除记录4. 修改5. 查询a>根据id查询用户信息b>根据多个id查询多个用户信息c>通过map条件查询用户信息d>查询所有数据6. 通用Servicea>IServi…

RK3588平台开发系列讲解(Display篇)开机视频的设置

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、开机视频功能介绍二、使用方法2.1、开启与关闭2.2、视频放置位置2.3、编译结果2.4、视频素材要求2.5、参数控制说明沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍RK3588平台开机视频的使用方法…

ARM64内存虚拟化分析(7)stage2异常处理

当虚拟机访问内存或虚拟机访问寄存器时&#xff0c;由于并没有分配真实的物理地址&#xff0c;并没有建立stage2映射&#xff0c;因此这两种情况会产生stage2异常处理&#xff0c;其中第一种情况为真实的stage2缺页&#xff0c;第二种情况为MMIO处理。同时如果在stage2产生外部…

零膨胀负二项回归案例分析

零膨胀负二项回归分析 计数研究模型中&#xff0c;常用泊松回归模型&#xff0c;但泊松回归模型理论上是要求平均值与标准差相等&#xff0c;如果不满足&#xff0c;则可使用负二项回归模型&#xff0c;负二项回归放宽了平均值标准差这一理论假定。 在实际研究中&#xff0c;…

网络协议类型

网络协议是一组规则、约定和数据结构&#xff0c;用于规定设备如何跨网络交换数据。换句话说&#xff0c;网络协议可以等同于两个设备必须理解的语言&#xff0c;以实现信息的无缝通信&#xff0c;无论其基础设施和设计差异如何。 OSI 模型&#xff1a;网络协议的工作原理 要…

Oracle数据库安装配置详细教程汇总(含11g、12c、18c、19c、21c)

不论你是数据库小白&#xff0c;还是久经沙场的技术专家&#xff0c;你接触和运维Oracle数据库的第一步可能都是安装配置。并且随着软硬件的升级、替换以及业务场景的变化&#xff0c;数据库安装也将是你常常会进行的操作之一。 这里先为大家附上Oracle各版本支持的生命周期及…

阶段性回顾(2)

1. 移位操作符的对象只能是整数&#xff0c;只能对整数的二进制位进行移动。 2. 二进制是数值的一种表示形式。一个整数占了四个字节&#xff0c;相当于一个整数可以用32位二进制位序列表示&#xff0c;那么这时候该如何判断正负呢?规定&#xff1a;这32位二进制序列的头一位如…

第二十二讲:神州路由器OSPF单区域路由的配置

实验拓扑图如下所示 设备 端口 IP 子网掩码 网关 Router-A F0/0 172.16.1.1 255.255.255.0 无 F0/3 172.16.0.1 255.255.255.0 无 Router-B F0/0 172.16.1.2 255.255.255.0 无 F0/3 172.16.2.1 255.255.255.0 无 PC1 172.16.0.2 255.255.255.0 172.1…

解决docker容器因报错无法启动的问题,检查、修复容器错误并重启

问题复现 使用&#xff1a; sudo docker ps -a查看当前的docker容器&#xff1a; 我们想启动name为【docker-mongo】的这个容器&#xff0c;因此要执行 sudo docker start docker-mongo但是执行后仍旧没有重启&#xff0c;大概率是重启的时候报错了&#xff0c;查看日志&a…