ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

sql优化技巧之 not in 改 left join

2022-05-14 19:33:08  阅读:304  来源: 互联网

标签:empid null join emp sql org NULL 逐行 left


在sql语句中,not in是经常会⽤到的⼀种写法,因为这种写法很直观,容易理解。

但如果不注意的话,很容易写出错误的sql,⽽且性能存在严重问题,所以,不建议使⽤not in,要尽量把 not in写法,改为left join。下面给个例子

CREATE TABLE emp
(
empid INT NOT NULL PRIMARY KEY CLUSTERED,
empname VARCHAR(20) NOT NULL,
tel VARCHAR(20) null
)
INSERT INTO dbo.emp
VALUES
(1, '张三','12'),
(2, '李四','34'),
(3, '王五','56'),
(4, '孙六','78'),
(5, '李二','90');

CREATE TABLE org
(
orgid INT NOT NULL PRIMARY KEY CLUSTERED,
orgname VARCHAR(30) NOT NULL,
parentid INT NULL,
empid INT NULL
)
INSERT INTO org(orgid,orgname,parentid,empid)
VALUES
(1, '部长', NULL,1),
(2, '副部长', 1,2),
(3, '组长', 1,3),
(5, '员工', 4,null)

如上sql创建两个表,一个组织表,一个雇员表。现在要查询,emp表中有,但是在org中不存在的empid,用not in 写法自然而然的写出如下的sql

SELECT e.empid,
       e.empname
FROM emp e
WHERE e.empid NOT IN (SELECT empid FROM org)

这个时候理论上讲,孙六和李二的id不在org表中,理应被查出来,来看看查询结果

这是不是要打个问号了,这⾥涉及到not in写法的⼀个坑,就是当not in ⼦查询中有null值,那么整个查询的结果就是空的。由于org表中员工的empid是NULL,所以就找不到值了。改写一下,过滤掉empid是null的情况,查询就有数据了。

SELECT e.empid,
       e.empname
FROM emp e
WHERE e.empid NOT IN (SELECT empid FROM org where empid is not null)

 

看看执行计划,sqlserver的解析是将not in 转成了 left Anti Semi Join。这个是左连接吧,但是 Semi 是什么意思?看下这两个次的意思。Anti 取反,Semi 半独立。

是不是先用左连接后取反的意思?就是说emp表中的每条empid,如果在org表中有记录就不返回。

我们再来看看将not in 改成左连接的写法

SELECT e.empid,
       e.empname
FROM emp e
LEFT JOIN org o
ON o.empid = e.empid
WHERE o.empid IS NULL

执行计划上看少了top,但增加了帅选器。

跟not in是完全一样的开销。这里有个差异就是执行嵌套循环最后返回的行数是20行再进行筛选,而not in 的执行嵌套循环后返回的是最终结果2行。

这里可以看出什么呢,就是not in 的时候要两个表逐行empid的对比Anti ,semi),不在的才返回,在的话就不反回了。

而左连接呢是逐行拼接,不需要逐行empid的对比。链接完就返回去。最后再通过一次empid is null 进行过滤。

数据量少的时候,由于逐行对比的操作没那么多,返回的数据也少,也不需要再进行一次过滤,not in 比left join 的效率要高一些。

但是当数据量大的时候,相比联查,逐行对比的开销的大的多了。

 

 

 

 

 

 

标签:empid,null,join,emp,sql,org,NULL,逐行,left
来源: https://www.cnblogs.com/choii/p/16267629.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有