查询优化 - 避免完全外连接

时间:2016-02-03 17:11:23

标签: join oracle11g full-outer-join

下面是使用的数据脚本。

create table enab_test (ban varchar2(10),DVR_IND char(1)); 
create table oms_test (ban varchar2(10),DVR_IND char(1));

insert into enab_test values('111111111','Y');
insert into enab_test values('123456789','N');
insert into enab_test values('321654987','N');
insert into enab_test values('444444444','Y');
insert into enab_test values('111111111','Y');
insert into enab_test values('741258963','Y');

insert into oms_test values('111111111','Y');
insert into oms_test values('222222222','N');
insert into oms_test values('333333333','N');
insert into oms_test values('444444444','N');
insert into oms_test values('555555555','Y');
insert into oms_test values('666666666','N');

在这里,我试图获取enab_test表中存在的禁令数量,如果禁止使用dvr_ind =' Y'然后它被计为一个,如果有许多相同的禁令,那么它被总结。如果在dms中有与dvr_ind =' Y'相同的禁令。对于禁令,将计数减去enab_test - oms_test。如果我们在从enab_test - oms_test中减去时有任何负数,则计数为零。和反之(oms_test-enab_test)。

下面是我处理的查询。

select nvl(enab.ENAB_COUNT,0) as ENAB_COUNT, 
case when nvl(enab.ENAB_COUNT,0) - nvl(oms.OMS_COUNT,0) > 0
   then nvl(enab.ENAB_COUNT,0) - nvl(oms.OMS_COUNT,0)
   else 0
end as IN_ENAB_NOT_OMS
from (
select ban, count(*) as OMS_COUNT from oms_test 
where dvr_ind = 'Y'
group by ban order by ban
) oms
full outer join (
select ban, count(*) as ENAB_COUNT from enab_test 
where dvr_ind = 'Y'
group by ban order by ban
) enab
on oms.BAN = enab.BAN

以下是查询的输出

ENAB_COUNT  IN_ENAB_NOT_OMS
    2               1
    0               0
    1               1
    1               1

运行计划对于上述查询,原始数据为

    Plan hash value: 2599843784

---------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                         |  6705K|   166M|       |    10M  (9)| 33:33:17 |
|   1 |  VIEW                 | VW_FOJ_0                |  6705K|   166M|       |    10M  (9)| 33:33:17 |
|*  2 |   HASH JOIN FULL OUTER|                         |  6705K|   255M|   204M|    10M  (9)| 33:33:17 |
|   3 |    VIEW               |                         |  6703K|   127M|       |  4767K  (9)| 15:53:31 |
|   4 |     SORT GROUP BY     |                         |  6703K|    76M|    14G|  4767K  (9)| 15:53:31 |
|*  5 |      TABLE ACCESS FULL| OMS_TEST                |   764M|  8749M|       |  3335K  (7)| 11:07:08 |
|   6 |    VIEW               |                         |  6705K|   127M|       |  5278K  (9)| 17:35:37 |
|   7 |     SORT GROUP BY     |                         |  6705K|    76M|    15G|  5278K  (9)| 17:35:37 |
|*  8 |      TABLE ACCESS FULL| ENAB_TEST               |   805M|  9215M|       |  3770K  (7)| 12:34:05 |
---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OMS"."BAN"="ENAB"."BAN")
   5 - filter("DVR_IND"='Y')
   8 - filter("DVR_IND"='Y')

我创建了上面的查询,可以在较小的数据上正常工作。如果我有很多记录,它会占用太多时间。有没有办法删除完整的外连接并优化查询或任何其他优化方法?

0 个答案:

没有答案