MySQL--索引和事务

目录

1.索引

1.1 前言

1.2 索引的相关操作

1.2.1 查看索引:show index from 表名;

1.2.2 创建索引:create index 索引名 on 表名(列名);

1.2.3 删除索引:drop index 索引名 on 表名;

1.3 索引的实现原理

1.3.1 引入B+树

1.3.2 简单了解B树

1.3.3 认识B+树

1.3.3.1 B+树的特点

1.3.3.2 B+树的优点

2.事务

2.1 事务的概念

2.2 事务的使用

2.3 事务的特性

2.3.1 原子性

2.3.2 一致性

2.3.3 持久性

2.3.4 隔离性

2.3.4.1 脏读

2.3.4.2 不可重复读

2.3.4.3 幻读

2.3.4.4 隔离级别


1.索引

1.1 前言

当数据库使用select查询时,会先遍历表,把当前的行带入条件中,看条件是否成立,成立就保留,不成立就跳过。这样的查询遍历成本非常大,时间复杂度起码是O(n)。数据库的数据是存储在硬盘上的,每一条记录都要访问硬盘,开销会特别大。

因此引入了索引这样的方便查询的概念,它会避免表的遍历,加快查询速度。

索引能够提高查询速度,但也有代价:

  • 占用更多空间。生成索引需要用到一系列数据结构和一系列数据,来存储到硬盘空间中
  • 会降低插入修改删除的速度。每次数据的更新都要将索引一同更新,存在额外时间开销。

在开发过程中查询的频率比插入修改删除的频率高得多。

1.2 索引的相关操作

1.2.1 查看索引:show index from 表名;

当表中的列存在unique、主键和外键的时候,系统会自动生成索引,因为unique和主键都是唯一值,需要频繁地进行查询操作,外键约束的子表需要不断查询父表对应的字段,父表的记录删除时也需要查询子表中有没有引用该记录。因此这三个约束会自动生成索引。

每个表可以有多个索引,就像字典中有多种目录(部首目录、拼音目录、偏旁目录……)有多个索引代表有多种查询方式,但是消耗的资源也相对多一点。

1.2.2 创建索引:create index 索引名 on 表名(列名);

创建索引是非常危险的操作。创建索引需要针对现有的所有数据进行大规模整理,如果是一个空表或存放的数据不多,创建索引还是可以的,但是如果表放的数据很多,很容易会把服务器很卡住,(要是非得在这种情况下创建索引,可以在搞一个机器,部署同样的mysql服务器,创建同样的表,把表上的索引设置好,再把原来的数据库中的数据导入到这个数据库中,导入过程控制速度,这样就能保证不影响原来服务器的运行了。)

1.2.3 删除索引:drop index 索引名 on 表名;

手动创建的索引能够删除,自动生成的索引删除不了。

删除索引也是危险操作,要是实在要删除,应该要使用上述创建索引的策略进行操作。

1.3 索引的实现原理

1.3.1 引入B+树

索引是通过一系列的数据结构来实现的。那么是使用哪种数据结构进行实现的呢?

顺序表、链表、栈、队列、堆都不适合查询,适合查询的有二叉搜索树(红黑树)、哈希表,但是这两种数据结构都不适合数据库作为索引,对哈希表来说,只能进行精准查询,而无法做到范围查询、模糊匹配;对二叉树来说,既能够精准查询也能够范围查询和模糊匹配(“孙%”可以,“%孙”不行),不适合索引的数据结构的原因不在这,在于红黑树是二叉树,度只有2,数据多了树的高度就会很高,一旦高度高了,查询的时候IO访问的次数就更多(查询到每个节点都会访问一次IO)。

因此为了让树的高度不那么高,可以增加树的度来降低树的高度。这种数据结构叫做B+树(N叉搜索树)。

1.3.2 简单了解B树

认识B+树之前,先了解一下什么是B树。B树是一个n叉搜索树,每个节点的度是不确定的,一个节点可以有多个key,n个key可以划分出最多n+1个区间,每个区间都能生成一颗子树(节点)。

一个节点里的key的个数不是无限制的,当一个节点中的key达到一定数量时,会触发节点的分裂,当删除key达到一定数目,也会进行节点的合并,如:

1.3.3 认识B+树

B+树时B树的改进版,针对数据库量身定做的。

1.3.3.1 B+树的特点
  • B+树也是N叉搜索树,一个节点有N个key,可以划分N个区间(不是N+1),每个节点最后一个key后面不能划分区间。
  • 每个节点的最后一个key是当前子树的最大值。
  • 父节点的key都会以最大值的身份出现在对应区间的子节点中,这样的意义是,叶子节点这一层会包含整个树的key。
  • B+树会用链表这样的结构将叶子节点串起来。此时就可以很方便地进行数据的遍历,并且很方便地在数据集合中取出一个范围的子集。

1.3.3.2 B+树的优点
  • N叉搜索树,高度有限,降低访问IO的次数。
  • 非常擅长范围查询
  • 所有查询都会在叶子节点上进行,每次查询的时间开销都是基本一致的,更加稳定。
  • 非叶子节点仅存储key,叶子节点存储整行记录的数据(这样就可以提前把非叶子节点的数据缓存到内存中,查询到时候直接在内存中进行,进一步地减少IO的访问)

2.事务

2.1 事务的概念

实际开发中,有些场景需要“一气呵成”地完成操作,中间不能报错,不能出现问题。比如转账:

如果出现这样的问题,就是严重错误了,为了解决这种数据不上不下的问题,引入了事务这样的概念。

事务是指逻辑上的一组操作。将多个sql语句打包成一个整体,这样的特点称为“原子性”。要么全部执行完,要么“一个都不执行”。此处的都不执行并不是真的没有执行,而是执行到一半出错了,后面的语句没有被执行到,MySQL就会发现此处出现问题了,对执行过的语句进行回退,回退成没执行前的样子,这样的操作称为回滚(rollback)。回滚的原理是以日志的方式,记录事务当中的重要操作。这样的记录就是回滚的依据。

2.2 事务的使用

开启事务:start transaction

提交:commit

回滚:rollback

2.3 事务的特性

2.3.1 原子性

将多个sql语句打包成一个整体,保证一系列操作能够“执行正确”或“恢复如初”。

2.3.2 一致性

在事务执行前和执行后,数据都不能太离谱,很多时候要靠数据库约束和一系列检查机制来完成的。

2.3.3 持久性

事务做出的修改,都是在硬盘上持久保存的。重启服务器,数据仍然存在,事务的修改仍然是有效的。

2.3.4 隔离性

这是在数据库并发执行多个事务会涉及到的问题。MySQL是一个客户端服务器结构的程序,一个服务器可以给多个客户端提供服务。多个客户端都可以让数据库执行事务,并发是非常常见的。

如果希望为了提高效率而提高并发程度,就会导致数据可能会出现一些“错误”。

隔离级别就是在“执行效率”和“数据准确性”之间做权衡。往往提高效率就会降低正确性,提高正确性就会降低效率。

在并发执行事务时,会出现哪些问题呢?

2.3.4.1 脏读

一个事务A在写数据的过程中,事务B在读数据,此时如果事务B读完了,事务A还在写或者改数据,那事务B读到的数据就是不完整的或是错误的。这种现象就叫做脏读。

解决的方案是给写操作加锁,在写数据的时候,不允许进行读操作。写操作完成后才可进行读操作,这样的执行方式虽然会降低效率,但可靠性高了,数据准确性提高了。

2.3.4.2 不可重复读

一个事务A在读数据的过程中,事务B在写操作,此时如果事务A中要读取多次数据,在这过程中事务B改写了数据,事务A接下来读到的数据将会与之前读到的数据不一致,这种情况就是不可重复读。如果是两个事务间读到的数据不一致,是没有问题的,如果是同一个事务中,读到的数据不一致,就是不能接受的。

解决方案是给读操作加锁,在读数据的过程中,不允许进行写操作。

2.3.4.3 幻读

事务A在文件1中读数据的过程中,事务B在文件2中写数据,此时如果在事务A读数据的时候,事务B写完了,等到事务A读完数据之后,就会发现多出了个文件2。虽然是事务A读的数据内容没变,但是整体的数据集变了,这种情况称为幻读。幻读是否需要解决要结合具体场景分析,可以是问题也可以不是问题。

解决方法是多个事务之间使用串行的方式进行执行,完全不使用并发执行,这样的执行方式就会使执行效率降低很多,但可靠性更高。

2.3.4.4 隔离级别

要在效率和准确性之间做权衡,不同场景中的要求不同,MySQL中提供了“隔离级别”,可以针对不同隔离程度进行设置,应付不同场景。有的场景追求准确度,效率是其次,比如充值、转账等一系列场景;有点场景追求效率,其次是准确度,比如短视频点赞、评论、转发。

MySQL提供的“隔离级别”总共有四种,可以针对不同需求进行设置,可以在MySQL中的配置文件中进行设置隔离级别。

四种级别,对应上述三个问题

MySQL默认的隔离级别是repeatable read(可重复读),这种隔离级别可以应付开发中绝大多数场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值