# 600万数据表未建关键索引导致系统整体缓慢
# 背景
客户系统整体使用缓慢,没有卡顿1分钟以上的,打开协同公文、处理相关数据等,都是10秒~20秒的样子。
# 初步分析过程
通过logs_sy/capability.log日志分析,后端相关操作确实很多在20秒以上,说明性能问题出在OA服务器上面。
如下图,每一行最后那个数字就是请求执行耗时,单位毫秒,以23278MS为例,等于请求在服务器上执行了23.278秒。
下一步是分析服务器什么导致了慢,服务器慢有很多种原因:CPU 100%、内存100%、磁盘IO性能低+大量读写操作、请求数据库慢等等。
访问服务器,查看CPU利用率较低,不存高负载情况,排除CPU问题。
系统管理员-系统监控导出的Jvm使用情况,内存占用极少,排除内存问题。
再检查JDBC数据库连接情况,发现晚上6点下班期间,在线用户不高的情况下,还存在十多个连接,略有不正常!
一般在线用户不高(200人以内)的情况下,busy connection活跃连接也就1~5个
# 深度分析
排除CPU、内存问题后,下一步就是分析Java程序问题,通过Thread Dump看到底什么代码执行慢:
这种情况,需要两台电脑配合了。
一台电脑,用系统管理员登录 - 系统监控 - 找到底部Thread Dump链接;
另一台电脑,用普通用户登录,复现慢的问题。
当另一台电脑,开始复现慢的问题,从第一秒慢开始,系统管理员立刻点击Thread Dump,然后每隔3秒都点击一次Thread Dump,一直这样,直至那台电脑卡顿结束。
随后提供三份文件:
1、把刚才慢时打开的所有Thread Dump另存为导出来
2、把刚才慢时的logs_sy/capability.log导出来
3、把刚才慢时前后半小时的数据库awr报告导出来
通过日志分析,慢的请求都是卡在数据库上:
查看awr报告,发现慢的数据库都卡在数据库磁盘IO上:
数据库内存配置足够丰富,给到了57G:
查看awr的SQL耗费列表,从各种维护看,占用服务器资源最高的几乎都是三条SQL:
导出SQL发现都是查询FILE_MAP表:
select filesecret0_.FM_ID as FM1_317_, ...... from FILE_MAP filesecret0_ where filesecret0_.FILE_ID=:1 and filesecret0_.FILE_TYPE=:2
三条资源耗费最大的SQL均用到了where FILE_ID=?
,此时重点怀疑:FILE_MAP表是否存在针对FILE_ID的关键索引。
通过索引检查发现FILE_ID除了主键外,没有索引,同时FILE_MAP表已经有590多万条数据。
# 结论和解决方案
综上,问题结论是程序大量from FILE_MAP where FILE_ID=?
SQL未走索引,导致一直从数据库磁盘块中解析数据而缓慢。
解决方案是,针对FILE_MAP表高频的where条件字段FILE_ID增加索引 : CREATE INDEX FILE_MAP_FILEID ON FILE_MAP(FILE_ID);
,随后问题解决。