近似子问题
1、一条SQL语句执行很慢的原因有哪些?(据说腾讯面试题)
2、一个WEB程序突然很慢的原因?
3、系统上线几个月后突然变慢的原因?
4、你的网站访问很慢的原因?
5、浏览器输入地址后发生了什么?(据说百度面试)
等等…
全局到细节(分类分析)
遇到此类问题,我们要揣测面试官想听到什么样的回答,他想考察的知识点有哪些?
其实,可以问出的知识体系相当的庞大。
一般而言,应该先站在一个比较全局的角度去思考问题,分类分重点一一阐述。
其次,最好举个相关的例子说明,更能表达清楚。
最后,需要注意的是,我们在说明白问题原因之后,必须给上一个切实可行的解决思路或者说具体方案。
回到主题
比如说,最近本人有个面试问题就是:
- 发现程序反应很慢是什么原因?
如果说是后端面试,那么我们可以完全把问题方向 理解成 后端反应慢的问题。
分情况分析
1、外部条件没变,一直都很慢?
(1)代码问题
(2)服务器问题
(3)数据库问题
2、只是偶尔很慢?(抛开网络信道情况)
(1)服务器问题
(2)数据库问题
3、以前正常,只是近期开始变很慢?
(1)代码问题
(2)数据库问题
(3)服务器问题
阐述
1-1:假设:从程序开发完成部署后,外部条件不变情况下,一直都很慢,是代码问题
编码不规范,导致编译或运行慢
如:
没有符合高内聚低耦合原则;
某些条件判断、循环语句,不规范导致的逻辑问题,由此引发程序执行了无意义的代码,时间复杂度上升;
数据结构使用不良,算法实现效率低下,导致函数处理慢
如:
像Java中 ArrayList、String、StringBuilder、StringBuffer、HashMap、HashTable、CurrentHashMap等等数据结构使用情况都是严格规定的;
算法的话当然不用说,非常重要,像 使用 BF 算法暴力递归 搜寻子字符串,和使用 KMP 算法 动态规划的去查找一个子串,时间复杂度是指数级提升;
设计模式上不讲究或者错误使用,导致资源占用高和执行效率低
如:
最简单的工厂模式、单例模式就是很好的证明,减少资源开销,提神速度和性能;
解决:
检查并优化代码(规范、算法、设计模式)
1-2:假设:从程序开发完成部署后,外部条件不变情况下,一直都很慢,是服务器问题
服务器硬件配置低,达不到咱们程序运行环境的最佳配置
服务器软件环境安装或者配置有问题
服务器带宽问题
解决:
先从软件检查,排除了软件环境和配置,就使劲砸钱升硬件,买最豪华套餐
1-3:假设:从程序开发完成部署后,外部条件不变情况下,一直都很慢,是数据库问题
索引问题(如果有一定数据量)
a.字段没有设置索引
b.字段有索引,没有命中
c.特殊骚操作,导致没有使用上索引
其他问题
不规范频繁删除、插入等
如:
1、字段 c 没有建立索引
1 | select c,d,e from t where 100 < c and c < 1000000; |
2、加了 c 和 d 两个字段复合索引 INDEX(c,d),但是没加 a 索引。
1 | select c,d,e from t where d > 100 and c < 100000 and e < 10000; |
虽然,不符合复合索引最左匹配原则,但是查询优化器会自动处理,然而后面的 e 会导致退化为全表查询
3、函数操作导致没有用上索引
1 | select c,d,e from t where pow(c,2) = 1000; |
4、在字段的左边做了运算,不会用上索引
1 | select c,d,e from t where c - 1 = 1000; |
解决:
1、优化SQL语句
2、建立有效的字段索引
关于SQL无法命中索引情况,可以详细了解下。
2-1 假设:程序偶尔反应很慢,是服务器问题
高峰期,服务器负载过高,导致IO占用、CPU、内存资源紧缺
如:某些时候,并发请求服务的数量太多,处理不过来
解决:
1、微服务拆分
2、分布式架构(负载均衡)
2-2 假设:程序偶尔反应很慢,是数据库问题
数据库 在 刷新 脏页【重点】
以下四种情况会刷新脏页:
a.redolog写满了
b.内存不够用了
c.MySQL 认为系统“空闲”
d.MySQL 正常关闭的时候
当我们要往数据库插入一条数据、或者要更新一条数据的时候,
我们知道数据库会在内存中把对应字段的数据更新了,
但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,
而是把这些更新的记录写入到 redo log 日记中去,等到空闲的时候,
在通过 redo log 里的日记把最新的数据同步到磁盘中去。
redolog写满了就没办法等到空闲的时候再把数据同步到磁盘的,
只能暂停其他操作,全身心来把数据同步到磁盘中去的,
而这个时候,就会导致我们平时正常的SQL语句突然执行的很慢,
所以说,数据库在在同步数据到磁盘的时候,就有可能导致我们的SQL语句执行的很慢了。
注:
当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。
内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。
事务锁(拿不到锁,一直等)
如:我们要执行的这条语句,刚好这条语句涉及到的表,别人在用,
并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了。
或者,表没有加锁,但要使用到的某个一行被加锁了,就等吧。
注:show processlist 查看当前状态
解决:
除了能该配置,我还能干啥? 不可能不让它 做 redolog 也不可能偷偷把 事务锁 给干掉了。慢是慢,但是稳啊!
3-1:假设:近期开始变很慢,是代码问题
跟踪请求日志,找到最慢的功能模块,检查近期修改或发布的版本记录
如:某一次上线,某个地方代码修改后有逻辑或规范问题
解决:
加班改,优化(逻辑、算法等)
3-2:假设:近期开始变很慢,是服务器问题
服务器硬件配置不够用了
如:内存
服务器软件配置不合适了
如:并发数、连接数
其他软件环境问题
如:加了其他内容,或者更新了啥
解决:调试改环境配置,加硬件
3-3:假设:近期开始变很慢,是数据库问题
索引【主要】
如:随着系统运行时间增加,数据量增大,查询字段未设置索引、索引未命中等
锁
如:近期新增功能中,使用到了新的锁,导致等待时间变长
其他配置不适用了
如:连接数、语句执行数
解决:
1、主要从索引出发,保证用上索引
2、检查事务锁情况、配置等
最后
其实每个具体问题不是绝对仅限于三个大的场景下,只是根据可能性更高去分析。
具体情况,还得回到实践中去,跟踪、调试才能一步步定位问题的所在,然后解决它。
个人总结,水平有限,欢迎批评指正!