1. 索引
索引也就是 index ,类似于下标,目录
索引可以提高查询的速度,但是会有其他的问题:
- 目录本身也占据存储空间(一般是硬盘)
- 虽然提高了查找效率,但是降低了增、删、改的效率
( 比如插入新记录,需要既能够插入硬盘的数据,又要调整索引 )
1.1 使用
- 查看索引
show index from 表名;
所谓的"索引”是按照列的方式来创建的,可以给某个列创建索引
- 创建索引(危险操作,存在大量 i o)
create index 索引名 on 表名(列名);
- 删除索引(危险操作,存在大量 i o)
drop index 索引名 on 表名;
- 示例:
如何给一个已经包含大量数据的表添加索引???
- 部署一个新的数据库,用新的数据库代替旧的数据库,并且注意要慢慢的到处数据,以免占满CPU,产生问题
1.2 索引的数据结构 (B+树)
索引是提高查询的效率,减少 I/O 的次数
数据结构中,查询效率高的有 哈希表 和 二叉搜索树,但是这两种不适合用于数据库索引
- 二叉搜索树,查询速度 O(N)最坏情况
AVL 树 / 红黑树 (比较平衡的二叉搜索树)O(logN)
如果数据库数据特别多时,树的高度就会比较高,高度高了就查询时比较的次数就会多 如果每次要读硬盘,这样就不太行了- 哈希表虽然增删查改都快 O(1)
但是只能查询值相等的情况。
- 解释一下B树
- 那么什么又是B+树:
2. 事务
2.1 事务的理解
把多个操作,打包成一个整体,称为“原子性”,即不可分割的最小单位
那么可以保证,要么整体都执行成功,要么一条都不执行,避免产生一部分执行,一部分未执行,避免产生“中间状态引起”的问题
回滚:
- 如果其中有一个出现了问题,数据库可以把 SQL 造成的影响恢复如初,看起来就像一条SQL语句都没有执行一样
那么为了实现回滚,数据库再执行事务的时候,会记录日志 —> 记录到硬盘文件中
- 若事务执行完毕,没有差错,记录的内容就可以不要了 但是如果出现了问题,
- 那么 MySQL 就可以根据日志的内容进行恢复操作
2.2 事务的使用
(1)开启事务:start transaction;
(2)执行多条SQL语句
(3)回滚或提交:rollback/commit; 全部失败/全部成功
2.3 事务的基本特性
- 原子性:事务的存在的意义,能够把多个SQL打包成一个整体,要么全部执行完,要么一个都不执行(如果执行过程中出错,则自动回滚)。
- 一致性:数据库执行事务之前和执行事务之后,数据是一致的(不会出现对不上的情况),如果出现了回滚,那么回滚后的数据要一致的,如果没有回滚,那么数据也是要一致的(是对数据正确的承诺)。
- 持久性:即程序重启/主机重启,数据仍然存在,数据存在硬盘上。
- 隔离性:数据库并发(多个客户端同时给服务器发起事务)执行事务的时候产生的情况,使并发执行时,事务之间保持“隔离”,不互相干扰。
- 脏读:
一个事务A在修改数据,提交之前
,另一个事务B读取了数据
,此时A极有可能在提交的时候提交的是不同数据(后续又修改了)
此时事务B读到的就是“无效的数据
”,就称为脏读,读取脏数据
解决"脏读"问题:
- 针对“写操作”加锁,写的时候不可以读,写完了才可以读
但是引入写加锁后,执行A的时候,B就不可以执行,需要等待。这也就降低了 “并发能力”,也会降低数据库服务器的处理效率,提高了”隔离性“,也提高了数据的准确性。(这里是做出了取舍,牺牲一部分效率,来提高准确性)
- 不可重复读:
存在三个事务A、B、C:
事务A针对事务进行修改,提交
;接下来事务B进行读取数据
(事务B这里的多个SQL都要进行读操作);在执行B的过程中又有一个事务C,又针对数据进行了修改
。
就会使B里面的不同的读操作,读出来的结果不一样
解决"不可重复读"问题:
读操作加锁:别人读的时候,我也不能写
引入读加锁,就会使 ”并发程度“进一步降低,效率也随之降低,”隔离性“又进一步提高,数据的准确性也会提高。这个时候ABC都不能并发了
- 幻读问题:
刚刚约定了,针对读操作和写操作都加锁了,
但是此时事务A先修改并提交数据,事务B进行读数据,此时事务C,没有修改B读的数据,但是给对应的表进行了新增数据/删除数据等操作,导致事务B中,读到的数据集不同(已有的数据内容一致,但是数据的条数增加/减少)。
解决"幻读"问题:
"串行化"使所有事务都严格按照”一个接着一个“的方式执行,完全没有并发了,此时的执行效率最低,隔离性也是最高的,数据也是最准确的。