把not in 改成not exists后的优化

 
把not in 改成not exists后的优化

近期, OA数据库里面存在一条慢SQL,其执行时间为 3分16秒。 这条慢SQL语句每个月可能会运行几次,但其运行后,总会导致数据库CPU利用率飙升。然后我就对这个慢SQL语句进行了改写测试,改写后的运行时间降为13s( 虽然还是很慢,但已经速度提升了18倍 )。




具体分析过程如下:
通过慢日志捕捉到的慢SQL及其运行时间:
1  select id,start_member_id,start_date,modify_member_id,modify_date from formmain_0141 where id  not in  (select content_data_id from ctp_content_all where content_template_id='6890363387462501722' and content_data_id is not null  ) limit 20000, 10000\G
Empty set ( 3 min 2.01 sec )

可见, 生产中,该语句运行时间是3分2秒。

我们来看看其执行计划,为什么这么慢:





2、我改写后的索引,用的是  not exists ,内外交互式子查询:

mysql> select id,start_member_id,start_date,modify_member_id,modify_date from formmain_0141 where  not exists  (select 1 from ctp_content_all where content_data_id= formmain_0141.id and content_data_id is not null and content_template_id='6890363387462501722') limit 20000, 10000 ;
Empty set ( 13.84 sec )

看到用not exists后,执行时间降到13秒,效率有显著提升。

我们再看一下优化后语句的执行计划:



把not in改写为not exists快的原因,我想用mysql 5.6的新特性ICP的原理来解释,在改写后的sql语句中,MySQL在从 ctp_content_all表中取出数据的同时,就开始判断是否可以在formmain_0141表中进行id过滤,从而大大减少了上层对SQL层的记录索引,提高数据库整体性能。
反观优化前的那条sql语句,它是把 ctp_content_all 表里面所有符合条件的记录都取出来后,再到 formmain_0141表里进行id字段过滤,所以慢。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28916011/viewspace-2138724/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28916011/viewspace-2138724/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值