not in

在我们平时写SQL时,如果遇到需要排除某些数据时,往往使用 id <> xxx and id <> xxx

进而改进为 id not in (xxx, xxx) ;这样写没有问题,而且简化了SQL,

但是往往有些极端情况,使用not in就会造成极大的性能损耗,例如:

select * from test where id not in (select id from test_back) and info like '%test%';

这样的话 select id from test_back 将成为一个子查询,而且不会走索引,每次走一遍全表扫描

每一条满足info like ‘%test%’的记录都会去调用这个方法去判断id是否不在子查询中,具体的执行计划见下面的例子。

改进方法:

1)使用 testtest_back 进行联合查询, id <> id 明显是不行的,这样只会判断同一关联条件下的一行中的id是否相同,无法做到排除某些id。

2)正确的方式应该使用 **not exists** ,将条件下推到里面,就不会出现子查询了:

select * from test t1 where info like '%test%' and not exists (select 1 from test_back t2 where t2.id = t1.id);