天天看点

关于嵌套子查询的理解

关于嵌套子查询的理解

A答案是说:先执行outer query,再执行nested query//取出outer query语句中的表的每一行都会去执行一次nested query

B答案是说:先执行nested query,再执行outer query

C答案是说:只有返回了nested query的结果,才能执行outer query

D答案是说:nested query返回的结果(的每一行)会遍历评判outer query中返回的每一行。

A答案描述的是嵌套查询的从外到内的执行过程,即取出outer query语句中的表的每一行都会去执行一次nested query,也就是说,在遍历一遍外查询语句里的表的过程中,会去执行一次内查询语句,具体地说,在每遍历外查询语句里的表的一行数据时,都会去执行一次内查询语句。

B答案描述的是嵌套查询的从内到外的执行过程,即执行完内查询语句而获得中间结果集后再去执行外查询语句。

题目是问关于相关子查询(the correlated subquery )的执行哪两个选项是对的,

所以,

库题的答案是:AD。

关于嵌套查询的说明

    Oracle的嵌套子查询分为两类分别是相关子查询和不相关子查询。所谓不相关子查询是指,子查询是一个独立的查询不与外部查询相关,子查询将被先执行,而且只被执行一次,子查询执行完成后,再执行外部的查询,外部查询在执行过程中会使用到子查询的结果。下面我们来看不相关子查询。

[html] view plaincopy

  1. [email protected]> set autot traceonly;  
  2. [email protected]> SELECT employee_id,first_name,salary  
  3.   2  FROM employees  
  4.   3  WHERE  
  5.   4  department_id=(SELECT department_id  
  6.   5  FROM departments where department_name='IT');  
关于嵌套子查询的理解

nested query叫:inner query,main query叫outer query。

outer query是:SELECTemployee_id,first_name,salary

  FROM employees;

Nested query是:SELECTdepartment_id

   FROM departments where department_name='IT';

       看上图的执行计划,是先执行:id=3(DEPARTMENTS做全表扫描,通过部门名称过滤出部门编号)即先执行nested query,然后再执行id=2(对EMPLOYEES表的DEPARTMENT_ID列上的索引做范围扫描,然后能索引的键值找到EMPLOYEES表中的编号、姓名、薪水),取后执行outer query。最后SELECT出来的数据来自于outer query。

通过上面的分析:子查询可以向主查询提供常量查询条件,子查询被优先执行,产生的结果作为主查询的过滤条件,然后主果询以这个条件过滤出结果,返回给用户数据。

   上面的语句也可以转化成表连接的方式:

[html] view plain copy

  1. [email protected]> SELECT  employee_id,first_name,salary  
  2.  2  FROM employees e,departments d  
  3.  3  WHERE e.department_id=d.department_id  
  4.  4  AND department_name='IT';  
关于嵌套子查询的理解

     上述通过表的连接方式替代(嵌套)子查询,以获得良的执行速度。

       将有些相关子查询可以不相关化,即解除构成子查询的查询语句与主查询语句的相关关系,也可以获得良的执行速度。例如,查询课程成绩进入前十名的学生以及其课程号,这里

select grade

fromsc_topten y

where y.sno=x.sno

就可以了,写成如下语句主要是为了演示。

select sno,cno

from sc x

where grade  in

(

select grade

from sc_topten y

where y.sno=x.sno);

按照从内到外的执行过程来理解时,可以等价于如下语句:

select sno,cno

from sc x

where (sno,grade)  in

(

select  sno,grade

from sc_topten y

where y.sno);

参见: 关于嵌套查询(nested query)的深入理解

事实上,几乎大部分的子查询都要经过转化。在子查询不相关化不可能实现时,优化器会制定把子查询放在最优先或最后位置 执行的独立执行计划。此时,这个查询语句的执行速度会随着子查询被放在最优先或最后位置执行的顺序不同而不同。

[html] view plain copy

  1. [email protected]> SELECT department_id, last_name, salary   
  2.   2     FROM employees x   
  3.   3     WHERE salary > (SELECT AVG(salary)   
  4.   4        FROM employees   
  5.   5        WHERE x.department_id = department_id)   
  6.   6     ORDER BY department_id;  
关于嵌套子查询的理解

总结:如果优化器无法将其连接转为表连接查询,而只能为其中的主查询和子查询制定相应的执行计划 。如果处理类型为需要将子查询的结果提供给主查询的列,且在子查询中能够使用索引,那么优化器就将制定优先执行子查询的执行计划。如果处理类型为在主查询被执行的同时验证子查询的FILTER,或在读取了各个集合数据之后再对其进行合并,那么就会按照hash连接的方式来执行。

 参见:

http://blog.csdn.net/guoyjoe/article/details/9457523

继续阅读