面试篇-Mysql-1+慢sql+索引
文章目录
- 前言
- 一、线上的慢sql 你们是怎么发现和处理的
- 1.1 发现慢sql:
- 1.1.1 通过开启mysql 的慢日志:
- 1.1.2 通过Skywalking 平台:
- 1.2 针对慢sql 你们是怎么处理的:
- 二、你了解过索引吗
- 2.1 索引是什么:
- 2.1.1 索引为什么要用b+树实现,二叉树,b树不行吗
- 2.1.2 你都知道哪些索引:
- 2.1.3 你知道mysql 的回表吗:
- 2.1.4 你知道mysql 的覆盖索引吗:
- 2.1.5 当项目中遇到深分页你们怎么处理的:
- 2.1.6 你们项目中通常都对表中的哪些字段创建索引
- 2.1.7 你们有没有遇到过索引失效的情况,你们是怎么排查的
- 总结
前言
你们项目都使用过哪些关系型数据库,Mysql 用过吗,针对线上慢查询你们是怎么排查的,索引是什么,你们是怎么使用索引进行优化的。本文重点对面试的问题进行介绍,祝愿每位程序员都能上岸!!!
一、线上的慢sql 你们是怎么发现和处理的
1.1 发现慢sql:
1.1.1 通过开启mysql 的慢日志:
首先:慢sql 通体现在页面数据加载缓慢,接口的响应时间过长。
其次:慢sql 是测试人员进行压测时,在预发布环境发现有些接口的响应时间超过了2s,然后对我们进行了反馈。
然后:我们在预发布环境开启mysql 的慢日志,记录超过2s 的sql,将其存放在log 文件中:
最后:配置完成后我们重启了mysql ,然后让测试人员配合压测,从慢日志中拿到了慢sql:
1.1.2 通过Skywalking 平台:
我们当时的系统部署了运维的监控系统Skywwalking,在展示的报表中可以看到是哪一个接口比较慢,并且可以分析这个接口哪部分比较慢,这里可以看到SOL的具体的执行时间,所以可以定位是哪个sql出了问题。
1.2 针对慢sql 你们是怎么处理的:
在Mysql 中提供了Explain 跟上要执行的sql ,可以看到sql 语句的执行计划,从结果中,我们主要关注sql 查询中对于索引的使用情况;
在结果中有个type 的字段,它是用来干嘛的,它都有哪些类型:
通常如果type 出现了 index 全索引树的扫描,和all 全表扫描,意为这我们需要对sql 进行优化。
二、你了解过索引吗
2.1 索引是什么:
索引是一种b+ 树的数据结构,这种结构以某种方式引用数据,Myql 通过索引可以快速的定位数据。
2.1.1 索引为什么要用b+树实现,二叉树,b树不行吗
Mysql 使用b+ 树作为数据存储的底层结构,是综合了数的高度与查询效率的稳定性,综合考虑决定的。
首先,对于二叉树,二叉搜索树,红黑树来说,本质上它们都是二叉树,使用它们存储数据树的高度会变得非常大;其次二叉树在最坏的情况,会退化到链表结构,虽然红黑树可以通过左旋和右旋来维持树的平衡,但是数的总体高度依然很高,树的高度越高检索数据需要花费的时间也就越多。
b 树是在二叉树的基础上进行的优化,他可以有多个分叉,以此来降低树的高度
B+Tree是在BTree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。b+ 树比b 树更有优势的地方在于:
- 非叶子节点只存储指针,磁盘读写代价抵
- 数据都在叶子节点查询效率稳定
- 叶子节点双向链表,更好支持范围查询
2.1.2 你都知道哪些索引:
通常在Mysql 中,我们会用到它的聚促索引和二级索引;
它们的区别在于:
你知道聚促索引的选取规则吗:
- 如果存在主键,主键索引就是聚集索引。
- 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。2
- 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。
2.1.3 你知道mysql 的回表吗:
Mysql的回表是先到二级索引中查询到id ,然后在去聚簇索引中遍历需要的id 获取到正好数据,因为有了第二次聚簇索引的遍历,所以这个过程被称之为回表。
2.1.4 你知道mysql 的覆盖索引吗:
覆盖索引是指查询使用了索引,返回的列,必须在索引中全部能够找到。
2.1.5 当项目中遇到深分页你们怎么处理的:
如sql 语句中有 limit 10000000 10 ,怎么保证sql 的效率。这种我们通查可以使用覆盖索引+子查询来处理(在子查询中得到需要的数据主键id);
2.1.6 你们项目中通常都对表中的哪些字段创建索引
- 针对于数据量较大,且查询比较频繁的表建立索引。单表超过10万数据(增加用户体验)
- 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
- 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
- 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
- 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
- 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率,
- .如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。
你们创建索引遵循的原则有哪些;首先,我们一般在表的数据量达到10w时,会对经常作为查询条件,分组,排序的字段创建索引;然后,我们会创建覆盖索引,然后一条sql 返回的值尽量使用覆盖索引;最后,对于大文本的字段,内容较长,我们通常使用前缀索引。
- 数据量较大,且查询比较频繁的表;
- 常作为查询条件、排序、分组的字段
- 字段内容区分度高
- 内容较长,使用前缀索引
- 尽量联合索引
- 要控制索引的数量
- 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它
2.1.7 你们有没有遇到过索引失效的情况,你们是怎么排查的
项目中在表的字段建立了索引,但是查询的时候却没有用到过;通常是由于违反了索引查询的一些原则,比如:没有遵守最左匹配,在查询时 % 在前面,对字段进行了运算。
说下索引的最左匹配原则:
通常最左匹配原则体现在复合索引上,因为我们是对多个字段共同使用了一个索引树,索引树存储的节点数据也是按照 索引字段 从左到右进行建立的,此时当我们查询时,跳过了前面的字段,直接使用后面的字段进行查询,此时就有可能造成索引失效。
在索引上的字段进行了运算:
字符串没有使用引号:
以% 开头 的查询:
总结
本位对线上慢sql 的排查及优化,以及索引的一些面试问题进行总结。