包含IN子查询的SQL语句的优化

当SQL语句中包含in语句时,有时候会极大的影响性能,我们可以把in子查询用exists子查询或外连接替代

例子如下:

   1.SQL语句中包含IN子查询:

Sql代码   收藏代码
  1. SQL> select * from servers s  
  2.   2   where s.srvr_id = 3333333 or  
  3.   3   s.srvr_id in (select t.srvr_id  
  4.   4                         from serv_inst t  
  5.   5                        where t.si_status = 'Activated'  
  6.   6                          and t.type = 'UNIX')  
  7.   7  /  
  8.   
  9. 已选择11行。  
  10.   
  11.   
  12. 执行计划  
  13. ----------------------------------------------------------  
  14. Plan hash value: 910321333  
  15.   
  16. --------------------------------------------------------------------------------  
  17. | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  18. --------------------------------------------------------------------------------  
  19. |   0 | SELECT STATEMENT   |           |     6 |   378 |     2   (0)| 00:00:01 |  
  20. |*  1 |  FILTER            |           |       |       |            |          |  
  21. |   2 |   TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |  
  22. |*  3 |   TABLE ACCESS FULL| SERV_INST |     2 |    38 |     2   (0)| 00:00:01 |  
  23. --------------------------------------------------------------------------------  
  24.   
  25. Predicate Information (identified by operation id):  
  26. ---------------------------------------------------  
  27.   
  28.    1 - filter("S"."SRVR_ID"=3333333 OR  EXISTS (SELECT /*+ */ 0 FROM  
  29.               "SERV_INST" "T" WHERE "T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated'  
  30.               AND "T"."TYPE"='UNIX'))  
  31.    3 - filter("T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated' AND  
  32.               "T"."TYPE"='UNIX')  
  33.   
  34. Note  
  35. -----  
  36.    - dynamic sampling used for this statement  
  37.   
  38.   
  39. 统计信息  
  40. ----------------------------------------------------------  
  41.           0  recursive calls  
  42.           0  db block gets  
  43.         818  consistent gets  
  44.           0  physical reads  
  45.           0  redo size  
  46.        1146  bytes sent via SQL*Net to client  
  47.         385  bytes received via SQL*Net from client  
  48.           2  SQL*Net roundtrips to/from client  
  49.           0  sorts (memory)  
  50.           0  sorts (disk)  
  51.          11  rows processed  
  52.   
  53. SQL>   

 2.把上面SQL语句改为EXISTS子查询形式

Sql代码   收藏代码
  1. SQL> select *  
  2.   2    from servers s  
  3.   3   where s.srvr_id = 3333333 or exists (select 1  
  4.   4                         from serv_inst t  
  5.   5                        where  s.srvr_id = t.srvr_id   
  6.   6                          and t.si_status = 'Activated'  
  7.   7                          and t.type = 'UNIX')  
  8.   8  /  
  9.    
  10. 已选择11行。  
  11.   
  12.   
  13. 执行计划  
  14. ----------------------------------------------------------  
  15. Plan hash value: 910321333  
  16.   
  17. --------------------------------------------------------------------------------  
  18. | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  19. --------------------------------------------------------------------------------  
  20. |   0 | SELECT STATEMENT   |           |     6 |   378 |     2   (0)| 00:00:01 |  
  21. |*  1 |  FILTER            |           |       |       |            |          |  
  22. |   2 |   TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |  
  23. |*  3 |   TABLE ACCESS FULL| SERV_INST |     2 |    38 |     2   (0)| 00:00:01 |  
  24. --------------------------------------------------------------------------------  
  25.   
  26. Predicate Information (identified by operation id):  
  27. ---------------------------------------------------  
  28.   
  29.    1 - filter("S"."SRVR_ID"=3333333 OR  EXISTS (SELECT /*+ */ 0 FROM  
  30.               "SERV_INST" "T" WHERE "T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated'  
  31.               AND "T"."TYPE"='UNIX'))  
  32.    3 - filter("T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated' AND  
  33.               "T"."TYPE"='UNIX')  
  34.   
  35. Note  
  36. -----  
  37.    - dynamic sampling used for this statement  
  38.   
  39.   
  40. 统计信息  
  41. ----------------------------------------------------------  
  42.           0  recursive calls  
  43.           0  db block gets  
  44.         818  consistent gets  
  45.           0  physical reads  
  46.           0  redo size  
  47.        1146  bytes sent via SQL*Net to client  
  48.         385  bytes received via SQL*Net from client  
  49.           2  SQL*Net roundtrips to/from client  
  50.           0  sorts (memory)  
  51.           0  sorts (disk)  
  52.          11  rows processed  
  53.   
  54. SQL>   

3.改成另一种外连接的方式

Sql代码   收藏代码
  1. SQL> select distinct s.*  
  2.   2    from servers s  
  3.   3    left join serv_inst t on s.srvr_id = t.srvr_id  
  4.   4                         and t.si_status = 'Activated'  
  5.   5                         and t.type = 'UNIX'  
  6.   6   where ((t.siid is not nullor (t.siid is null and s.srvr_id = 3333333))  
  7.   7  /  
  8.   
  9. 已选择11行。  
  10.   
  11. 执行计划  
  12. ----------------------------------------------------------  
  13. Plan hash value: 2837582902  
  14.   
  15. ----------------------------------------------------------------------------------  
  16. | Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  17. ----------------------------------------------------------------------------------  
  18. |   0 | SELECT STATEMENT     |           |    96 |  8448 |     7  (29)| 00:00:01 |  
  19. |   1 |  HASH UNIQUE         |           |    96 |  8448 |     7  (29)| 00:00:01 |  
  20. |*  2 |   FILTER             |           |       |       |            |          |  
  21. |*  3 |    HASH JOIN OUTER   |           |    96 |  8448 |     6  (17)| 00:00:01 |  
  22. |   4 |     TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |  
  23. |*  5 |     TABLE ACCESS FULL| SERV_INST |    57 |  1425 |     3   (0)| 00:00:01 |  
  24. ----------------------------------------------------------------------------------  
  25.   
  26. Predicate Information (identified by operation id):  
  27. ---------------------------------------------------  
  28.   
  29.    2 - filter("T"."SIID" IS NOT NULL OR "T"."SIID" IS NULL AND  
  30.               "S"."SRVR_ID"=3333333)  
  31.    3 - access("S"."SRVR_ID"="T"."SRVR_ID"(+))  
  32.    5 - filter("T"."TYPE"(+)='UNIX' AND "T"."SI_STATUS"(+)='Activated')  
  33.   
  34. Note  
  35. -----  
  36.    - dynamic sampling used for this statement  
  37.   
  38.   
  39. 统计信息  
  40. ----------------------------------------------------------  
  41.           0  recursive calls  
  42.           0  db block gets  
  43.          12  consistent gets  
  44.           0  physical reads  
  45.           0  redo size  
  46.        1154  bytes sent via SQL*Net to client  
  47.         385  bytes received via SQL*Net from client  
  48.           2  SQL*Net roundtrips to/from client  
  49.           0  sorts (memory)  
  50.           0  sorts (disk)  
  51.          11  rows processed  
  52.   
  53. SQL>   

 4.另一种外连接的写法

Sql代码   收藏代码
  1. SQL> select distinct s.*  
  2.   2    from servers s, serv_inst t  
  3.   3   where s.srvr_id = t.srvr_id(+)  
  4.   4     and t.si_status(+) = 'Activated'  
  5.   5     and t.type(+) = 'UNIX'  
  6.   6     and ((t.siid is not nullor (t.siid is null and s.srvr_id = 3333333))  
  7.   7  /  
  8.   
  9. 已选择11行。  
  10.   
  11.   
  12. 执行计划  
  13. ----------------------------------------------------------  
  14. Plan hash value: 2837582902  
  15.   
  16. ----------------------------------------------------------------------------------  
  17. | Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  18. ----------------------------------------------------------------------------------  
  19. |   0 | SELECT STATEMENT     |           |    96 |  8448 |     7  (29)| 00:00:01 |  
  20. |   1 |  HASH UNIQUE         |           |    96 |  8448 |     7  (29)| 00:00:01 |  
  21. |*  2 |   FILTER             |           |       |       |            |          |  
  22. |*  3 |    HASH JOIN OUTER   |           |    96 |  8448 |     6  (17)| 00:00:01 |  
  23. |   4 |     TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |  
  24. |*  5 |     TABLE ACCESS FULL| SERV_INST |    57 |  1425 |     3   (0)| 00:00:01 |  
  25. ----------------------------------------------------------------------------------  
  26.   
  27. Predicate Information (identified by operation id):  
  28. ---------------------------------------------------  
  29.   
  30.    2 - filter("T"."SIID" IS NOT NULL OR "T"."SIID" IS NULL AND  
  31.               "S"."SRVR_ID"=3333333)  
  32.    3 - access("S"."SRVR_ID"="T"."SRVR_ID"(+))  
  33.    5 - filter("T"."SI_STATUS"(+)='Activated' AND "T"."TYPE"(+)='UNIX')  
  34.   
  35. Note  
  36. -----  
  37.    - dynamic sampling used for this statement  
  38.   
  39.   
  40. 统计信息  
  41. ----------------------------------------------------------  
  42.           0  recursive calls  
  43.           0  db block gets  
  44.          12  consistent gets  
  45.           0  physical reads  
  46.           0  redo size  
  47.        1154  bytes sent via SQL*Net to client  
  48.         385  bytes received via SQL*Net from client  
  49.           2  SQL*Net roundtrips to/from client  
  50.           0  sorts (memory)  
  51.           0  sorts (disk)  
  52.          11  rows processed  
  53.   
  54. SQL>   

 以上三种方式比较,看来还是用外连接的方式查询效率更高

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值