首先排查系统资源问题,如CPU、内存、磁盘、带宽等,可以通过后台服务器或监控平台查看。如果是CPU占用率过高,需要找出导致此问题的特定进程。可以使用top
命令查看CPU使用率最高的进程,并使用jstack
命令生成进程的堆栈信息来进一步分析。如果发现是频繁的Full GC(垃圾回收)导致CPU使用率高,还需要查看内存快照以分析内存使用情况。对于内存泄漏问题,可以通过free -h
命令查看内存使用情况,并通过jmap -histo:live
命令获取Java进程的对象实例统计,从而找出可能的内存泄漏点。磁盘IO问题也是常见导致系统缓慢的原因之一。通过iostat -x 1
命令可以查看磁盘IO情况,如果某个磁盘的util%值接近或达到100%,则说明磁盘IO已饱和。此时,可以使用iotop
命令进一步查找是哪个进程在频繁读写磁盘。
如果以上排查没有问题,那么可以进一步检查应用服务器,如Jboss或者Tomcat的线程池配置是否合理,请求的排队现象是否严重,重新设置线程池。此外,还需要检查是否存在慢SQL,并对慢SQL进行优化。
我们可以使用MySQL中的explain命令来查看语句的执行计划,定位低性能的SQL语句。对于查询到的SQL语句进一步分析,看其是否load了额外的数据,是否查询了多余的行或者加载了结果中不需要的列等等,对语句进行分析和重写。排查SQL获得索引的情况,修改语句或者索引,并检查表中的数据量是否过大,考虑分库分表等等。
最后可以查看访问慢的服务的调用链,查看一下调用链中的每一步响应时间是否合理以及web服务器是否存在Doss攻击。
关于SQL的调优,也是面试的常考点之一,我们可以从以下几个角度进行考虑。
1.了解和优化表结构:
了解表的字段及其类型和索引情况是基础。通过PROCEDURE ANALYSE工具,可以分析表中的数据并给出优化建议。
处理冗余数据,确保每行数据可以被唯一区分,避免包含其他表中已存在的非关键信息。
对于大数据量的表,拆分成多个小表可以提高性能。例如,可以将不常用的属性分离成单独的小表。
2.创建合适的索引:
在经常用于检索和排序的字段上创建索引,如姓名、员工部门等字段。
控制每个表的索引数量,一般不超过6个,以避免降低插入和更新操作的效率。
避免在索引上进行计算或者使用函数,这会导致数据库无法利用索引而进行全表扫描。
3.使用预编译查询:
尽量使用参数化SQL,这样数据库会对参数化查询进行预编译,从而提高执行速度。
4.调整查询语句中的连接顺序:
在WHERE子句中先写表之间的连接条件,然后再写其他过滤条件,这样可以尽早地过滤掉不必要的记录。
5.压缩多条SQL语句到单一语句中:
每次执行SQL都会经历网络连接、权限校验等耗时过程,尽量减少SQL语句的执行次数。
6.用WHERE字句替换HAVING字句:
HAVING对结果集进行过滤,而WHERE在聚合前就进行过滤,能更有效地减少数据处理量。
7.使用临时表暂存中间结果:
将复杂的查询分解成多个步骤,并使用临时表暂存中间结果,可以减少对主表的多次扫描。
8.优化数据类型和字段:
尽可能使用 varchar/nvarchar代替char/nchar,变长字段更节省存储空间,查询效率也更高。
9.优化SELECT语句:
只选择需要的列而不是所有列(*),避免在WHERE子句中对字段进行NULL值判断,这会导致忽略索引而全表扫描。
10.分析查询计划:
使用EXPLAIN命令查看查询的执行计划,分析各节点的表扫描、索引使用情况,识别并解决性能瓶颈。
11.维护和重建索引:
定期重建或优化索引,保持索引在最佳状态以提高查询效率。
12.避免使用游标处理大数据量:
游标处理大量数据时效率较低,如果必须处理大量数据,考虑优化需求或采用其他方案。