---
title: 《面试实录》 字节二面，SQL执行慢的原因？如何优化？
category: 
  - 对线面试官
  - 面试实录
  - Java
  - MySQL
tag:
  - MySQL
head:
  - - meta
    - name: keywords
      content: 面试实录,MySQL,JAVA,大厂面试,慢SQL优化
    - name: description
      content: 字节二面，SQL执行慢的原因？如何优化？涉及知识点：MySQL慢 SQL 查询排查、SQL优化相关
---

本期是【**面试实录**】系列文章的第 **2** 期，持续更新中.....。

- 欢迎关注+订阅，持续更新中！！！致力打造校招核心面试攻略~
- 根据秋招春招上岸大厂面试经历以及身边朋友上岸面试录音模拟面试现场，并整合面试常考知识点，通俗有趣的去讲解 `八股文`，不一样的系列，轻松掌握知识~

【**面试实录**】专栏系列目前已经连载 **2** 篇了，据说看了这个系列的朋友都拿到了大厂offer~

[【BAT高频面点】百度二面，Sychronized原理详解](./1)

# 考题速查

本期会通过面试模拟探讨MySQL高级，`一条SQL执行慢的原因，并给予解决方案`

`本期题改编自 ——202届秋招 字节 二面`

# 面试现场

叮叮叮......

**面试官**：“你好，我是XX面试官，请问是小龙吗？”

**小龙**：“您好，面试官，我是小龙”

**面试官**：“好的，现在有空吗，我们开始面试吧”

**小龙**：“嗯嗯，准备好啦”

.......

other questions

.......

**面试官**：“我看你简历写熟悉 `MySQ`L 使用，还有相关调优经验，是吗？”

**小龙**：“是的呢！在实习时和主管一起解决过相关问题。”

**面试官**：“好的，那你们项目中假如遇到慢 SQL 查询，你们是怎样排查和解决的呢？”

**独白**：“送分题来了”

**小龙**：”总的来说，我们应该从`索引、架构、网络、I/O吞吐量、内存、锁、SQL语句`等各个方面去分析，但是由于涉及范围太广，如果不能理清思路去逐步分析，便会使得排查效率极低。“

**面试官**：”噢，怎样做呢？“

**小龙**：”为了快速定位，针对这个问题，我们得对系统有个全局监控，然后分情况讨论啦。“

**小龙**：”如果`大多数情况下都正常，偶尔很慢`，则可能是：数据库在刷新脏页，例如 redo log 写满了需要同步到磁盘；或者执行的时候，**遇到锁**，如表锁、行锁；又或许你这次执行的 SQL 写的有问题，由于真实业务数据量又大，就导致速度极慢。“

**小龙**：”当然这是我们主要考虑的原因，另外，也有可能是当时网络不好，内存不足，I/O吞吐量小，形成了瓶颈效应，不过一般公司不会出现这种情况，用的设施都很好的。“

**面试官**：”嗯嗯，接着说。“

**小龙**：”还有就是假如`这条 SQL 语句一直执行的很慢`。可能是没有用上索引或则索引失效：**例如该字段没有索引；或则由于对字段进行运算、函数操作导致无法用索引**。“

**小龙**：”然后这时候我们可以有个大概方向，然后我们还得结合具体手段去定位慢查询 SQL。“

**面试官**：”说说看哈~“

**小龙**：”首先数据库中设置 SQL 慢查询，我们可以修改配置文件，在 my.ini 增加几行: 主要是慢查询的定义时间（超过2秒就是慢查询），以及慢查询log日志记录（ slow_query_log）或者直接通过命令行，通过MySQL数据库开启慢查询。“

```sql
[mysqlld]
//定义查过多少秒的查询算是慢查询，我这里定义的是2秒
long_query_time=2
#5.8、5.1等版本配置如下选项
log-slow-queries="mysql_slow_query.log"
#5.5及以上版本配置如下选项
slow-query-log=On
slow_query_log_file="mysql_slow_query. log"

//记录下没有使用索引的query
log-query-not-using-indexestpspb16glos dndnorte/t


mysql>set global slow_query_log=ON
mysql>set global long_query_time = 3600;
mysql>set global log_querise_not_using_indexes=ON;
```

**小龙**：”然后当出现慢查询时，我们可以去分析**慢查询日志**。我们可以使用 `show processlist` 命令定位低效率执行 SQL，也可以用 `explain` 分析 SQL 的**执行计划**。“

**面试官**：”那你使用 `explain`字段，一般会关注哪些字段呢？ “

**小龙**：”其实使用这个我们主要是看有没有使用到索引，索引失效，访问类型等问题。因此，我们大多情况下都是看 **possible_keys**、**key**、**key_len**（这三个一般套起来分析），还有就是**Extra**、**type**（看全表扫描还是索引、还是索引范围扫描）等等。“

**小龙**：“**possible_keys**: 表示查询可能使用的索引，**key**: 实际使用的索引，**key_len**: 使用索引字段的长度，结合起来可以看出索引使用情况。”

**小龙**：“**Extra**（using index：覆盖索引，不回表，尽量覆盖，可以提高效率；**using filesort**：需要额外的排序，不能通过索引得到排序结果，尽量避免这种情况，会使得速度很慢）”

**面试官**：”好的，那么你们是怎样尝试去优化的呢？“

**小龙**：”对于 MYSQL 慢 SQL 语句的优化，我们也可以分几个方面来进行分析（基本覆盖全面啦）：可以从这几方面考虑：`索引+SQL 语句+数据库结构优化+优化器优化+架构优化+I/O+内存+网络。`“

**小龙**：”1、`对于索引`。我们需要从建立索引就开始考虑，索引一般建在 where 和 order by，数据基数要大，区分度要高，不要过度索引，在提高速度同时节约内存。“

**小龙**：”避免索引失效，然后可以尽量覆盖索引，5.6支持索引下推可以使得速度更快；“

**小龙**：“在写多读少的场景下，可以选择`普通索引`而不要`唯一索引`。因为更新时，**普通索引可以使用change buffer进行优化，减少磁盘IO,将更新操作记录到change bufer**，等查询来了将数据读到内存再进行修改。”

**小龙**：”2、`对于 SQL 语句`。我们有很多优化手段，随便举几个，比如分页查询优化，该方案适用于主键自增的表，可以把 Limit 查询转换成某个位置的查询。select * from tb_sku where id>20000 limit 10；”

**小龙**：“Insert 插入语句时，多条插入语句写成一条，同时可以利用主键索引特性让数据有序插入而使效率更高。”

**小龙**：“当然还有很多关于 SQL 写法的优化，这里略提。比如还有，注意 union 和 union all 的区别，union all好；注意使用DISTINCT，在没有必要时不要用，它同 union 一样会使查询变慢，注意临时表、视图等等。”

**面试官**：“好的呢，还有吗？”

**小龙**：“3、对于`数据库结构`。我们可以考虑将字段多的表分解成多个表。有些字段使用频率高，有些低，数据量大时，会由于使用频率低的存在而变慢，可以考虑分开；而对于经常联合查询的表，可以考虑建立中间表。”

**小龙**：“4、对于`架构`，在真实业务场景中，数据量大，并发压力大，我们可以考虑分库分表，纵向、横向分割表，减少表的尺寸，还有采用读/写分离（主库写，从库读）集群模式。”

**小龙**：“当然采用集群，无疑要增加成本，分库分表又要考虑分布式事务、分布式Id、一致性等等问题，因此有好也有坏，当你采用某种措施之前也得考虑其性价比，最终带来的好处更多还是坏处更多。”

**面试官**：“考虑的很全面，好的，还有补充吗？”

**小龙**：“除了这些，我们有时也会考虑，把数据、日志、索引放到不同的 `I/O` 设备上，增加读取速度，`升级硬件`，`提高网速`等等。不过也不能一味的去追求速度，因**为也得考虑成本，所以具体问题具体分析吧**！”

**面试官**：“好的，虽然还有很多细节问题，但是整体思路还行，可见有去思考过。继续加油~”

# 知识总结

本期我们通过面试模拟深入探讨了`慢SQL优化` 的套路，下期再见。**订阅+关注** 持续追更。

## **面试重点**

`MySQL慢 SQL 查询排查、SQL优化相关`