SQL 优化案例之变更表结构

从慢日志报表中看到一条很长的SQL

select 
  id 
from
  myinfo 
WHERE 1 = 1 
  and ((
    SUBSTRING_INDEX(location_axis, '$', 3) like concat('%$', 2334) 
    or SUBSTRING_INDEX(location_axis, '$', 3) like concat(concat('%$', 2334), '$%')
  ) 
  or (
    SUBSTRING_INDEX(location_axis, '$', 3) like concat('%$', 2337) 
    or SUBSTRING_INDEX(location_axis, '$', 3) like concat(concat('%$', 2337), '$%')
  ) 
  or (
    SUBSTRING_INDEX(location_axis, '$', 3) like concat('%$', 2340) 
    or SUBSTRING_INDEX(location_axis, '$', 3) like concat(concat('%$', 2340), '$%')
  ) 
  or (
    SUBSTRING_INDEX(location_axis, '$', 3) like concat('%$', 2353) 
    or SUBSTRING_INDEX(location_axis, '$', 3) like concat(concat('%$', 2353), '$%')
  ) 
  or (
    SUBSTRING_INDEX(location_axis, '$', 3) like concat('%$', 2367) 
    or SUBSTRING_INDEX(location_axis, '$', 3) like concat(concat('%$', 2367), '$%')
  ) 
  or ......

询问开发得知是通过程序拼成的sql

表中存入的location_axis是区域信息,存三个区域,用$分隔,如 $1$2$3,可以看出要实现的是匹配值是否在location_axis中的第一个域或第二个域中

匹配的值是从另一个表中根据条件获取的如:

select it_area_id itinfo where dep_id='0111'

问题:繁琐、前缀为%无法使用索引,导致比较慢

优化方式:

将第一个地域编码和第二个分别存在单独的列中,然后和表it_area_id进行关联查询

变更表结构

alter table myinfo add first_axis varchar(10),add sec_axis varchar(10);
update myinfo t1 inner join (select id,SUBSTRING_INDEX(SUBSTRING_INDEX(location_axis,'$',2),'$',-1) as c1 from itinfo)t2 using(id) set t1.first_axis=t2.c1; 
update myinfo t1 inner join (select id,SUBSTRING_INDEX(SUBSTRING_INDEX(location_axis,'$',3),'$',-1) as c1 from itinfo)t2 using(id) set t1.sec_axis=t2.c1;   

查询语句变为

select opr_bo_id from myinfo t1 inner join itinfo t2 on t1.first_axis=t2.it_area_id or t1.sec_axis=t2.it_area_id where t2.dep_id='0111';

结果达到毫秒级别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值