`

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

阅读更多

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

例子如下:

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

SQL> select * from servers s
  2   where s.srvr_id = 3333333 or
  3   s.srvr_id in (select t.srvr_id
  4                         from serv_inst t
  5                        where t.si_status = 'Activated'
  6                          and t.type = 'UNIX')
  7  /

已选择11行。


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

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     6 |   378 |     2   (0)| 00:00:01 |
|*  1 |  FILTER            |           |       |       |            |          |
|   2 |   TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| SERV_INST |     2 |    38 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter("S"."SRVR_ID"=3333333 OR  EXISTS (SELECT /*+ */ 0 FROM
              "SERV_INST" "T" WHERE "T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated'
              AND "T"."TYPE"='UNIX'))
   3 - filter("T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated' AND
              "T"."TYPE"='UNIX')

Note
-----
   - dynamic sampling used for this statement


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

SQL> 

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

SQL> select *
  2    from servers s
  3   where s.srvr_id = 3333333 or exists (select 1
  4                         from serv_inst t
  5                        where  s.srvr_id = t.srvr_id 
  6                          and t.si_status = 'Activated'
  7                          and t.type = 'UNIX')
  8  /
 
已选择11行。


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

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     6 |   378 |     2   (0)| 00:00:01 |
|*  1 |  FILTER            |           |       |       |            |          |
|   2 |   TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| SERV_INST |     2 |    38 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter("S"."SRVR_ID"=3333333 OR  EXISTS (SELECT /*+ */ 0 FROM
              "SERV_INST" "T" WHERE "T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated'
              AND "T"."TYPE"='UNIX'))
   3 - filter("T"."SRVR_ID"=:B1 AND "T"."SI_STATUS"='Activated' AND
              "T"."TYPE"='UNIX')

Note
-----
   - dynamic sampling used for this statement


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

SQL> 

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

SQL> select distinct s.*
  2    from servers s
  3    left join serv_inst t on s.srvr_id = t.srvr_id
  4                         and t.si_status = 'Activated'
  5                         and t.type = 'UNIX'
  6   where ((t.siid is not null) or (t.siid is null and s.srvr_id = 3333333))
  7  /

已选择11行。

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

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |    96 |  8448 |     7  (29)| 00:00:01 |
|   1 |  HASH UNIQUE         |           |    96 |  8448 |     7  (29)| 00:00:01 |
|*  2 |   FILTER             |           |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |           |    96 |  8448 |     6  (17)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| SERV_INST |    57 |  1425 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

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

   2 - filter("T"."SIID" IS NOT NULL OR "T"."SIID" IS NULL AND
              "S"."SRVR_ID"=3333333)
   3 - access("S"."SRVR_ID"="T"."SRVR_ID"(+))
   5 - filter("T"."TYPE"(+)='UNIX' AND "T"."SI_STATUS"(+)='Activated')

Note
-----
   - dynamic sampling used for this statement


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

SQL> 

 4.另一种外连接的写法

SQL> select distinct s.*
  2    from servers s, serv_inst t
  3   where s.srvr_id = t.srvr_id(+)
  4     and t.si_status(+) = 'Activated'
  5     and t.type(+) = 'UNIX'
  6     and ((t.siid is not null) or (t.siid is null and s.srvr_id = 3333333))
  7  /

已选择11行。


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

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |    96 |  8448 |     7  (29)| 00:00:01 |
|   1 |  HASH UNIQUE         |           |    96 |  8448 |     7  (29)| 00:00:01 |
|*  2 |   FILTER             |           |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |           |    96 |  8448 |     6  (17)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| SERVERS   |    96 |  6048 |     2   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| SERV_INST |    57 |  1425 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

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

   2 - filter("T"."SIID" IS NOT NULL OR "T"."SIID" IS NULL AND
              "S"."SRVR_ID"=3333333)
   3 - access("S"."SRVR_ID"="T"."SRVR_ID"(+))
   5 - filter("T"."SI_STATUS"(+)='Activated' AND "T"."TYPE"(+)='UNIX')

Note
-----
   - dynamic sampling used for this statement


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

SQL> 

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

分享到:
评论

相关推荐

    数据库设计(包括select语句、子查询、语句嵌套)

    关于电影公司的数据库设计建模 包括 select语句 子查询,语句嵌套等

    SQL语句优化总结34条

    对SQL语句的各种情况下的优化,包括索引的使用,子查询的优化并涉及SQL执行编译的原理

    sql脚本优化

    下面是sql语句优化的一些提示要点,主要讲述的是操作符优化过程。 IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。 但是用IN的SQL性能总是比较低的,从sql执行的步骤来...

    sql语句的优化方法

    (1) 选择最有效率的表名顺序(只在基于规则...(5) 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200 (6) 使用DECODE函数来减少处理时间 等优化方法详解

    数据库实验报告 SQL查询 ,子查询组合

    实验目的和要求:,了解SQL语句的数据定义与数据更新功能,了解SQL语句的查询功能,掌握SQL中的数据定义语句的用法,熟练掌握SQL中的插入、修改和删除语句的操作,熟练掌握使用SQL语句进行数据库的简单查询、连接...

    Oracle数据库SQL语句优化策略

    ORACLE 试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用 IN的SQL至少多了一个转换的过程。一般的SQL都可以转换...

    sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句

    在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT ...

    SQL子查询语句简单示例

    SQL 中的 SELECT 命令不仅能够直接用来查询数据库中的数据,还能够嵌入到 WHERE 中作为子查询语句,或者将查询结果插入到另一个表中。  将子查询用于 WHERE 子句  子查询能够与 SELECT、INSERT、UPDATE 和 ...

    sqlserver 子查询语句

    表ta userno(编号),username(名字) 表tb userno(编号),score(分数) 想查询结果为 userno(编号),username(名字)..."子查询"是SQL语言中的一个重要概念,它允许在一个查询语句(主查询)中嵌套另一个查询语句(子查询)

    SQL语句集锦.rar

    动态SQL语句.txt 动态语句.txt 区分大小写.txt 去掉重复的列名.txt 取n到m条记录.txt 合并字符串.txt 多列的行转列.sql 多行补充.sql 多表对多表进行统计.txt 大小写转换.txt 子查寻和内联查寻.txt 学生名次.txt ...

    SQL语句嵌套查询

    基于SQL2005的嵌套查询,包括返回一个值的子查询、返回一组值的子查询(使用ANY谓词查询、使用IN谓词查询、使用ALL谓词查询使用EXISTS查询)。附有详细的表信息。

    经典SQL语句大全

    4、说明:子查询(表名1:a 表名2:b) select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3) 5、说明:显示文章、提交人和最后回复时间 select a.title,a.username,b....

    子查询是指一条SELECT语句作为另一条SELECT语句的一部分,外层的SELCT语句称为外部查询,内层的SELECT语句称为内部查询(或子查询)

    子查询是指一条SELECT语句作为另一条SELECT语句的一部分,外层的SELCT语句称为外部查询,内层的SELECT语句称为内部查询(或子查询).doc

    巧用with as 对sql语句多次利用

    对于需重复查询的sql语句,可巧用with as 对sql语句进行精简,提高查询效率

    SQL语句总结

    本人学习MySQL笔记,常用的数据库操作增删改查等和条件,排序,分页,聚合函数,分组,连接,子查询等高级数据库操作的总结

    LECCO SQL Expert (智能自动SQL优化)

    IDIN(SELECT SAL_EMP_IDFROM EMP_SAL_HISTB WHERESAL_SALARY>70000) 按“优化”按钮后,经过十几秒,SQL Expert就完成了优化的过程,从优化细节中可以看到,它在十几秒的时间内重写产生了2267条等价的SQL语句,其中...

    sql子查询总结

    在SQL语言中,当一个查询语句嵌套在另一个查询的查询条件之中时,称为子查询。

    精通sql结构化查询语句

    10.1.5 使用子查询创建视图 10.2 使用IN语句的子查询 10.2.1 简单的IN语句子查询 10.2.2 使用IN子查询实现集合交运算 lO.2.3 使用IN子查询实现集合差运算 10.3 使用EXISTS语句的子查询 10.3.1 简单的EXISTS语句子...

    SQL查询安全性及性能优化

    说明:通过这个报表找到排在前10 的sql语句,如果这些语句是用户编写的sql语句,我可以对其进行优化。 我们可以根据这些信息筛选出需要优化的SQL语句进行优化 SQL优化经验  大表缺索引---必要字段上建立索引  ...

    sql常用语句

    主要内容包括,增删改查(CURD),重点在查询(子查询,模糊查询,分组查询等)。 在开始之前,要注意:sql是不区分大小写的,但是为了代码容易阅读与调试,一般将Sql关键字大写,对所有的表名和列明使用小写。多条...

Global site tag (gtag.js) - Google Analytics