怎么not in 还不如 not exists ?

not in 不到1秒就执行完了,
not exists 执行较长,都没耐心等。
这是什么情况?

msyql数据库,两张表,一个30万条数据,一个25万条数据:
doctor 医生基本信息表,主键did
doctor_intro 医生额外信息表(有text类型的字段)

not in:

SELECT
    count( * ) 
FROM
    doctor d 
WHERE
    d.did NOT IN ( SELECT did FROM doctor_intro );

not exists:

SELECT
    count( * ) 
FROM
    doctor d 
WHERE
    NOT EXISTS ( SELECT 1 FROM doctor_intro di WHERE di.did = d.did );
阅读 3.5k
2 个回答

not exists效率本来就不高啊...

暂时先不考虑数据库自动进行的编译优化这点,假设两个实现用最朴素的实现方式

not exists本质上就是循环执行doctor数据量次数的select 1 xxx语句,筛选出执行查询没有结果的数据,在这里就是30w或者20w次的select,即便都有索引select起来很快也架不住循环次数多啊

not in一般是先把in里的语句查出来,然后对结果和doctor做一个join关联出匹配的上(in)或者匹配不上(not in)的数据,就算没有优化查询次数也依然比not exists少很多

而且如果not in的子查询有建索引,还可以直接自动优化成一个join语句做两张表的关联以进行索引之间的对比,也不用先把select子查询计算出来再对比,类似
select count(*) from docker d,doctor_intro di where d.did = di.did and d.did is not null and di.did is null(sql随便写的,也没实际执行,可能是错误的,大概可以理解意思就行)
这样一来的话速度就更快了,因为执行时可以直接对比索引文件里的数据是否关联的上,把关联不上的数量取出来就完成了,可以省略掉先查出 SELECT did FROM doctor_intro 这步了

具体上mysql我目前很少用,内部做了哪些优化也不清楚,我上面说的是建立在没有优化的基础上,实际上涉及到sql编译优化后问题就复杂了很多,我目前也是还没学完属于基本不懂的状态,这方面就不多说什么了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题