IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况
发布日期:2021-06-29 05:05:51 浏览次数:2 分类:技术文章

本文共 2214 字,大约阅读时间需要 7 分钟。

SQL里的EXISTS与in、
not exists与
not in 效率比较和使用

在 MSSQL 中,插入(insert)一条记录很简单,但是一些特殊应用,在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,本文介绍的就是这个问题的解决方案。

问题: 我创建了一个表来存放客户信息,我知道可以用 insert 语句插入信息到表中,但是怎么样才能保证不会插入重复的记录呢?
答案: 可以通过使用 EXISTS 条件句防止插入重复记录。
示例一:插入多条记录 
假设有一个主键为 client_id 的 clients 表,可以使用下面的语句:
Code:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT supplier_id, supplier_name, 'advertising'
FROM suppliers
WHERE 
not 
exists (select * from clients
where clients.client_id = suppliers.supplier_id);

 

个人批注:not exists不存在,也就是说后面的括号中只要返回了数据那么这个条件就不存在了,可以理解为括号前的not

exists是一个左表达式 ,括号后的查询是一个右表达式,只有当右表达式返回的也是not exists(即后面的查询出来的结果是非空的)时,等式才成立。

 

示例一:插入单条记录 
Code:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE 
not 
exists (select * from clients
where clients.client_id = 10345);

使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。

系统要求进行SQL优化,对效率比较低的SQL进行优化,使其运行效率更高,其中要求对SQL中的部分in/not in修改为exists/not exists

修改方法如下:

in的SQL语句

SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime 

FROM tab_oa_pub WHERE is_check=1 and 
category_id in (select id from tab_oa_pub_cate where no='1') 
order by begintime desc

修改为exists的SQL语句

SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime 
FROM tab_oa_pub WHERE is_check=1 and 
exists (select id from tab_oa_pub_cate where tab_oa_pub.category_id=convert(int,no) and no='1') 
order by begintime desc

分析一下exists真的就比in的效率高吗?

    我们先讨论IN和EXISTS。

    select * from t1 where x in ( select y from t2 )
    事实上可以理解为:
    select * 
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;
    ——如果你有一定的SQL优化经验,从这句很自然的可以想到t2绝对不能是个大表,因为需要对t2进行全表的“唯一排序”,如果t2很大这个排序的性能是不可忍受的。但是t1可以很大,为什么呢?最通俗的理解就是因为t1.x=t2.y可以走索引。但这并不是一个很好的解释。试想,如果t1.x和t2.y都有索引,我们知道索引是种有序的结构,因此t1和t2之间最佳的方案是走merge join。另外,如果t2.y上有索引,对t2的排序性能也有很大提高。
    select * from t1 where exists ( select null from t2 where y = x )
    可以理解为:
    for x in ( select * from t1 )
    loop
       if ( exists ( select null from t2 where y = x.x )
       then 
          OUTPUT THE RECORD!
       end if
    end loop
    ——这个更容易理解,t1永远是个表扫描!因此t1绝对不能是个大表,而t2可以很大,因为y=x.x可以走t2.y的索引。
    综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。 

我们要根据实际的情况做相应的优化,不能绝对的说谁的效率高谁的效率低,所有的事都是相对的

转载地址:https://blog.csdn.net/zhaokuner/article/details/9817127 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Eclipse快捷键
下一篇:在IE浏览器中resize事件执行多次的解决方法

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月19日 13时32分12秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章