oracle in,exists,not in,not exists

本文探讨了Oracle数据库中使用IN、EXISTS、NOT IN与NOT EXISTS等关键字时的查询优化策略,通过具体案例展示了如何利用这些操作符提升查询性能。
--在in和exists中,oracle可以把父查询推进到子查询


SQL> SELECT COUNT(*)
  2    FROM T0 LT
  3   WHERE  EXISTS (SELECT NULL FROM T1 LA WHERE LA.T1_ID = LT.T0_ID)
  4     AND LT.T0_ID IN (10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016);


  COUNT(*)
----------
        17


已用时间:  00: 00: 00.39


执行计划
----------------------------------------------------------
Plan hash value: 2619996249


---------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                            |     1 |    10 |    20   (5)| 00:00:01 |
|   1 |  SORT AGGREGATE      |                            |     1 |    10 |            |          |
|   2 |   NESTED LOOPS       |                            |     1 |    10 |    20   (5)| 00:00:01 |
|   3 |    SORT UNIQUE       |                            |  3382 | 16910 |    19   (0)| 00:00:01 |
|   4 |     INLIST ITERATOR  |                            |       |       |            |          |
|*  5 |      INDEX RANGE SCAN| T1_IDX |  3382 | 16910 |    19   (0)| 00:00:01 |
|*  6 |    INDEX UNIQUE SCAN | T0_PK             |     1 |     5 |     0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------


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


   5 - access("LA"."T1_ID"=10000 OR "LA"."T1_ID"=10001 OR
              "LA"."T1_ID"=10002 OR "LA"."T1_ID"=10003 OR
              "LA"."T1_ID"=10004 OR "LA"."T1_ID"=10005 OR
              "LA"."T1_ID"=10006 OR "LA"."T1_ID"=10007 OR
              "LA"."T1_ID"=10008 OR "LA"."T1_ID"=10009 OR
              "LA"."T1_ID"=10010 OR "LA"."T1_ID"=10011 OR
              "LA"."T1_ID"=10012 OR "LA"."T1_ID"=10013 OR
              "LA"."T1_ID"=10014 OR "LA"."T1_ID"=10015 OR
              "LA"."T1_ID"=10016)
   6 - access("LA"."T1_ID"="LT"."T0_ID")
       filter("LT"."T0_ID"=10000 OR "LT"."T0_ID"=10001 OR "LT"."T0_ID"=10002 OR
              "LT"."T0_ID"=10003 OR "LT"."T0_ID"=10004 OR "LT"."T0_ID"=10005 OR
              "LT"."T0_ID"=10006 OR "LT"."T0_ID"=10007 OR "LT"."T0_ID"=10008 OR
              "LT"."T0_ID"=10009 OR "LT"."T0_ID"=10010 OR "LT"."T0_ID"=10011 OR
              "LT"."T0_ID"=10012 OR "LT"."T0_ID"=10013 OR "LT"."T0_ID"=10014 OR
              "LT"."T0_ID"=10015 OR "LT"."T0_ID"=10016)




统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         34  consistent gets
          0  physical reads
          0  redo size
        354  bytes sent via SQL*Net to client
        476  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed
 
 
SQL> SELECT COUNT(*)
  2    FROM T0 LT
  3   WHERE LT.T0_ID IN (SELECT LA.T1_ID FROM T1 LA)
  4     AND LT.T0_ID IN (10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016);


  COUNT(*)
----------
        17


已用时间:  00: 00: 00.39


执行计划
----------------------------------------------------------
Plan hash value: 2619996249


---------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                            |     1 |    10 |    20   (5)| 00:00:01 |
|   1 |  SORT AGGREGATE      |                            |     1 |    10 |            |          |
|   2 |   NESTED LOOPS       |                            |     1 |    10 |    20   (5)| 00:00:01 |
|   3 |    SORT UNIQUE       |                            |  3382 | 16910 |    19   (0)| 00:00:01 |
|   4 |     INLIST ITERATOR  |                            |       |       |            |          |
|*  5 |      INDEX RANGE SCAN| T1_IDX |  3382 | 16910 |    19   (0)| 00:00:01 |
|*  6 |    INDEX UNIQUE SCAN | T0_PK             |     1 |     5 |     0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------


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


   5 - access("LA"."T1_ID"=10000 OR "LA"."T1_ID"=10001 OR
              "LA"."T1_ID"=10002 OR "LA"."T1_ID"=10003 OR
              "LA"."T1_ID"=10004 OR "LA"."T1_ID"=10005 OR
              "LA"."T1_ID"=10006 OR "LA"."T1_ID"=10007 OR
              "LA"."T1_ID"=10008 OR "LA"."T1_ID"=10009 OR
              "LA"."T1_ID"=10010 OR "LA"."T1_ID"=10011 OR
              "LA"."T1_ID"=10012 OR "LA"."T1_ID"=10013 OR
              "LA"."T1_ID"=10014 OR "LA"."T1_ID"=10015 OR
              "LA"."T1_ID"=10016)
   6 - access("LT"."T0_ID"="LA"."T1_ID")
       filter("LT"."T0_ID"=10000 OR "LT"."T0_ID"=10001 OR "LT"."T0_ID"=10002 OR
              "LT"."T0_ID"=10003 OR "LT"."T0_ID"=10004 OR "LT"."T0_ID"=10005 OR
              "LT"."T0_ID"=10006 OR "LT"."T0_ID"=10007 OR "LT"."T0_ID"=10008 OR
              "LT"."T0_ID"=10009 OR "LT"."T0_ID"=10010 OR "LT"."T0_ID"=10011 OR
              "LT"."T0_ID"=10012 OR "LT"."T0_ID"=10013 OR "LT"."T0_ID"=10014 OR
              "LT"."T0_ID"=10015 OR "LT"."T0_ID"=10016)




统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         34  consistent gets
          0  physical reads
          0  redo size
        354  bytes sent via SQL*Net to client
        476  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed


--从以上查询可知在in,exits,oracle可以把查询条件推进到子查询中,进而可以使用索引  




SQL> SELECT COUNT(*)
  2    FROM T0 LT
  3   WHERE LT.T0_ID NOT IN (SELECT LA.T1_ID FROM T1 LA)
  4     AND LT.T0_ID IN (10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016);


  COUNT(*)
----------
         0


已用时间:  00: 00: 01.83


执行计划
----------------------------------------------------------
Plan hash value: 1672357812


----------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                       | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                            |     1 |    10 | 14768   (1)| 00:02:58 |       |       |
|   1 |  SORT AGGREGATE         |                            |     1 |    10 |            |          |       |       |
|*  2 |   FILTER                |                            |       |       |            |          |       |       |
|   3 |    NESTED LOOPS ANTI SNA|                            |     1 |    10 | 14768 (100)| 00:02:58 |       |       |
|   4 |     INLIST ITERATOR     |                            |       |       |            |          |       |       |
|*  5 |      INDEX UNIQUE SCAN  | T0_PK             |    17 |    85 |    15   (0)| 00:00:01 |       |       |
|*  6 |     INDEX RANGE SCAN    | T1_IDX |  7512K|    35M|     2   (0)| 00:00:01 |       |       |
|   7 |    PARTITION RANGE ALL  |                            |     1 |     5 | 14736   (1)| 00:02:57 |     1 |     6 |
|*  8 |     TABLE ACCESS FULL   | T1          |     1 |     5 | 14736   (1)| 00:02:57 |     1 |     6 |
----------------------------------------------------------------------------------------------------------------------


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


   2 - filter( NOT EXISTS (SELECT 0 FROM "T1" "LA" WHERE "LA"."T1_ID" IS NULL))
   5 - access("LT"."T0_ID"=10000 OR "LT"."T0_ID"=10001 OR "LT"."T0_ID"=10002 OR "LT"."T0_ID"=10003 OR
              "LT"."T0_ID"=10004 OR "LT"."T0_ID"=10005 OR "LT"."T0_ID"=10006 OR "LT"."T0_ID"=10007 OR
              "LT"."T0_ID"=10008 OR "LT"."T0_ID"=10009 OR "LT"."T0_ID"=10010 OR "LT"."T0_ID"=10011 OR
              "LT"."T0_ID"=10012 OR "LT"."T0_ID"=10013 OR "LT"."T0_ID"=10014 OR "LT"."T0_ID"=10015 OR
              "LT"."T0_ID"=10016)
   6 - access("LT"."T0_ID"="LA"."T1_ID")
   8 - filter("LA"."T1_ID" IS NULL)




统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      53595  consistent gets
          0  physical reads
          0  redo size
        353  bytes sent via SQL*Net to client
        476  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed


 
SQL> SELECT COUNT(*)
  2    FROM T0 LT
  3   WHERE  NOT EXISTS (SELECT NULL FROM T1 LA WHERE LA.T1_ID = LT.T0_ID)
  4     AND LT.T0_ID IN (10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016);


  COUNT(*)
----------
         0


已用时间:  00: 00: 00.39


执行计划
----------------------------------------------------------
Plan hash value: 4283638437


---------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                            |     1 |    10 |    34   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE      |                            |     1 |    10 |            |          |
|*  2 |   HASH JOIN ANTI     |                            |     1 |    10 |    34   (0)| 00:00:01 |
|   3 |    INLIST ITERATOR   |                            |       |       |            |          |
|*  4 |     INDEX UNIQUE SCAN| T0_PK             |    17 |    85 |    15   (0)| 00:00:01 |
|   5 |    INLIST ITERATOR   |                            |       |       |            |          |
|*  6 |     INDEX RANGE SCAN | T1_IDX |  3382 | 16910 |    19   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------


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


   2 - access("LA"."T1_ID"="LT"."T0_ID")
   4 - access("LT"."T0_ID"=10000 OR "LT"."T0_ID"=10001 OR "LT"."T0_ID"=10002 OR
              "LT"."T0_ID"=10003 OR "LT"."T0_ID"=10004 OR "LT"."T0_ID"=10005 OR
              "LT"."T0_ID"=10006 OR "LT"."T0_ID"=10007 OR "LT"."T0_ID"=10008 OR
              "LT"."T0_ID"=10009 OR "LT"."T0_ID"=10010 OR "LT"."T0_ID"=10011 OR
              "LT"."T0_ID"=10012 OR "LT"."T0_ID"=10013 OR "LT"."T0_ID"=10014 OR
              "LT"."T0_ID"=10015 OR "LT"."T0_ID"=10016)
   6 - access("LA"."T1_ID"=10000 OR "LA"."T1_ID"=10001 OR
              "LA"."T1_ID"=10002 OR "LA"."T1_ID"=10003 OR
              "LA"."T1_ID"=10004 OR "LA"."T1_ID"=10005 OR
              "LA"."T1_ID"=10006 OR "LA"."T1_ID"=10007 OR
              "LA"."T1_ID"=10008 OR "LA"."T1_ID"=10009 OR
              "LA"."T1_ID"=10010 OR "LA"."T1_ID"=10011 OR
              "LA"."T1_ID"=10012 OR "LA"."T1_ID"=10013 OR
              "LA"."T1_ID"=10014 OR "LA"."T1_ID"=10015 OR
              "LA"."T1_ID"=10016)




统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         34  consistent gets
          0  physical reads
          0  redo size
        353  bytes sent via SQL*Net to client
        476  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
--对于not in,oracle不可以把子查询推进到子查询中,进而走了全表扫描
--对于not exists,oracle可以把父查询推进到子查询,进而走索引
--所以如果子查询表很大时not exists较not in好,如果子查询表很少,则反之
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值