「MySQL」索引事务

🎇个人主页:Ice_Sugar_7
🎇所属专栏:数据库
🎇欢迎点赞收藏加关注哦!

索引&事务

  • 🍉索引
    • 🍌特点
    • 🍌通过 SQL 操作索引
    • 🍌底层数据结构
  • 🍉事务
    • 🍌特性

🍉索引

在数据库中,进行条件查询的时候经常需要遍历表。
我们知道遍历一遍的时间复杂度是O(N),不过由于数据库是把数据存储在硬盘上的,硬盘上的 IO 比内存中的慢很多,即此处的 O(N) 比我们通常说的 O(N) 要慢很多
因此,我们可以给数据库引入索引,提高查询的速度

🍌特点

  1. 加快查询的速度
  2. 索引本身是一定的数据结构,也要占据存储空间
  3. 当我们进行新增、删除、修改的时候,也需要对索引进行更新,这就有额外的开销

由索引的特点,我们不难得出它适用的场景:

  1. 对于存储空间要求不高的场景(或者存储空间比较充裕)
  2. 需要进行较多的查询操作,而增加、修改、删除的操作次数相对较少的应用场景
    (这种“读多写少”的场景是比较常见的,很多的 web 程序(网站)都是如此)

🍌通过 SQL 操作索引

1. 查看索引
查看某个表是否有索引,以及有几个索引

show index from 表名;

这里有一个结论:MySQL 中的主键、unique 和外键都会自动生成索引

比如我们现在创建一个学生表,它有两列:id 和姓名,其中 id 是主键,姓名用 unique 约束。然后查看它的索引:

create table student(id int primary key,name varchar(20) unique);

查看索引
在这里插入图片描述

可以看到 id 和 name 都是这张表的索引

从上面的例子我们也可以看出,一个表可以有多个索引,而每个索引都是根据某个具体的列来展开的,这样,后续按照这个列来查询的时候,就能提高效率


2. 创建索引

除了主键、外键和 unique 作为索引,我们也可以自己创建索引:

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

举个例子,假设刚才创建的学生表没有设置主键和 unique,那么查看索引的结果集就为空
然后我们手动创建索引:

create index id_index on student(id);
create index name_index on student(name);

再次查看索引:

在这里插入图片描述

注意:创建索引也是一个比较危险的操作。如果表中没有数据或者数据比较少,此时创建索引没问题;但如果表中已经有很多数据,此时创建索引,就会触发大量的硬盘 IO,很可能就把数据库给搞挂了


3. 删除索引

drop index 索引名 on 表名
drop index id_index on student;
drop index name_index on student;

注意:删除索引也是一个危险操作


🍌底层数据结构

数据库的索引使用 B+ 树作为数据结构,其实 B+ 树就是针对数据库这个场景量身定制的
要理解 B+ 树,得先了解 B 树(B-树)

B 树是一个 N叉搜索树,是在二叉搜索树的基础上进行拓展,它一个节点上可能包含 N 个值,这 N 个值划分出(N + 1)个区间
举个例子,现在根节点有三个值,分别为30、40、50
那就会划分出4个区间,分别为:小于30的区间、30到40之间的区间、40到50之间的区间和大于50的区间,然后子节点又会继续划分出多个区间

在这里插入图片描述
从 B 树的特性可以看出,同样高度的树,它能表示的元素相比于二叉搜索树来说多了很多,所以使用 B 树来查询的时候,比较的次数比二叉搜索树多
比如上面的例子中,要找46的位置,就得先和30比较,比30大,那就得跟40比,比40大,就要跟50比,比50小,就说明46在40到50这个区间

当然这不意味着 B 树不如二叉搜索树,恰恰相反,因为同一个节点的 key 值都是一次硬盘 IO 就能读出来的。即使总的比较次数多了,但 B 树硬盘 IO 次数少了,而一次硬盘 IO 相当于内存中进行 1w 次比较,所以 B 树完全薄纱二叉搜索树

而 B+树则是在 B 树的基础上,又进行改进
同样是 N 叉搜索树,每个节点包含多个 key,不过 B+树只划分出 N 个区间,少了最右边的区间

还是举个例子

在这里插入图片描述
我们可以看到,B+树是没有大于15的区间的,这样就只有两个区间。对于小于8的区间,子节点中包含8;对于8到15的区间,子节点包含15。
也就是说每个节点的 key 会体现在子节点中,直到叶子节点。这样的话叶子节点就包含所有数据(数据全集),这样的好处在于查询过程中经过的硬盘 IO 次数是一样的(B树的硬盘 IO 有时多,有时少),查询时间是稳定

然后叶子节点之间用链式结构相连(图中红色箭头)
用链式节点的好处在于可以进行范围查询,比如现在要找出4到10这个区间,只需找出4,然后沿着链表往后遍历找到10就 ok 了

反之,如果没有链式结构,那就可能需要反复对树进行回溯,这样就很麻烦(比如找完4之后要回到上一层,然后去找10)

当然,因为现在是在讲数据库,所以关于B+树更详细的讨论,我们放到以后再讲


🍉事务

很多时候对数据库进行的多个操作,我们期望能够“打包”到一起,共同执行

先来看一个经典场景:转账
有一个账户表,记录用户 id、姓名和余额
在这里插入图片描述
假如现在张三向李四转账500,那就需要两条SQL语句:

update account set balance = balance - 500 where name = '张三';
update account set balance = balance + 500 where name = '李四';

但是有一个问题,就如果执行完第一个SQL之后,在执行第二个SQL前,数据库挂了,那等到数据库恢复的时候,就会发现张三钱少了,但是李四的钱没有多!

所以需要想个办法,使得即使数据库真挂了,也不会有这样的负面影响

事务就可以做到,它可以保证上述这两个SQL,要么都成功执行,要么都不执行
说是说“不执行”,但实际上还是执行了,只不过在数据库恢复的时候,把数据也还原回去了。这种还原的机制称为回滚机制事务的原子性本质上就是依托回滚
为什么能回滚呢?因为数据库通过日志(undo log 和 redo log)把之前的数据记录下来了,也就是写到文件里。即使数据库挂了,但是日志已经记录下来了,等到数据库重启之后,读取之前的日志,看看是否有那种执行了一半的事务,如果有,就会把这前面的操作进行回滚,恢复到没有操作之前的状态

🍌特性

谈到事务,我们就需要讲到它4个核心的特性:

  1. 原子性(最重要的特性)
    通过事务,把多个操作打包到一起
  2. 一致性
    相当于是原子性的延伸,就是当数据库中间出问题了,不会出现上述那种“钱凭空消失”这种异常情况;另一方面,通过约束来避免数据出现一些非法的情况
  3. 持久性
    对事务进行的任何修改,都是持久化存在的(因为是写入硬盘的),无论是重启程序,还是重启主机,修改都不会丢失(因为数据库本身就是为了持久化存储)
  4. 隔离性
    多个事务并发执行的时候,可能会带来一些问题,通过隔离性对这些问题进行权衡(就是看你是希望数据尽量准确,还是速度尽可能快)

前三个都比较好理解,我们主要来讲隔离性
先理解一个概念——“并发”
并发是计算机领域中一个很大的话题,后面所讲的“多线程”,其实就属于是“并发编程”中的一种典型实现方式

数据库是客户端——服务器结构的程序,一个服务器可能会涉及到多个客户端。那么,如果有多个客户端同时向数据库服务器发起事务请求,这个时候就叫作“并发执行事务”
如果这多个事务修改的是不同的表,那么问题不大;而如果是修改同一张表,就可能产生一些 bug

典型 bug 1:脏读问题
有两个事务1、2,其中事务1修改了某个数据,但此时事务还没有提交,而事务2读取了这个数据(事务2会多次读取这个数据),此时事务2读取到的数据,很可能是一个脏数据,因为事务1后续可能还要再次修改这个数据。
这就导致事务2第一次读取到的数据是A,但是第二次读取到的数据是B,前后不一致

解决脏读问题的核心思路就是降低事务的并发程度
要解决的话就得给写操作加锁,加锁意味着在释放锁之前,这个数据是无法访问的(写的时候不能读)


典型 bug 2:不可重复读
这个有点像脏读,但这是在写操作加锁的前提下导致的问题
还是以上面的脏读为例,此时来了一个事务3,它在事务2读数据的时候,修改了数据,这样也会导致事务2前后读取的数据不一致

要解决这个问题,就需要给读操作加锁,即读的时候不能写


典型 bug 3:幻读
现在有事务1、2,其中事务1修改数据,然后提交,事务2开始读数据。此时来了一个事务3,它新增了一些其他的数据,这就可能导致事务2两次读取的结果集(就是查询的时候,有多少行)不同

要解决幻读问题,就要串行化:不再进行任何并发,让每个事务都是串行执行的(执行完第一个,再执行第二个,再第三个…)

不过其实上述这三种情况,不算真正的 bug,主要还是得看实际的场景,要看你的场景是更关注数据的准确性,还是更关注效率


MySQL在配置中,提供了“隔离级别”的选项,我们可以根据需要,调整隔离级别,用来应对不同的情况

  1. read uncommitted:读未提交,此时并行程度最高,隔离程度最低,数据是最不靠谱的,可能出现脏读、不可重复读和幻读
  2. read committed:读已提交,相当于给写操作加锁。并行程度降低了,隔离程度提高了,效率会降低一些,此时可能会出现不可重复读和幻读
  3. repeatable read默认的隔离级别:可重复读,相当于给写操作和读操作加锁了。并行程度进一步降低,隔离程度进一步提高。此时仅可能出现幻读
  4. serializable:串行化,让所有事务都是串行执行。此时并行程度最低,隔离程度最高,效率最低,但是数据是最靠谱的

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

芒果YOLOv8改进130:Neck篇,即插即用,CCFM重构跨尺度特征融合模块,构建CCFM模块,助力小目标检测涨点

芒果专栏 基于 CCFM 的改进结构,改进源码教程 | 详情如下🥇 💡本博客 改进源代码改进 适用于 YOLOv8 按步骤操作运行改进后的代码即可 即插即用 结构。博客 包括改进所需的 核心结构代码 文件 YOLOv8改进专栏完整目录链接:👉 芒果YOLOv8深度改进教程 | 🔥 订阅一个…

微服务(基础篇-006-Docker安装-CentOS7)

目录 05-初识Docker-Docker的安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p46&spm_id_frompageDriver&vd_source60a35a11f813c6dff0b76089e5e138cc 0.安装Docker 1.CentOS安装Docker 1.1.卸载(可选) 1.2.安装dock…

UE5启用SteamOSS流程

一、安装OnlineSubsystemSteam插件 1、在UE里安装OnlineSubsystemSteam 2、设置默认开始地图 3、设置DefaultEngine.ini文件: 打开项目根目录/Config/DefaultEngine.ini文件 打开官网的配置说明 复制并粘贴到该文件中 4、设置运行模式 5、测试 确保Steam平台已…

electron打包桌面版.exe之vue项目踩坑(vue3+electron 解决打包后首页打开空白,打包后路由不跳转及请求不到后端数据等问题)

vue项目https://www.qingplus.cn/components-web/index打包桌面版问题集合 一、静态资源加载问题 npm run electron_dev桌面版运行后页面空白,内容未加载。 填坑: 打包配置要用相对路径 vite.config.ts文件中的base要改成./,之前加了项目…

postcss安装和使用(详细)

1,安装postcss: 在此之前需要安装有node.js 第一步 命令:cnpm install postcss-cli -g 第二步 命令:cnpm install postcss –g 推荐内容 2,下载autoprefixer插件,并创建postcss.config.js文件并写入配置代码 autoprefixer插件…

习题2-5 求平方根序列前N项和

本题要求编写程序,计算平方根序列 的前N项之和。可包含头文件math.h,并调用sqrt函数求平方根。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中按照“sum S”的格式输出部分和的值S,精确到小数点后两位。题目保证计算结果不…

西南交大swjtu算法实验3.3|穷举法

1.实验目的 通过具体例子学习排列这种典型的穷举算法的求解过程以及程序框架,分析其算法的求解过程,以及如何设计穷举法解决实际问题。通过本实验,理解穷举法的特点以及实际应用中的局限性。 2.实验任务 有n (n>1)个任务需要…

HarmonyOS 应用开发之FA模型与Stage模型应用组件

应用配置文件概述(FA模型) 每个应用项目必须在项目的代码目录下加入配置文件,这些配置文件会向编译工具、操作系统和应用市场提供描述应用的基本信息。 应用配置文件需申明以下内容: 应用的软件Bundle名称,应用的开发…

使用Python实现对word的批量操作

Python在平时写写小工具真是方便快捷,Pyhon大法好。以下所有代码都是找了好多网上的大佬分享的代码按照自己的需求改的。 调用的库为Python-docx、win32com、PyPDF2、xlwings(操作excel)。 因为公司的任务要对上千个word文件进行批量操作&a…

JAVAEE之网络编程

1.网络编程 网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。 当然,我们只要满足进程不同就行; 所以即便是同一个主机,只要是不同进程&am…

【论文阅读】ELA: Efficient Local Attention for Deep Convolutional Neural Networks

(ELA)Efficient Local Attention for Deep Convolutional Neural Networks 论文链接:ELA: Efficient Local Attention for Deep Convolutional Neural Networks (arxiv.org) 作者:Wei Xu, Yi Wan 单位:兰州大学信息…

C语言-文件操作

🌈很高兴可以来阅读我的博客!🌟我热衷于分享🖊学习经验,🏫多彩生活,精彩足球赛事⚽🔗我的CSDN: Kevin ’ s blog📂专栏收录:C预言 1. 文件的作用 …

基于spark的大数据分析预测地震受灾情况的系统设计

基于spark的大数据分析预测地震受灾情况的系统设计 在本篇博客中,我们将介绍如何使用Apache Spark框架进行地震受灾情况的预测。我们将结合数据分析、特征工程、模型训练和评估等步骤,最终建立一个预测模型来预测地震造成的破坏程度,同时使用可视化大屏的方式展示数据的分布…

docker-compose运行springinitializr用来创建springboot2

前言 spring initializr官方的地址是: https://start.spring.io/ ,这是一个用来创建springboot脚手架的一个工具,但是目前这个工具已经更新到springboot3,而我还没学springboot3,目前还想继续创建springboot2,我就想能…

Unity类银河恶魔城学习记录11-10 p112 Items drop源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili ItemObject_Trigger.cs using System.Collections; using System.Collecti…

Gin入门指南:从零开始快速掌握Go Web框架Gin

官网:https://gin-gonic.com/ GitHub:https://github.com/gin-gonic 了解 Gin Gin 是一个使用 Go 语言开发的 Web 框架,它非常轻量级且具有高性能。Gin 提供了快速构建 Web 应用程序所需的基本功能和丰富的中间件支持。 以下是 Gin 框架的一些特点和功能: 快速而高效:…

设计模式-结构型-享元模式Flyweight

享元模式的特点: 享元模式可以共享相同的对象,避免创建过多的对象实例,从而节省内存资源 使用场景: 常用于需要创建大量相似的对象的情况 享元接口类 public interface Flyweight { void operate(String extrinsicState); } 享…

信息工程大学第五届超越杯程序设计竞赛(同步赛)题解

比赛传送门 博客园传送门 c 模板框架 #pragma GCC optimize(3,"Ofast","inline") #include<bits/stdc.h> #define rep(i,a,b) for (int ia;i<b;i) #define per(i,a,b) for (int ia;i>b;--i) #define se second #define fi first #define e…

【C++庖丁解牛】自平衡二叉搜索树--AVL树

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1 AVL树的概念2. AVL…

Solidity Uniswap V2 Router swapTokensForExactTokens

最初的router合约实现了许多不同的交换方式。我们不会实现所有的方式&#xff0c;但我想向大家展示如何实现倒置交换&#xff1a;用未知量的输入Token交换精确量的输出代币。这是一个有趣的用例&#xff0c;可能并不常用&#xff0c;但仍有可能实现。 GitHub - XuHugo/solidit…