SQL优化之-In和Exists

IN和EXISTS是极具争论的两个单词,我们通过一个普通的示例来看看两者的效率之差:

有A,B两张表,A的结构如下:

CREATE TABLE A(
  aid    VARCHAR2(16),
  bid    VARCHAR2(16),
  CONSTRAINT pk_a PRIMARY KEY (aid, bid)
);

 

B的结构如下:

CREATE TABLE B(
  bid    VARCHAR2(16),
  bname    VARCHAR2(16),
  CONSTRAINT pk_b PRIMARY KEY (bid)
);

 

其中A.bid和B.bid关联,为提高查询速度,Oracle已经自动对两张表的主键建立了索引。

问题:A和B中的数据都过百万条,写一条Oracle支持的SQL语句,把A中bid在B中不存在的记录删除。

 

根据表结构,很容易就想到用IN来解决,于是写出:

DELETE FROM A a WHERE a.bid NOT IN (SELECT bid FROM B)

遗憾的是,它的执行效率很低,两张表的数据达到百万条时,这条SQL的执行无疑会让你失去耐性。

 

我们借助PLSQL Developer来看看它的执行计划(选择SQL按F5即可):

 

低效率SQL的执行计划

 

从图中可以看出,这条SQL在执行时分别对表A和B都进行了一次全表扫描,没有用到索引,这无疑是最差的执行效果了,所以需要优化,略做思考,写出一条同等执行效果的SQL:

DELETE FROM A a WHERE NOT EXISTS (SELECT b.bid FROM B b WHERE a.bid = b.bid)

这条SQL也不难理解,只是把IN换成了EXISTS,我们再来看看它的执行计划:

 

高效率的SQL执行计划

 

从图中可以看出,这条SQL在执行时只对表A进行了全表扫描,而对B扫描时使用了索引PK_B,所以效率会有百倍千倍的提升。

 

测试:

A表数据1W条,B表数据1W条

DELETE FROM A a WHERE a.bid NOT IN (SELECT bid FROM B) --执行所用时间:53.313s
DELETE FROM A a WHERE NOT EXISTS (SELECT b.bid FROM B b WHERE b.bid = a.bid)--执行所用时间2.266s

 

A表数据2W条,B表数据2W条

DELETE FROM A a WHERE a.bid NOT IN (SELECT bid FROM B) --执行所用时间:1231.609s
DELETE FROM A a WHERE NOT EXISTS (SELECT b.bid FROM B b WHERE b.bid = a.bid)--执行所用时间3.734s

 

可以看出,随着记录数的增加,效率悬殊越来越大。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值