生产环境中出现一个问题,点击一个菜单,等待几秒后,弹出一个错误提示框。然而在测试环境没有这个问题。两个环境的区别是数据的区别,生产环境数据较多。
当时初步分析可能是超时导致:
点击菜单后,调用远程的一个dubbo服务,目前生产环境的dubbo服务配置如下,超时时间统一配置为了10秒:
而页面上的错误提示框大概就是在10秒左右弹出,所以问题应该处在这里。
修改方法有两个,①调整该dubbo服务的超时时间,覆盖统一配置的10秒,②排查服务慢的原因,进行调优。
方法①简单,但比较粗暴,而且还需要重新发布版本,重新部署,所以优先考虑方法②
经过排查,该dubbo服务中的用到sql如下:
SELECT
p.project_id, p.project_no, p.linkman(……这里大概有30多个列,涉及机密信息,所以不在此列出)
FROM
外表 p
WHERE NOT EXISTS
(SELECT ps.project_id FROM 内表 ps WHERE ps.project_id = p.project_id AND ps.special_id = 'xxxxxxxxxxxx')
AND p.is_delete = 0
ORDER BY p.cre_date DESC
外表数据大概是2万,内表大概是2千,数据量也不大,这个语句初步看,用的是not exists,没有用效率低的not in,怎么会执行数几秒?用客户端连上生产环境的数据库执行该sql,用时达7秒,很意外的一个数字。经排查,内表除了主键索引外是没有辅助索引的,not exists的执行原理主要是用到了内表上的索引。
在内表上针对关联字段project_id和where语句中special_id字段建立索引后,语句执行耗时不到1秒,这样内表查询时用到了覆盖索引,project_id字段直接从索引取出。
鉴于此,not exists这样的写法,不论表数据量是否大,建立索引都是有利的,而且等到数据量过大时再建立索引,会耗时很久,并且有可能导致锁表问题,导致生产事故。5.6版本中引入的innodb-online-ddl,在新建或者删除二级索引的时候可以并发执行DML语句,除了建索引操作会消耗硬件资源,不影响表的正常使用,但为了保险起见,索引还是尽早加比较好。