关于oracle中的in和exists的效率问题

来源:百度知道 编辑:UC知道 时间:2024/05/13 02:35:17
最近做报表的时候发现一段SQL执行速度很慢,如下:
select aa19.分公司 as 分公司,
case when count(aa19.独立故障编号) is null then 0 else count(aa19.独立故障编号) end as 月完成,
sum(aa19.月完成历时) as 月完成总历时
from(
select distinct(b.tr_code) as 独立故障编号,a.applycentcompany as 分公司,(case when b.end_time is null then sysdate else b.end_time end-b.apply_time)*24*60 as 月完成历时
from tr_queryregisterforreport a,tr_register b,tr_return_affirm cc
where b.tr_code = a.tr_code
and cc.cs_code=b.cssystem_no
and b.cssystem_no is not null
and b.reserver1=@prompt('客服工单类型:','A','省公司故障统计分析\客服工单类型',Mono,Free,Persistent,,User:4)
and (case b.status when '4' then '1' when '5' then '1' when '6' then '1' else '0' end ) = '1'
and to_number(to_char(cc.tr_end_time,'yyyymm')) = to_number(substr(to_char(to_date(@prompt('查询日期:','A','故障处理明细表\日期1',Mono,Free,Persistent,,User:2),'y

一般来说exists处理起来比in要快很多,优化SQL时一般都是建议将in改为exists,
从你所描述的情况来看:
and a.producttype in (select c.name from tr_ywlx c where c.fenlei!='广视通')---tr_ywlx数据相比之下很小很小,而且这个子查询只是表本身数据的筛选
and exists(select 1 from tr_ywlx c where c.fenlei!='广视通' and c.name = a.producttype)---这里是将tr_ywlx这个数据很小的表与100W笔数据的表关联起来了,形成了一个笛卡尔积,它要将两个表数据一对一进行比对,100W啊,肯定慢了

你给producttype做一个索引再试试

你的这个SQL实在是太复杂了,而且还用到了外链接,不知道为什么要写的这么复杂,我以前用过exists,比in的效率要高出很多。
关于EXISTS与IN的区别:
EXISTS检查是否有结果,判断是否有记录,返回的是一个布尔型(TRUE/FALSE)。
IN是对结果值进行比较,判断一个字段是否存在于几个值的范围中,所以 EXISTS 比 IN 快。

主要区别是:
exists主要用于片面的,有满足一个条件的即可,
in主要用于具体的集合操作,有多少满足条件.

exists是判断是否存在这样的记录,
in是判断某个字段是否在指定的某个范围内。
exists快一些吧 。

in适合内外表都很大的情况,exists适合外表结果集很小的情况。

单说in和exsist,in的效率较差。
原理是什么我也不清楚,用数据库的人都这么说。