首页 > 《InterviewGuide》第十一弹MySQL万字总结
头像
拱白菜的阿秀
发布于 2021-05-14 15:38
+ 关注

《InterviewGuide》第十一弹MySQL万字总结

大家好,我是鸽秀。

嗯,鸽子的鸽...

图片说明

《逆袭进大厂》系列貌似鸽很久了,都有粉丝跑来给我留言催更....
图片说明

这段时间阿秀也是一直在忙自己毕业的事,研究生大论文搞得我脑壳都要大了,艾玛昨天好不容易写完提交外审了。

赶紧连夜整理好 MySQL 方面的笔记,然后发布出来...

在这段时间又有不少小伙伴专程跑过来加我微信,告诉我上岸的好消息,真的非常多...随便挑了两个。

百度凤巢和字节offer 阿里本地生活offer

一个是百度核心部分凤巢,一个是阿里本地生活!真的很替他们高兴鸭!其实我的 PDF 只是起到归纳总结的作用,最重要的还是他们自己的努力 + 坚持才收获到这些胜利果实的,希望看到这里的你也能吸吸欧气,早日上岸!

好了,开始我们今天的主题吧。

我的 MySQL 笔记全部整理完是 24,846 个字。本想一次性全部发完的,但考虑到以前我那令人诟病的排版,还是分为两期发布好了。第一期一共是是 12,474 字,剩下的下一期,也就是第十二单再公开出来好了,来看看本期你会多少吧。

1、为什么使用索引?

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 帮助服务器避免排序和临时表
  • 将随机IO变为顺序IO。
  • 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

2、Innodb为什么要用自增id作为主键?

如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。
如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置, 频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE(optimize table)来重建表并优化填充页面。

3、MyISAM和InnoDB实现B树索引方式的区别是什么?

  • MyISAM,B+Tree叶节点的data域存放的是数据记录的地址,在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址读区相应的数据记录,这被称为“非聚簇索引”

  • InnoDB,其数据文件本身就是索引文件,相比MyISAM,索引文件和数据文件是分离的其表数据文件本身就是按B+Tree组织的一个索引结构,树的节点data域保存了完整的数据记录,这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引,这被称为“聚簇索引”或者聚集索引,而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。

    在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引。因此,在设计表的时候,不建议使用过长的字段为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

4、说一下MySQL是如何执行一条SQL的?具体步骤有哪些?

SQL执行的全部过程

Server层按顺序执行sql的步骤为:

  1. 客户端请求->
  2. 连接器(验证用户身份,给予权限) ->
  3. 查询缓存(存在缓存则直接返回,不存在则执行后续操作)->
  4. 分析器(对SQL进行词法分析和语法分析操作) ->
  5. 优化器(主要对执行的sql优化选择最优的执行方案方法) ->
  6. 执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)->
  7. 去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)

简单概括:

  • 连接器:管理连接、权限验证;
  • 查询缓存:命中缓存则直接返回结果;
  • 分析器:对SQL进行词法分析、语法分析;(判断查询的SQL字段是否存在也是在这步)
  • 优化器:执行计划生成、选择索引;
  • 执行器:操作引擎、返回结果;
  • 存储引擎:存储数据、提供读写接口。

5、你了解MySQL的内部构造吗?一般可以分为哪两个过分?

可以分为服务层和存储引擎层两部分,其中:

服务层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5版本开始成为了默认的存储引擎。

6、说一说Drop、Delete与Truncate的共同点和区别

第一种回答

Drop、Delete、Truncate都表示删除,但是三者有一些差别:
Delete用来删除表的全部或者一部分数据行,执行delete之后,用户需要提交(commmit)或者回滚(rollback)来执行删除或者撤销删除,会触发这个表上所有的delete触发器。
Truncate删除表中的所有数据,这个操作不能回滚,也不会触发这个表上的触发器,TRUNCATE比delete更快,占用的空间更小。
Drop命令从数据库中删除表,所有的数据行,索引和权限也会被删除,所有的DML触发器也不会被触发,这个命令也不能回滚。

因此,在不再需要一张表的时候,用Drop;在想删除部分数据行时候,用Delete;在保留表而删除所有数据的时候用Truncate。

第二种回答
  • drop直接删掉表;
  • truncate删除表中数据,再插入时自增长id又从1开始 ;
  • delete删除表中数据,可以加where字句。
具体解析
  1. DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。
  2. 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。
  3. 一般而言,drop > truncate > delete
  4. 应用范围。TRUNCATE 只能对TABLE;DELETE可以是table和view
  5. TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)。
  6. truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。
  7. delete语句为DML(Data Manipulation Language),这个操作会被放到 rollback segment中,事务提交后才生效。如果有相应的 tigger,执行的时候将被触发。
  8. truncate、drop是DDL(Data Define Language),操作立即生效,原数据不放到 rollback segment中,不能回滚
  9. 在没有备份情况下,谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围。回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除,如果于事务无关,用truncate即可实现。如果和事务有关,或老是想触发trigger,还是用delete。
  10. Truncate table 表名 速度快,而且效率高,因为: truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
  11. TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。
  12. 对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

7、MySQL优化了解吗?说一下从哪些方面可以做到性能优化?

  • 为搜索字段创建索引
  • 避免使用 Select *,列出需要查询的字段
  • 垂直分割分表
  • 选择正确的存储引擎

8、数据库隔离级别

  • 未提交读,事务中发生了修改,即使没有提交,其他事务也是可见的,比如对于一个数A原来50修改为100,但是我还没有提交修改,另一个事务看到这个修改,而这个时候原事务发生了回滚,这时候A还是50,但是另一个事务看到的A是100.可能会导致脏读、幻读或不可重复读
  • 提交读,对于一个事务从开始直到提交之前,所做的任何修改是其他事务不可见的,举例就是对于一个数A原来是50,然后提交修改成100,这个时候另一个事务在A提交修改之前,读取的A是50,刚读取完,A就被修改成100,这个时候另一个事务再进行读取发现A就突然变成100了;可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • 重复读,就是对一个记录读取多次的记录是相同的,比如对于一个数A读取的话一直是A,前后两次读取的A是一致的;可以阻止脏读和不可重复读,但幻读仍有可能发生
  • 可串行化读,在并发情况下,和串行化的读取的结果是一致的,没有什么不同,比如不会发生脏读和幻读;该级别可以防止脏读、不可重复读以及幻读
隔离级别 脏读 不可重复读 幻影读
READ-UNCOMMITTED 未提交读
READ-COMMITTED 提交读 ×
REPEATABLE-READ 重复读 × ×
SERIALIZABLE 可串行化读 × × ×

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)

这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别 下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以 说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要 求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。

因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内 容):,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读)并不会有任何性能损失

InnoDB 存储引擎在分布式事务 的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。

9、都知道数据库索引采用B+树而不是B树,原因也有很

全部评论

(1) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期精华帖

热门推荐