【MySQL】索引和事务


前言

你所做的事情,也许暂时看不到成果,但不要灰心或焦虑,你不是没有成长,而是在扎根

【索引和事务】主要和面试题有关!


一、索引

一)概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。

二)作用

  1. 索引的存在主要是为了提高查询的效率
  2. 但是索引也是需要付出代价的:

①消耗更多的空间
②虽然提高了查询效率,但是降低了增加、删除、修改的效率——增删改,不仅要修改数据,还要调整索引!

(虽然索引有代价,但是是值得的,因为:大多数情况下,查询频率大于增删改频率)

  1. 索引所起的作用类似书籍目录,可用于快速定位、检索数据

三)使用场景

  1. 要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
  • 数据量较大,且经常对这些列进行条件查询
  • 该数据库表的插入操作,及对这些列的修改操作频率较低
  • 索引会占用额外的磁盘空间。
    满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
  1. 反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

四)使用

创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。

1. 查看索引

show index from 表名;

2. 创建索引

  1. 语法:
create index 索引名 on 表名(列名);
  1. 创建索引是一个“低效操作”,如果表中数据少则影响不大;如果表中数据较多时创建索引就可能非常耗时+带来大量的硬盘IO——也是可能会卡死数据库的
  2. 创建索引会创建出一些相关的数据结构。(索引的实现通常使用B树及其变种B+树。)
  3. 对于非主键、非唯一约束、非外键的字段,可以创建普通索引。

3. 删除索引

  1. 语法:
 drop index 索引名 on 表名;
  1. 删除操作和创建操作类似,都是比较低效的操作
    (对于生产环境上比较大的表,一般都是建表之初就把索引规划好的)

  2. SQL确实能够支持一些 定义变量、定义函数、条件、循环、库函数等操作,但是很少会使用; 一般不会使用SQL写一些太复杂的逻辑,逻辑层面的东西一般都是通过Java这样的语言来完成的;SQL一般是完成 增删查改 操作的。

  3. 可以使用explain来进行查看SQL的执行:

explain select * from test_user where id_number=123;

4. 补充

  1. 面试经典问题:
    1) 索引背后的数据结构是啥样的
    2) 谈谈ArrayList和LinkedList的区别:
    ① ArrayList底层是顺序表,LinkedList底层是链表;
    ② ArrayList查找较快,LinkedList增加删除较快(这是错误的!)——ArrayList查找并不快,只是具备随机访问能力(随机访问 是通过下标获取元素; 查找是根据来获取元素位置indexOf 。 而ArrayList查找的时候是要遍历的,时间复杂度O(N)并没有优势)
    LinkedList增加删除也不快,首尾增删是O(1),但是中间位置进行增删还是O(N),增加add(index,value)要遍历找index位置,所以还是O(N))】
    (这里的中间位置插入删除之所以是O(N)不是链表不行,而是LinkedList不太行)

  2. 哈希表和二叉搜索树都不太适合左数据库的索引。理由如下:
    ①哈希表增删查改都快,但是只能查询值相等的情况,对于> < between…and… 这类比较大小的范围查询是不太适合的
    ②二叉搜索树最坏查询速度是O(N),像AVL树/红黑树这些比较平衡的二叉搜索树是O(logN);如果数据库数据特别多,则二叉树高度O(logN)就会比较高,这又和查询次数相关。
    故:如果比较是在内存内进行的,那么多比几次少比几次影响不大,但是如果每次都要读取硬盘,这个就可能会产生影响:IO次数越少越好

  3. 数据库索引的量身定做:B+树
    (认识B+树之前,先认识一下B树,有些书上的B-树其实就是B树)
    1)B树是一个N叉搜索树,每个结点上可能会包含N-1个值,当然也可以更少;N-1个值就把区间划分成N份;这样,在同样的数据集合下,N叉树就会比二叉树的高度小很多,IO次数也就降低了
    2)B树代码的实现是非常复杂的,复杂主要是在 分裂和合并 上

  4. 【B树与B+树的区别:
    ① B树每个结点N-1个值,就分出了N个区间;B+树N个值就分出了N个区间;
    ② B树中的值不会重复出现,B+树是可能重复出现的(况且在B+树中,父元素的值会在子元素中以最大值/最小值的姿态出现);
    ③ 在叶子结点这里,B+树会把所有的叶子结点以链表的形式首尾相连(so:在叶子结点这里已经是完整的数据集合了,前面的非叶子结点都会在这里体现出来,这也就是元素重复的意义),此时就非常便于范围查找
    ④ 正因为叶子结点是全集数据,只需要把每一行(每一条记录的完整的所有列关联到叶子结点上即可),非叶子结点只需保存索引列(其实就是一个id)
    ——so:非叶子结点占用的空间相比于完整的数据集合非常小,就可以在内存中缓存;因此此时的查询又进一步减少了硬盘IO】


二、事务

一) 为什么使用事务

银行、购物等为例,钱只有一边减少。

二) 事务的概念

  1. 事务:操作要么全部执行,要么一个都不执行(其实就是如果中途执行失败就自动回滚rollback),也就是保证了原子性。
  2. 在事务的执行过程中,MySQL会记录每一步都干了啥,一旦出现问题就根据记录的日志进行修改回滚
  3. 注:为什么数据库不设置撤回功能?——因为撤回功能实际上一般是人为操作失误进行撤回的,但是操作数据库大部分都是使用代码,而且要实现撤回功能要记录所有操作;因此,撤回功能不常使用且代价太大。

三) 使用

  1. start transaction; // 事务开启

  2. commit; // 事务结束,提交事务

  3. rollbacck; // 回滚

  4. 注:事务的开启、提交、回滚一般都是通过代码来控制的
    (代码都不复杂,复杂的是 事务的相关原理(面试常考!))

  5. 事务的特性
    ① 原子性A:事务的根本/事务存在的意义,能够把多个SQL打包成一个整体,要么都执行,要么都不执行(如果执行过程中出错就进行回滚)
    ② 一致性C:事务执行前后,数据处在“一致”的状态
    ③ 持久性D:事务进行的改动都是写到硬盘里,不会随着程序启动/主机重启而丢失
    ④ 隔离性I:(最复杂)多个事务并发执行的时候,事务之间能够保持“隔离”独立,不相互干扰

(如果这些并发执行的事务操作的是不同的数据库/不同的表,那么此时是没啥影响的;但是如果操作的是相同的数据库、相同的表就可能会进行抢占而出现问题)

  • so:隔离性存在的意义其实就是:让并发执行事务的过程中尽量不出现问题/问题在可控范围内
  1. 脏读问题:即读脏数据。脏数据就是一个临时的数据,不代表最终结果,中间可能数据就被修改了。
    1)所以:脏读其实就是一个事务A在提交之前修改了数据,而事务B读到的是事务A修改之前的数据,即事务B读到了“无效的数据”,这就是脏读。
    2)【如何解决脏读问题:在提交之后才能读(即:写完读),相当于对 写操作加锁
    3)在写加锁之前,读和写操作是完全并发的,隔离性是最低的; 但是当写操作加锁之后,并发性降低了(效率降低),隔离性提高了(准确性提高)。

  2. 不可重复读:在事务提交之后,对于该事务读取数据时发现数据被人修改,多次读取到的数据不一样。
    1)【解决方法:写加锁 + 读加锁
    2)读加锁的引入,使得并发程度进一步降低(效率降低),但是隔离性/准确率提高)
    3)【在一个程序读文件A的时候,另一个程序去操作其他的文件,此时并不影响该程序对文件数据的读取,但是会发现最后的结果集可能改变了——这是 “幻读”(可以视为是“不可重复读”的特殊情况)
    ——解决“幻读”问题:“串行化”(一次只有一个程序在操作)——此时并发程度最低/效率最低,但是隔离性最高/数据的准确性最高】

  3. 并发执行事务中可能带来的影响:【脏读、不可重复度、幻读。】但是这些影响并不一定是bug(是不是bug看实际需求,是否符合需求、是否允许存在一定误差)

  4. 如果需求对于数据精度要求不高,就可以让并发性高一些、隔离性差一些,以此提高效率; 但是如果需求对于数据精度要求很高,则并发性低一些,隔离性高一些,以此提高精度

  5. MySQL的隔离级别:
    ① read uncommitted 允许读未提交的数据,并发程度最高,隔离性最低;可能存在脏读、不可重复读、幻读问题。
    ② read committed 只能读提交之后的数据,相当于写加锁,并发程度降低,隔离性提高;解决了脏读问题,但是可能存在不可重复读、幻读问题。
    ③ repeatable read 相当于读和写都加锁了,并发性再降低,隔离性再提高;解决了脏读和不可重复度问题,但是可能存在幻读问题。【MySQL默认!
    ④ serializable 严格执行串行化,并发程度最低,隔离性最高;解决了脏读、不可重复读和幻读问题。效率最低。
    (可以在mysql的配置文件my.ini中进行设置:根据不同的需求场景设置不同的级别,以此来平衡效率和准确性)

  6. 【面试题:】
    1)谈谈如何理解索引——①索引是干啥的(解决了什么问题) ②索引付出的代价 ③索引背后的数据结构
    2)谈谈如何理解事务——①事务是干啥的(从原子性切入) ②事务的其他特性 ③重点隔离性,在并发执行事务下会有哪些问题、以及如何解决 ④MySQL的隔离级别有哪些,和上面的问题如何对应


THINK

  1. 索引
    (1)对于插入、删除数据频率高的表,不适用索引
    (2)对于某列修改频率高的,该列不适用索引
    (3)通过某列或某几列的条件查询频率高的,可以对这些列创建索引
  2. 事务
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值