mysql not exists 索引调优——生产环境一个实例

生产环境中出现一个问题,点击一个菜单,等待几秒后,弹出一个错误提示框。然而在测试环境没有这个问题。两个环境的区别是数据的区别,生产环境数据较多。

当时初步分析可能是超时导致:

点击菜单后,调用远程的一个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语句,除了建索引操作会消耗硬件资源,不影响表的正常使用,但为了保险起见,索引还是尽早加比较好。

猜你喜欢

转载自blog.csdn.net/chuixue24/article/details/86624825
今日推荐