Java 面试八股文这篇专栏够用之数据库篇(一)

115 阅读8分钟

Java 面试八股文这专栏够用之数据库篇(一)

问1:如何定位慢查询?

  1. 我们系统中当时采用了运维工具( Skywalking ),可以监测出哪个接口,最终因为是 sql 的问题
  2. 在 mysql 中开启慢日志查询,我们设置的值就是 2 秒,一旦 sql 执行超过 2 秒就会记录到日志中(调试阶段),配置信息如下:
# 开启 MySQL 慢日志查询开关
slow_query_log=1# 设置慢日志的时间为 2 秒, SQL 语句执行时间超过 2 秒,就会视为慢查询,记录慢查询日志
long_query_time=2

详细回答

面试官:MySQL 中,如何定位慢查询?

候选人:

嗯~,我们当时做压测的时候有的接口非常的慢,接口的响应时间超过了 2 秒以上,因为我们当时的系统部署了运维的监控系统 Skywalking,在展示的报表中可以看到是哪一个接口比较慢,并且可以分析这个接口哪部分比较慢,这里可以看到 SQL 的具体的执行时间,所以可以定位是哪个 sql 出了问题。

如果,项目中没有这种运维的监控系统,其实在 MySQL 中也提供了慢日志查询的功能,可以在 MySQL 的系统配置文件中开启这个慢日志的功能,并且也可以设置 SQL 执行超过多少时间来记录到一个日志文件中,我记得上一个项目配置的是 2 秒,只要 SQL 执行的时间超过了 2 秒就会记录到日志文件中,我们就可以在日志文件找到执行比较慢的 SQL 了。

问2:那这个 SQL 语句执行很慢 , 如何分析呢?

可以采用 EXPLAIN 或者 DESC 命令获取 MySQL 如何执行 SELECT 语句的信息

- 直接在 select 语句之前加上关键字 explain / desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件 
  • 通过 key 和 key_len 检查是否命中了索引(索引本身存在是否有失效的情况)
  • 通过 type 字段查看 sql 是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
  • 通过 extra 建议判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修 image.png

详细回答

面试官:那这个 SQL 语句执行很慢,如何分析呢?

候选人:

如果一条 sql 执行很慢的话,我们通常会使用 mysql 自动的执行计划 explain 来去查看这条 sql 的执行情况,比如在这里面可以通过 key 和 key_len 检查是否命中了索引,如果本身已经添加了索引,也可以判断索引是否有失效的情况,第二个,可以通过 type 字段查看 sql 是否有进一步的优化空间,是否存在全索引扫描或全盘扫描,第三个可以通过 extra 建议来判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复。

问3:MYSQL 支持的存储引擎有哪些 , 有什么区别 ? 在 mysql 中提供了很多的存储引擎,比较常见有 InnoDB 、 MyISAM 、 Memory

  • InnoDB 存储引擎是 mysql5.5 之后是默认的引擎,它支持事务、外键、表级锁和行级锁
  • MyISAM 是早期的引擎,它不支持事务、只有表级锁、也没有外键,用的不多
  • Memory 主要把数据存储在内存,支持表级锁,没有外键和事务,用的也不多

问4:存储引擎在 mysql 的体系结构哪一层,主要特点是什么?

  • MySQL 体系结构
  • InnoDB 存储的特点

问5:索引在项目中的使用方式

  • 一是验证你的项目场景的真实性,二是为了作为深入发问的切入点
  • 缓存
  • 分布式锁
  • 消息队列、延迟队列
  • ... ...

问6:了解过索引吗?(什么是索引)

面试官:了解过索引吗?(什么是索引)
候选人:嗯,索引在项目中还是比较常见的,它是帮助 MySQL 高效获取数据的数据结构,主要是用来提高数据检索的效率,降低数据库的 IO 成本,同时通过索引列对数据进行排序,降低数据排序的成本,也能降低了 CPU 的消耗

问7:索引的底层数据结构了解过嘛?

面试官:索引的底层数据结构了解过嘛?
候选人:

MySQL 的默认的存储引擎 InnoDB 采用的 B + 树的数据结构来存储索引,选择 B + 树的主要的原因是:第一阶数更多,路径更短,第二个磁盘读写代价 B + 树更低,非叶子节点只存储指针,叶子阶段存储数据,第三是 B + 树便于扫库和区间查询,叶子节点是一个双向链表

问8:B 树和 B + 树的区别是什么呢

面试官:B 树和 B + 树的区别是什么呢?
候选人:

第一:在 B 树中,非叶子节点和叶子节点都会存放数据,而 B + 树的所有的数据都会出现在叶子节点,在查询的时候,B + 树查找效率更加稳定
第二:在进行范围查询的时候,B + 树效率更高,因为 B + 树都在叶子节点存储,并且叶子节点是一个双向链表

问9:什么是聚簇索引(聚集索引),什么是二级索引(非聚簇索引)?

面试官:什么是聚簇索引,什么是非聚簇索引?
候选人:
好的~,聚簇索引主要是指数据与索引放到一块,B + 树的叶子节点保存了整行数据,有且只有一个,一般情况下主键在作为聚簇索引的

非聚簇索引值的是数据与索引分开存储,B + 树的叶子节点保存对应的主键(就是说保存的是自己的字段和主键),可以有多个,一般我们自己定义的索引都是非聚簇索引

下面的是两个索引的图解:

image.png

注意:

问10:知道什么是回表查询嘛?

面试官:知道什么是回表查询嘛?
候选人:嗯,其实跟刚才介绍的聚簇索引和非聚簇索引是有关系的,回表的意思就是通过二级索引找到对应的主键值,然后再通过主键值找到聚集索引中所对应的整行数据,这个过程就是回表

【备注:如果面试官直接问回表,则需要先介绍聚簇索引和非聚簇索引】

问11:知道什么叫覆盖索引嘛?

面试官:知道什么叫覆盖索引嘛?
候选人:嗯~,清楚的

覆盖索引是指 select 查询语句使用了索引,在返回的列,必须在索引中全部能够找到,如果我们使用 id 查询,它会直接走聚集索引查询,一次索引扫描,直接返回数据,性能高。

如果按照二级索引查询数据的时候,返回的列中没有创建索引,有可能会触发回表查询,尽量避免使用 select*,尽量在返回的列中都包含添加索引的字段

问12:MYSQL 超大分页怎么处理?

面试官:MYSQL 超大分页怎么处理?
候选人:嗯,超大分页一般都是在数据量比较大时,我们使用了 limit 分页查询,并且需要对数据进行排序,这个时候效率就很低,我们可以采用覆盖索引和子查询来解决

先分页查询数据的 id 字段,确定了 id 之后,再用子查询来过滤,只查询这个 id 列表中的数据就可以了

因为查询 id 的时候,走的覆盖索引,所以效率可以提升很多

问13:索引创建原则有哪些?

面试官:索引创建原则有哪些?
候选人:嗯,这个情况有很多,不过都有一个大前提,就是表中的数据要超过 10 万以上,我们才会创建索引,并且添加索引的字段是查询比较频繁的字段,一般也是像作为查询条件,排序字段或分组的字段这些。

还有就是,我们通常创建索引的时候都是使用复合索引来创建,一条 sql 的返回值,尽量使用覆盖索引,如果字段的区分度不高的话,我们也会把它放在组合索引后面的字段。

如果某一个字段的内容较长,我们会考虑使用前缀索引来使用,当然并不是所有的字段都要添加索引,这个索引的数量也要控制,因为添加索引也会导致新增改的速度变慢。

问14:什么情况下索引会失效?

面试官:什么情况下索引会失效?

候选人:嗯,这个情况比较多,我说一些自己的经验,以前遇到过的

比如,索引在使用的时候没有遵循最左匹配法则,第二个是,模糊查询,如果 % 号在前面也会导致索引失效。如果在添加索引的字段上进行了运算操作或者类型转换也都会导致索引失效。

我们之前还遇到过一个就是,如果使用了复合索引,中间使用了范围查询,右边的条件索引也会失效

所以,通常情况下,想要判断出这条 sql 是否有索引失效的情况,可以使用 explain 执行计划来分析