网站建设注意哪些方面,展览馆展示设计,家教中介网站开发,个人养老保险怎么查询前言#x1f440;~
紧接着数据库的相关知识#xff0c;今天讲解MySQL面试中频繁被问到的知识点#xff0c;索引与事务!!! 如果各位对文章的内容感兴趣的话#xff0c;请点点小赞#xff0c;关注一手不迷路#xff0c;如果内容有什么问题的话#xff0c;欢迎各位评论纠正… 前言~
紧接着数据库的相关知识今天讲解MySQL面试中频繁被问到的知识点索引与事务!!! 如果各位对文章的内容感兴趣的话请点点小赞关注一手不迷路如果内容有什么问题的话欢迎各位评论纠正 个人主页N_0050-CSDN博客 相关专栏java SE_N_0050的博客-CSDN博客 java数据结构_N_0050的博客-CSDN博客 MySQL索引 面试中考察的重点
首先我们知道在查询数据的时候会先遍历表然后把当前的行数据和我们给的条件进行比较看条件是否满足满足条件我们保留不满足则跳过如果表的记录数不多还好但是多的话我们的效率不高且开销大我们要知道数据库的存储数据是存储在硬盘上的每次读取数据的时候就要去读取硬盘所以开销很大由此我们引出索引这个针对查询进行优化
索引 属于是针对 查询操作 引入的 优化手段 可以通过索引来加快查询的速度避免针对表进行遍历索引通过使用特殊的数据结构可以快速查找和访问数据库表中的记录从而避免全表扫描提高查询效率可以把索引所起的作用想象成书籍目录可用于快速定位、检索数据 索引是能提高查询速度的但是也有代价
1.占用更多的空间生成索引是需要一系列的数据结构以及一系列的额外的数据来存储到硬盘空间中的
2.能提高 查询速度但是可能会降低 插入修改删除 的速度
索引使用场景
1.数据量较大且经常对这些列进行 条件查询
2.该数据库表的插入操作及对 这些列的 修改 操作频率较低
3.索引会占用额外的 磁盘空间
反之如果非条件查询列 或经常做插入、修改操作或磁盘空间不足时不考虑创建索引 索引的相关操作 有些情况下我们这张表会自带索引就是有时候索引是我们手动创建的有时候是数据库自动创建的
手动索引手动索引会增加数据库的维护成本因为每次插入、更新或删除操作时索引也需要更新选择哪些字段创建手动索引需要考虑查询频率和性能需求如果一个字段经常出现在查询条件中手动为其创建索引是有意义的
什么时候数据库自动创建的呢
主键约束、unique约束、外键约束这些情况下会自动生成索引
为什么会自动生成呢
主键 和 unique是要求数据不能出现重复的怎么判断重不重复 通过查询因为他们对数据进行操作的时候都会先触发查询的操作所以会涉及频繁的查询为了优化查询的速度就引入了索引 外键 因为子表要保证在父表那一列中存在对子表进行操作的时候就要去父表中查一查判断记录是不是存在。反之删除父表中的一条记录也要去子表中查一查看看当前要操作的记录是不是在子表中被引用了所以会涉及频繁的查询为了优化查询的速度就引入了查询 主键 unique 外键
父表和子表进行外键关联 有了这个索引后后续在父表中删除一条记录就拿着父表的id去子表中查通过这个索引可以快速查到是否存在 1.查看索引 show index from 表名; 一个索引是针对 一个列 来指定的只有针对这一列进行条件查询的时候查询速度才能被索引优化 2.创建索引 create index 索引名字 on 表名(列名); 创建索引操作是一个危险的操作
创建索引的时候需要针对现有的数据进行大规模的重新整理
如果当前表是一个空表或者数据不多创建索引没什么问题如果这个表很大数据很多创建索引很容易把数据库服务器给卡住数据量很多的情况下创建索引非要创建也不是不行我们就需要一个新的数据库然后把表结构和索引设置好再把之前旧的数据库的数据导出来然后导入到这个新的数据库中 3.删除索引 drop index 索引名 on 表名; 手动创建的索引可以手动删除如果是自动创建的索引主键/外键unique不能删除的 总结
(1)对于插入、删除数据频率高的表不适用索引
(2)对于某列修改频率高的该列不适用索引
(3)通过某列或某几列的条件查询频率高的可以对这些列创建索引 索引背后的原理的理解 索引也是通过一定的数据结构来实现的数据库引入的索引是一个改进的树形结构B树N叉搜索树 我们回顾个别适合查找的数据结构首先是我们的哈希表哈希表在进行查询的时候时间复杂度接近O(1)但是呢我们要知道哈希表进行查询的时候先计算出哈希值然后再通过哈希函数计算出我们放在哪个index下对于单条数据进行查询的时候速度是很快但是对于我们在查询的时候添加一些条件呢此时如果我们要查询1-100的数据那我们要一个一个进行hash然后计算下标那这效率和开销都不是很理想所以MySQL没有将其作为索引的数据结构。
接着就是二叉搜索树我们知道二叉搜索树在进行查询的效率也很高因为它的左子树的节点都是满足小于我们根节点的值的条件右子树的节点都是大于我们根节点的值所以在最好的情况下时间复杂度为O(log2N 以二为底的对数)但是呢如果我们要找的数据在刚好在叶子节点呢并且我们的数据有很多的时候那我们树的高度就很高此时我们的查询效率和开销都不理想显然它也不适合作为索引的数据结构。 N叉搜索树
N叉搜索树意思是有N个分叉每个分叉代表一个区间 二叉树两个分叉就每个节点下有两个子节点对于N叉树就是每个分叉代表一个区间区间存放着键值当区间中的键值少了的时候会进行合并多了的时候会进行拆分可能有点绕就这样理解区间就是节点然后我们的节点存放多个键值下面出现区间这个词的时候可以这样理解 例子比如根节点中存放3个节点10、20、30然后每个节点对应一个区间你存放了N个键值就有N1个键值拿刚才的例子说第一个区间就是存放小于值为10的键值第二个区间就是存放值为10-20之间的键值第三个区间就是值为20-30之间的键值最后一个区间则是存放大于值为30的键值 怎么找数据呢照着图思考如果我们要找18的话先从根节点中判断在哪个子节点中很明显在拥有13和17这个键值的节点中接着继续判断一眼就看出了18在大于17这个键值的节点下面的B树也是这样的结构 B树 B树的特点
1.就是我们有的节点中有N个键值就会有N1个区间
2.B树节点中存储的数据可以理解为行数据就是数据库表中的行数据
3.B树的开销大B树会涉及大量读写因为硬盘上读写1次成本相当于内存上读写1w次成本 B树 B树是相对于B树做出了一定的改进 B树也是N叉搜索树
B树的根区间中的节点存放N个节点就有N个区间有个约定就是保存的N个节点中有一个节点的值是最大的 B树的搜索步骤比如我们要找所有大于21的值照图思考首先进入根节点进行判断我们马上锁定在30这个值然后我们去到它的子节点接着找到25再往下走来到了叶子节点这个节点包含了大于21的值并且我们的叶子节点是链表结构组成的这和前面的B树不同因为B树的叶子节点是链式结构顺序读取范围内的所有数据时只需要一次顺序扫描即可就是说进入叶子节点的时候只需要一次硬盘IO就可以读取范围内的所有数据因为叶子节点是链式结构所以我们直接就可以找出所有大于21的值而换做是B树的话它还要回溯回到上个节点接着判断这样效率和开销和B树比起来差多了。 B树的查询时间开销是稳定的比如你要查图中的8即使一开始就找到了它还是会往下走走到叶子节点所以对于B树来说所有的查询最后都会走到叶子节点进行查询叶子节点中存放的是行的数据非叶子节点中存放包含的是索引信息比如id我们就能很快定位到对应的数据
B树的特点
1.B树开销小并且查询效率高特别是进范围查询
2.B树的叶子节点才是存储我们的数据而非叶子节点呢存储的是key比如我们给id这列设置了主键然后生成索引了我们的非叶子节点存储的就是这个id这样应该能懂吧 注意对于like %孙这种进行查找的话不会触发索引因为%这个具体是什么没法确定而索引本质是靠大小关系进行排列类似二分查找实际是N分查找 事务重要 面试中考察的重点
实际开发中有时候有些操作需要一次性完成例如转账如果转账的过程中我的钱扣了但是对方没收到这时候就需要用到事务 大多数情况下我们在谈论事务的时候如果没有特指分布式事务往往指的就是数据库事务 事务也可以理解是一个数据库操作的单位包含一个或多个数据库操作这些操作要么都执行正确要么一个都不执行 事务可以把多个sql语句打包成一个整体作为整体来执行这样的特点称为原子性可以保证这些sql语句要么都执行正确要么一个都不执行,一个都不执行并不是真正的一个都不执行得执行了才知道失败此时触发事务的回滚rollback 事务的操作 1.start transaction
2.执行sql语句 此时的sql语句具有原子性 打包成一个整体执行 要么都执行正确要么一个都不执行
3.commit和rollback 执行提交如果出错了则执行回滚主动触发
回滚是怎么做到的呢?
通过记录日志的方式记录事务中的关键操作日志会记录我们在事务中的每一步操作操作之前是一个什么样的结果操作之后是一个什么样的结果都会被记录下来这样的记录就是回滚的依据什么意思呢你进行插入操作后续回滚的时候就执行删除反之你执行删除操作后续回滚的时候就执行插入 日志是什么就是一些打印出来的内容存放在文件里以文件的形式存放在磁盘里,即使系统崩溃日志也不会丢失系统可以通过读取日志文件恢复数据。在上述操作中日志记录事务的每一步操作 事务的特性 我们知道mysql是一个客户端和服务器结构的程序所以肯定会遇到多个客户端让服务器执行多个事务的情况并且得出并发程度越高整体效率越高。
什么是并发程度呢指的是在多个任务的情况下系统能够同时处理的任务的数量
1.原子性A 主要通过回滚的方式 保证这一系列的操作要么都执行正确要么都不执行
2.一致性C 就刚才那个转账的例子给某某转1000你总不能转1000某某收2000
事务的一致性很多时候是靠数据库数据库管理系统DBMS约束以及一系列的检查机制完成
精确解释就是事务执行前后数据的状态从一个一致性的状态到另外一个一致性的状态,就是在执行事务前数据该是什么样子的就是什么样子的执行事务后数据该是什么样子的也就是什么样子的执行事务前后的数据要符合预期,保证数据库始终处于合法的状态,通过这种方式确保数据库的准确性
3.持久性D 事务做出的修改都是在硬盘上持久保存的即使重启了服务器数据仍然还在事务执行的修改也还是有效的
4.隔离性I 多个事务并发执行时一个事务的执行不应影响其他事务的执行。即事务之间相互隔离。简单点说就是在一场考试中 我写我的 你写你的 它写它的 相互不影响 注意只有保证了事务的持久性、原子性、隔离性之后一致性才能得到保障。也就是说 A、I、D 是手段C 是目的 并发执行多个事务引发的问题重要
1.脏读可以这么理解就是事务A在进行写操作的时候事务B进行读操作读取的是事务A未提交的数据接着事务A又对数据进行了修改之前事务B所读取的数据属于脏数据也可以说是无效数据,如果是串行化执行的话没什么问题并发执行的话就会出现脏读
解决方式对写操作加锁只能进行写操作不能进行读操作只能在事务进行提交之后才能在进行读操作
并发程度降低隔离性提高就是两个事务之间的影响小了效率降低准确性提高 2.丢失更新有两类丢失更新第一类丢失更新就是第一个事务执行更新操作的后第二个事务回滚了第一个事务的更新操作
第二类丢失更新就是两个事务都先执行读操作然后都执行更新操作会导致其中的一个事务更新的结果被覆盖了最终谁的修改先提交谁的修改就会被覆盖
解决方式使用读锁和写锁确保事务A在读或写数据时其他事务不能对数据进行操作。 3.不可重复读事务A和事务B在对同一条数据执行操作的时候例如事务A在对这条数据进行修改事务B第一次读的时候是一个数据第二次读的时候发现数据变了前面加写锁后事务在进行写操作的时候另外一个事务不能读操作但是没说一个事务在进行读的时候另外一个事务不能执行写操作。这个强调的是对单条记录的两次(多次)读操作受到的影响
解决方式对读操作加锁 (只能进行读操作不能进行写操作) 就是现在一个事务在进行读操作的时候另外一个事务不能进行写操作了
并发程度降低隔离性提高就是两个事务之间的影响小了效率降低准确性提高 4.幻读事务A在执行插入操作的时候事务B在执行读的操作的时候事务B第一次读的时候是一个结果集第二次读取的一个结果集中突然多了条记录,就像幻觉一样。这个强调的是两次(多次)读操作对结果集的记录数受到的影响
解决方式引入串行化的方式执行事务此时并发所引发的所有问题都不存在了并且此时的效率最低、隔离性最高、没有并发程度这一说因为都使用串行化执行了哪来的并发准确性最高 不可重复读和幻读的区别数据范围的区别不可重复读我认为是对同一条数据进行操作多次读操作同一条数据会有影响注重数据的内容而幻读呢是一个范围执行两次读操作一个结果集的记录数注重数据的数量会有影响 隔离级别 实际开发中在不同的场景有时候我们需要效率高例如点赞10000和10100、评论有时候呢需要准确性高例如充值、转账这时候就引出隔离级别这个概念mysql提供了四种隔离级别来应对不同的场景的不同要求,可以在mysql的配置文件中修改隔离级别
默认的隔离级别是repeatable read可重复读
这四种隔离级别对应并发执行引发的一系列问题
1.read uncommitted读未提交此时并发程度最高、效率最高、隔离性最低、准确性最低会引发脏读、不可重复读、幻读 2.read commit读已提交引入写加锁只能读取已经提交的版本此时并发程度降低、效率降低、隔离性提高、准确性提高解决了脏读问题 3.repeatable read可重复读引入加锁和读加锁读的时候不能写写的时候不能读此时并发程度再一步降低、效率也再一步降低、隔离性再提高、准确性也再提高解决了脏读和不可重复读问题 4.serializable串行化按照串行的方式一个一个执行事务此时没有并发程度这么一说效率最低、隔离性最高、准确性最高 以上便是索引和事务的知识点这一章的内容相当重要面试中频繁出现所以大家好好吸收和理解知识量还是很多的我们下一章再见爱心