【MySQL初阶】索引与事务

news2024/9/23 23:32:26

1. 索引

1.1 索引基本概念

1.1.1 索引介绍

索引(index):是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或者多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。(具体细节在MySQL进阶章节详细讨论)

在数据库中,使用条件查询时需要遍历表,相当于O(N)的时间复杂度,但是数据库中的数据是存储在硬盘上的,而数据结构中的O(N)是基于内存的角度谈论的,所以硬盘I/O操作遍历操作更加缓慢!

而索引的目的就是提高 “查询效率” ,考虑有一本书,如何能够快速的找到某个章节的页码,这个时候就需要借助目录了 ,而索引的功能就类似于目录,能够提高查询效率。
索引特点

  1. 索引能够加快查询效率
  2. 索引自身也是一定的数据结构组成,也要占据相应的存储空间
  3. 当我们进行新增、删除、修改操作时,不仅需要修改数据,同时也要对索引进行维护管理

总结:因此索引适用的场景需要具备如下两大条件:1、对于存储空间要求不高(存储空间充裕);2、应用场景以查询居多,增加、修改、删除等频率不高

1.1.2 索引相关SQL操作

1.1.2.1 查看索引

语法格式:show index from 表名;

create database blog_mysql_index;
create table t_user(username varchar(20) primary key,`password` varchar(20) not null);
show index from t_user;

结果
image.png
从中我们可以发现表中具有哪些索引,以及哪些列上加上了索引,并且我们可以发现某些约束例如 primary keyunique 等频繁用于查询操作,所以会自动加上一些索引

1.1.2.2 新增索引

语法格式:create index 索引名 on 表名(列名);

create index index_password on t_user(`password`);
show index from t_user;

结果
image.png
从中我们可以发现列password也加上了索引。需要注意的是,创建索引这个操作是一个危险操作!如果表中数据量比较少不会产生问题,但是如果数据量非常庞大,这个时候添加索引就会导致数据结构重新组织,此时就会触发大量的硬盘I/O,数据库服务器很容易就宕机了!

1.1.2.3 删除索引

语法格式:drop index 索引名 on 表名;

drop index index_password on t_user;
show index from t_user;

结果
image.png
同理,删除索引也是一个十分危险的操作!所以尽量在建表之初就确定好哪些字段需要加上索引,而不要等到生产环境上线数据量庞大之后再考虑索引的问题。

但是实际情况由于需求的不断变化,因此很难项目之初就确定好,所以事实上程序员可以通过"曲线救国"的方式处理索引问题,那就是使用新的机器部署数据库,然后建表建索引,逐步将原环境上的数据拷贝到新数据库中,最后用新的机器代替旧的机器就可以了!

1.2 索引底层数据结构

我们需要关心索引底层数据结构的实现,但是我们此处也是简单介绍(详细内容在数据库进阶或者高阶数据结构部分介绍)

前面提到索引本身实际上就是通过额外的数据结构来对表中的数据进行重新组织,那么我们需要考虑使用什么样的数据结构才能在时间、空间上占据优势呢?回忆下我们之前学习的常见数据结构有顺序表、链表、栈、队列、二叉树、哈希表,其中顺序表、链表、栈、队列显然是不适合用于"查找"功能的!而哈希表通过一定时间扩容是可以实现平均时间复杂度为O(1)的,但是哈希表的原理是通过哈希函数计算得出存储下标进行查找,而数据库中很多操作并不是单纯比较相等,例如between and范围比较就无法使用哈希表!所以此处最适合的还是平衡二叉树这样的数据结构(时间复杂度为O(logN))

1.2.1 Java中的ArrayList与LinkedList的区别(常见面试题)

个人整理:

  • 针对ArrayList来说,它的底层实现是数组,具有随机访问特性,随机访问的时间复杂度是O(1),ArrayList尾插/尾删较快(时间复杂度都是O(1)),而在头插/头删/中间节点插入/中间节点删除的平均时间复杂度是O(N)
  • 针对LinkedList来说,它的底层实现是基于链表的,不支持随机访问,进行头插/头删/尾插/尾删的时间复杂度是O(1),中间节点插入/删除的时间复杂度是O(N)
  • LinkedList相较于ArrayList的唯一优势就是可以支持头插头删,因此可以用来轻松实现队列这样的数据结构,除此以外,其他方面大多数都是ArrayList占据优势

常见错误说法

  1. 使用LinkedList占用空间比ArrayList少,因为ArrayList需要预分配好空间大小,容易浪费

    LinkedList中的节点不止存放数据,也需要其他空间用于存放指针域,所以具体的存储空间大小不一定!

  2. LinkedList的遍历速度快于ArrayList

    这也是错误的,链表访问下一个元素需要通过next指针引用,相比于ArrayList的i++操作要多一次访存操作,而i++通常会优化到寄存器

  3. LinkedList的中间节点插入的时间复杂度是O(1)

    正确答案应该是O(N),这是Java的接口设计失误导致的!事实上C++通过迭代器的方式可以实现O(1)时间复杂度,但是Java的插入就是通过遍历找节点的方式

1.2.2 B+树

数据库的索引使用了B+树这样的数据结构,可以说B+树像是专门为数据库这样的场景量身定制的数据结构了,要想理解B+树,我们需要先了解它的前身——B树(也被写做B-树)

1.2.2.1 B-树

B-树:是一颗N叉搜索树(有序),是对于二叉搜索树的扩展,一个节点可以包含N个key值,这N个值又划分出了N+1个区间,如下图所示:
image.png
因此相较于二叉搜索树来说,相同高度的B树可以表示的数据个数更多了,使用B树来查询的时候,如果单论比较次数确定比二叉搜索树多很多,但是关键在于同一个节点的多个key值可以通过一次硬盘IO读取,即使总的比较次数增加了,但是硬盘IO次数少了,显著提高了效率!

1.2.2.2 B+树

B+树:B+树就是在B-树的基础上又做出了改进,同样也是N叉搜索树,每个节点可以包含多个key值,N个key可以划分出N个区间,B+树如图所示:
image.png
B+树的特点

  1. N叉搜索树,一个节点包含N个key值,N个key值划分出N个区间
  2. 每个节点的N个key中,设定一个最大值(或最小值)
  3. 每个节点的N个key值都会在子树中重复出现
  4. 把叶子节点通过 链式结构 相连

B+树的好处

  1. 针对范围查询比较有利,例如查询21 <= age <= 37的所有人群,只需要在B+树中找到叶子节点中的21然后沿着链表往后一直遍历到37即可,得益于该链式结构,就省去了对树进行回溯查找的麻烦了
  2. 查询时间以及IO次数更加稳定,查询所有元素都需要经过根节点直到叶子节点的过程,所以途经的硬盘IO次数是固定的,更加稳定可预测!
  3. 由于叶子节点是数据的全集,因此非叶子节点为了节省内存空间可以只存储对应的key值缓存而不存储具体元素内容,大幅度减少了硬盘IO的次数

2. 事务

2.1 事务的相关概念

事务:事务是一组逻辑操作,这些操作要么全都执行成功,要么全都不执行,事务可以在不同环境中使用,在数据库中就称之为"数据库事务"

2.2 事务基本特性(经典面试题)

事务具有以下四大特性(简称ACID):

  1. 原子性:通过事务将多个操作打包在一起,要么全都执行,要么都不执行
  2. 一致性:相当于原子性的延申,数据库状态总是从一个一致性状态向另一个一致性状态转变的,不可能存在例如转账业务中钱凭空消失这样不科学的情况
  3. 持久性:事务的任何修改操作,都是会持久化存在的(存入硬盘)
  4. 隔离性:多个事务并发执行时,可能会引入一些问题,通过隔离性以及隔离级别的设置可以有效权衡其中的问题

由于数据库是一个基于客户端/服务器(C/S架构)的程序,因此如果多个客户端向服务器提交事务请求,就会出现事务并发执行的情况,如果处理的是同一个数据,就可能会引入问题,下面就来讨论几种常见的问题:
典型bug1:脏读问题
考虑这样一个场景,当前有存在两个事务:事务t1,事务t2,其中事务t1对成绩表中姓名为张三的同学成绩修改为59,此时事务t2并发执行读取同一张成绩表中名为张三的成绩为59,但是此时事务t1发现有一个分数忘记统计了,因此再次修改张三同学的成绩为60,那么现在问题来了,如果事务t2需要根据成绩登记是否挂科,那就出大问题了!即存在两个事务,事务t1修改数据,事务t2读取数据,可能事务t1后续仍需要再次修改数据,t2此时读取的就是一个"脏数据",这就被称为 “脏读问题” ,而解决脏读问题就要对"写操作"加锁,即事务t1在修改数据的过程中,其他事务无法进行读取操作
典型bug2:不可重复读问题
此时我们规定对"写操作"加锁,因此不会出现脏读问题,再次考虑这样一个场景,事务t1对张三的成绩修改为59(此时其他事务无法读取或修改),当事务t1执行完毕后,事务t2读取张三成绩为59,由于t2事务为读取操作,其他事务可以并发执行,此时事务t3修改张三成绩为60,此时问题又出现了!这样的情况就是**“不可重复读”** ,解决"不可重复读"问题的关键就在于给"读操作"加锁,当事务t2读取数据时,其他事务无法修改同样的数据
典型bug3:幻读问题
此时我们规定对"写操作"加锁、对"读操作"加锁,因此不会出现"脏读"、"不可重复读"问题,再次考虑这样一个场景,事务t1读取张三成绩时,事务t2新增了一个学生的成绩,此时由于修改的不是同一个数据所以不会触发"不可重复读"这样的问题,但是对于事务t2来说,整体的数据集合仍然发生了变化,这种情况就叫做 “幻读” ,解决"幻读"问题就需要让事务完全"串行化"执行,即不采取并发执行操作,严格按照执行事务t1,然后再执行事务t2,最后执行事务t3的顺序
总结:上述这些情况是否真的算是"bug"是要针对不同的业务场景进行定义的,归根到底需要根据实际情况判断是追求数据的可靠性还是效率!MySQL针对不同情况为我们提供了不同的隔离级别:

  1. read uncommited:读未提交,并行程度最高、隔离程度最低、数据最不可靠、效率最高,此时可能出现脏读+幻读+不可重复读问题
  2. read commited:读已提交,相当于给"写操作"加锁,此时并行程度降低、隔离级别变高、数据更加可靠、效率降低一些,可能会出现不可重复读+幻读问题
  3. repeatable read:可重复读,相当于给"读操作"加锁,此时并行程度进一步降低、隔离级别进一步升高、数据可靠性进一步提升、效率进一步降低,可能会出现幻读问题
  4. serializable:串行化执行,让所有的事务串行顺序执行,并行程度最低、隔离级别最高、数据最可靠、效率最低

其中MySQL的默认级别为repeatable read可重复读

2.3 事务的基本使用

事务在数据库中可以通过如下几个命令进行操作:

  1. 开启事务

    语法格式:start transaction;

  2. 事务回滚

    语法格式:rollback;

  3. 事务提交

    语法格式:commit;

代码示例

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_user values ('qwe','123');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t_user values ('abc','456');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_user;
+----------+----------+
| username | password |
+----------+----------+
| abc      | 456      |
| qwe      | 123      |
+----------+----------+
2 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t_user;
Empty set (0.00 sec)

mysql> insert into t_user values ('qwe','123');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t_user values ('abc','456');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;
+----------+----------+
| username | password |
+----------+----------+
| abc      | 456      |
| qwe      | 123      |
+----------+----------+
2 rows in set (0.00 sec)

mysql>

image.png
总结:事务在数据库中是一大核心机制,是用来保证数据可靠性的,但是我们往往不会在数据库命令行中开启事务,往往是搭配某一门编程语言在业务中使用的,例如Java的Spring框架就封装了事务管理,当程序抛出异常时可以考虑回滚机制来确保数据的可靠性!事务回滚机制实现方式既跟undo log、redo log有关,也跟背后的存储引擎有关,会在后续数据库进阶章节进行讨论!

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

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

相关文章

Kafka3.x进阶

来源&#xff1a;B站 目录 Kafka生产者生产经验——生产者如何提高吞吐量生产经验——数据可靠性生产经验——数据去重数据传递语义幂等性生产者事务 生产经验——数据有序生产经验——数据乱序 Kafka BrokerKafka Broker 工作流程Zookeeper 存储的 Kafka 信息Kafka Broker 总…

SDWAN组网基于软件,部署灵活且周期

在当今数字化时代&#xff0c;企业网络架构面临着日益复杂的挑战。传统的硬件路由器和专线连接已经不能满足企业对网络带宽、灵活性和安全性的需求。SD-WAN组网作为一种新兴的网络架构技术&#xff0c;通过基于软件的虚拟化和智能路由功能&#xff0c;为企业提供了部署灵活且周…

“警示”!中国大连证监局等七部门紧急发文:防范虚拟货币非法集资!受害人主要为中老年群体?

“国家发行了一种数字货币&#xff0c;一个人只能买一单&#xff0c;一单1000元&#xff0c;到年底时保底能赚回来5万元”……如此拙劣的骗局&#xff0c;6年间让超过1万名受害人上当。 2023年下半年&#xff0c;福建省漳州市公安机关成功打掉这一诈骗犯罪团伙&#xff0c;查明…

一样的代码不同项目跳转页面报404的解决办法

今天收到实施反馈的一个问题&#xff0c;点项目名称跳转项目详情页面时&#xff0c;有的页面跳转显示正常&#xff0c;有的页面跳转报404错误。错误如下&#xff1a; 发现报错的项目都有一个共性就是有特殊字符“[ ]” , 解决的办法就是把带有特殊字符的字段 用 encodeURI()…

HarmonyOS Stage模型基本概念讲解

本文 我们来说harmonyos中的一种应用模型 Stage模型 官方提供了两种模型 一种是早期的 FA模型 另一种就是就是 harmonyos 3.1才开始的新增的一种模型 Stage模型 目前来讲 Stage 会成为现在乃至将来 长期推进的一种模型 也就是 无论是 现在的harmonyos 4.0 乃至 之后要发布的 …

LeetCode.106. 从中序与后序遍历序列构造二叉树

题目 106. 从中序与后序遍历序列构造二叉树 分析 前面讲过根据前序和中序构建二叉树&#xff1a;博客链接 这道题是告诉我们一颗二叉树的后序和中序&#xff0c;让我们根据后序和中序构造出整颗二叉树。 拿到这道题&#xff0c;我们首先要知道中序的后序又怎样的性质&#…

时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测

时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测 目录 时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间…

【GStreamer】GstElement详解:GStreamer 中最重要的对象

1、什么是元素GstElement? 每个解码器、编码器、解复用器、视频或音频输出实际上都是一个GstElement。GstElement可以视为一个黑盒子:例如,对于解码器元素,输入为已编码数据,输出为解码后的数据,解码过程已由GstElement封装好。 2、都有哪些元素GstElement? 2.1 源点…

PG索引分析示例

名Index MethodTable Name约束字段唯一键并发idx_alarm_originator_alarm_typeB-Treealarmoriginator_id "pg_catalog"."uuid_ops" ASC NULLS LAST, type COLLATE "pg_catalog"."default" "pg_catalog"."text_ops"…

2024-02-22(Spark)

1.Spark Application程序入口为&#xff1a;SparkContext&#xff0c;任何一个应用首先需要构建SparkContext对象&#xff0c;两个步骤构建&#xff1a; 第一步&#xff0c;创建SparkConf对象。设置Spark Application基本信息&#xff0c;比如应用的名称AppName和应用运行Mast…

【PX4SimulinkGazebo联合仿真】在Simulink中使用ROS2控制无人机沿自定义8字形轨迹正向飞行(带偏航角控制)并在Gazebo中可视化

在Simulink中使用ROS2控制无人机沿自定义8字形轨迹正向飞行&#xff08;带偏航角控制&#xff09;并在Gazebo中可视化 系统架构Matlab官方例程Control a Simulated UAV Using ROS 2 and PX4 Bridge运行所需的环境配置PX4&Simulink&Gazebo联合仿真实现方法建立Simulink模…

渗流量监测方法有哪些,怎么选择?

在水利工程中&#xff0c;渗流量的监测是至关重要的&#xff0c;因为它直接影响着建筑物的安全和性能。渗流量观测就是观测和分析在水头作用下渗过建筑物和地基的水量。为了准确测量这一数据&#xff0c;我们需要选择合适的监测方法。那么&#xff0c;如何选择渗流量监测方法呢…

Nginx跳转模块location

一.location模块概述 1.定义 location块是server块的一个指令。作用&#xff1a;基于Nginx服务器接收到的请求字符串&#xff0c;虚拟主机名称&#xff08;ip&#xff0c;域名&#xff09;、url匹配&#xff0c;对特定请求进行处理。 2.三种匹配类别 精准匹配&#xff1a;l…

LeetCode刷题---对称二叉树

解题思路: 首先对二叉树进行判空&#xff0c;如果根节点为空&#xff0c;则返回true 接下来对当前节点的左节点和右节点进行判断 1.如果左节点和右节点同时为空&#xff0c;则返回true。 2.如果左节点和右节点只有一个为空时&#xff0c;返回false。 3.如果左节点的值和右节点的…

独家深度 | 一文看懂 ClickHouse vs Elasticsearch:谁更胜一筹?

简介&#xff1a; 本文的主旨在于通过彻底剖析ClickHouse和Elasticsearch的内核架构&#xff0c;从原理上讲明白两者的优劣之处&#xff0c;同时会附上一份覆盖多场景的测试报告给读者作为参考。 作者&#xff1a;阿里云数据库OLAP产品部 仁劼 原文地址:https://developer.ali…

时序预测demo 代码快速实现 MLP效果比LSTM 好,简单模拟数据

【PyTorch修炼】用pytorch写一个经常用来测试时序模型的简单常规套路&#xff08;LSTM多步迭代预测&#xff09; 层数的理解&#xff1a; LSTM&#xff08;长短期记忆&#xff09;的层数指的是在神经网络中堆叠的LSTM单元的数量。层数决定了网络能够学习的复杂性和深度。每一层…

PLC_博图系列☞基本指令“插入输入”

PLC_博图系列☞基本指令“插入输入” 文章目录 PLC_博图系列☞基本指令“插入输入”背景介绍插入输入说明参数示例 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 插入输入 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的博图软件。我并不是专…

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法)

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法) 写上篇文章时测试过程比较乱&#xff0c;写的时候有些地方有点失误&#xff0c;所以重新写了这篇 本文内容均在RGB-D环境下进行程序测试 本文涉及到的动态特征点剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…

Java学习-21 网络编程

什么是网络编程&#xff1f; 可以让设备中的程序与网络上其他设备中的程序进行数据交互&#xff08;实现网络通信的&#xff09; 基本的通信架构 基本的通信架构有2种形式: CS架构(Client客户端/Server服务端) BS架构(Browser浏览器/Server服务端)。 网络通信三要素 IP …

粉色ui微信小程序源码/背景图/头像/壁纸小程序源码带流量主

云开发版粉色UI微信小程序源码&#xff0c;背景图、头像、壁纸小程序源码&#xff0c;带流量主功能。 云开发小程序源码无需服务器和域名即可搭建小程序另外还带有流量主功能噢&#xff01;微信平台注册小程序就可以了。 这套粉色UI非常的好看&#xff0c;里面保护有背景图、…