热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

IN&EXISTS与NOTIN&NOTEXISTS的优化原则小结

下面只是从理论上提出了一些建议,最好的原则是大家在上面的基础上,能够使用执行计划来分析,得出最佳的语句的写法。

下面只是从理论上提出了一些建议,最好的原则是大家在上面的基础上,能够使用执行计划来分析,得出最佳的语句的写法。

1. EXISTS的执行流程
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 对于in 和 exists的性能区别:
如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in,反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。
其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了
另外IN时不对NULL进行处理,如:
select 1 from dual where null in (0,1,2,null)
结果为空。

2. NOT IN 与NOT EXISTS:
NOT EXISTS的执行流程
代码如下:
select .....
from rollup R
where not exists ( select 'Found' from title T
where R.source_id = T.Title_ID); 可以理解为:
代码如下:
for x in ( select * from rollup )
loop
if ( not exists ( that query ) ) then
OUTPUT
end if;
end; 注意:NOT EXISTS 与 NOT IN 不能完全互相替换,看具体的需求。如果选择的列可以为空,则不能被替换。
例如下面语句,看他们的区别:
select x,y from t;
x y
------ ------
1 3
3 1
1 2
1 1
3 1
5
select * from t where x not in (select y from t t2 )
no rows
select * from t where not exists (select null from t t2
where t2.y=t.x )
x y
------ ------
5 NULL
所以要具体需求来决定
对于not in 和 not exists的性能区别:
not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,并使用anti hash join.
如果主查询表中记录少,子查询表中记录多,并有索引,可以使用not exists,另外not in最好也可以用/*+ HASH_AJ */或者外连接+is null
NOT IN 在基于成本的应用中较好
比如:
代码如下:
select .....
from rollup R
where not exists ( select 'Found' from title T
where R.source_id = T.Title_ID); 改成(佳)
select ......
from title T, rollup R
where R.source_id = T.Title_id(+)
and T.Title_id is null;
或者(佳)
sql> select /*+ HASH_AJ */ ...
from rollup R
where ource_id NOT IN ( select ource_id
from title T
where ource_id IS NOT NULL )
注意:上面只是从理论上提出了一些建议,最好的原则是大家在上面的基础上,能够使用执行计划来分析,得出最佳的语句的写法。
'//=============================
exists,not exists总结

1 exists
SELECT * FROM anken_m WHERE EXISTS(
SELECT my_list_temp_m.sales_code
FROM my_list_temp_m
WHERE my_list_temp_m.sales_code=anken_m.sales_code)
说明:
1) 查询在anken_m表和my_list_temp_m表中都存在的sales_code。
2) sales_code是anken_m的主键,my_list_temp_m的外键。
注意:
1) 外层查询表anken_m是查询的对象。
2) 内层查询表my_list_temp_m是条件对象。
3) 内外层的查询表不能相同。
4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。
5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。

2 not exists
SELECT * FROM anken_m WHERE NOT EXISTS(
SELECT my_list_temp_m.sales_code
FROM my_list_temp_m
WHERE my_list_temp_m.sales_code=anken_m.sales_code)
说明:
1) 查询在anken_m表中存在,但是在my_list_temp_m表中不存在的sales_code。
2) sales_code是anken_m的主键,my_list_temp_m的外键。
注意:
1) 外层查询表anken_m是查询的对象。
2) 内层查询表my_list_temp_m是条件对象。
3) 内外层的查询表不能相同。
4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。
5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。

3 综合运用
UPDATE anken_m
SET(plan_type_code, branch_name, business_type_code)
=(SELECT anken.plan_type_code,anken.branch_name,anken.business_type_code
FROM anken
WHERE anken.sales_code=anken_m.sales_code)
WHERE EXISTS (
SELECT anken.sales_code
FROM anken,my_list_temp_m
WHERE my_list_temp_m.sales_code=anken.sales_code
AND anken.sales_code=anken_m.sales_code
)
说明:
1) 用一个表的记录数据更新另一个表的记录数据。
2) 用一个SQL语句进行批量更新。
2) sales_code是anken,anken_m的主键,my_list_temp_m的外键。
注意:
1) set 语句中的要被更新字段必须跟数据源字段一一对应,另外数据源查询中的条件必须限定一条记录。也就是根据sales_code可以唯一确定anken的一条记录,和anken_m的一条记录,这样才能保证要被更新的记录和数据源记录的主键是相同的。
2) 根据WHERE EXISTS语句可以确定数据源记录的范围,也就是可以用anken表中哪些记录更新anken_m表。所以anken_m不需要在WHERE EXISTS语句中的FROM后添加。
推荐阅读
  • 如何在不同数据库中提取前N%的记录
    本文详细介绍了如何在SQL Server、Oracle和MySQL等不同数据库中提取前N%的记录。通过具体的示例和代码,帮助读者理解和掌握这些方法。 ... [详细]
  • Nacos 0.3 数据持久化详解与实践
    本文详细介绍了如何将 Nacos 0.3 的数据持久化到 MySQL 数据库,并提供了具体的步骤和注意事项。 ... [详细]
  • 解决SQL Server数据库sa登录名无法连接的问题
    在安装SQL Server数据库后,使用Windows身份验证成功,但使用SQL Server身份验证时遇到问题。本文将介绍如何通过设置sa登录名的密码、启用登录名状态以及开启TCP协议来解决这一问题。 ... [详细]
  • 在将Web服务器和MySQL服务器分离的情况下,是否需要在Web服务器上安装MySQL?如果安装了MySQL,如何解决PHP连接MySQL服务器时出现的连接失败问题? ... [详细]
  • SQL 连接详解与应用
    本文详细介绍了 SQL 连接的概念、分类及实际应用,包括内连接、外连接、自连接等,并提供了丰富的示例代码。 ... [详细]
  • 本文介绍了如何使用Flume从Linux文件系统收集日志并存储到HDFS,然后通过MapReduce清洗数据,使用Hive进行数据分析,并最终通过Sqoop将结果导出到MySQL数据库。 ... [详细]
  • 本文介绍了如何在 Spring 3.0.5 中使用 JdbcTemplate 插入数据并获取 MySQL 表中的自增主键。 ... [详细]
  • BIEE中的最终用户界面被称为Presentation Layer(展现层)。展现层呈现的内容与用户在Web报表开发界面中看到的一致,使用业务语言进行描述,隐藏了技术细节,如星型模型。本文将详细介绍展现层的设计要点及其与业务模型层的关系。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • PHP 使用 Cookie 进行访问授权的方法
    本文介绍了如何使用 PHP 和 Cookie 实现访问授权,包括表单验证、数据库查询和会话管理等关键步骤。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 操作系统如何通过进程控制块管理进程
    本文详细介绍了操作系统如何通过进程控制块(PCB)来管理和控制进程。PCB是操作系统感知进程存在的重要数据结构,包含了进程的标识符、状态、资源清单等关键信息。 ... [详细]
  • 基于iSCSI的SQL Server 2012群集测试(一)SQL群集安装
    一、测试需求介绍与准备公司计划服务器迁移过程计划同时上线SQLServer2012,引入SQLServer2012群集提高高可用性,需要对SQLServ ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 深入解析HTML5字符集属性:charset与defaultCharset
    本文将详细介绍HTML5中新增的字符集属性charset和defaultCharset,帮助开发者更好地理解和应用这些属性,以确保网页在不同环境下的正确显示。 ... [详细]
author-avatar
yaunye
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有