쿼리 실행 순서.. 0 5 3,347

by 우태열 [SQL Query] 쿼리 [2015.09.13 13:39:48]


반갑습니다.
질문만 자꾸올리네요.

환경은 :
OS : Windows 7,
DB : Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit 입니다.

오라클을 학습하다, 막혀서 이렇게 질문을 올립니다.
저가 궁금한건 실행 순서가 가능한지 알고싶습니다.

사용한 쿼리는

set serveroutput off;
set linesize 2000;
alter session set statistics_level = all;

select c1, c2, c3
  from subquery_t2 t2
 where c1 >= 20000 and c1 <= 20004                    <-------- 2
   and exists ( select /*+ NO_UNNEST */
                       'x'
                  from subquery_t1 t1                 
                 where t1.c4 = t2.c1 )                <--------- 1
;
-- 실행한 순서를 확인해보려고 아래와 같이 확인해보면

select * 
  from table(dbms_xplan.display_cursor(null, null, 'ADVANCED'))
;

--------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    |       |       |    13 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| SUBQUERY_T2        |     1 |    12 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | PK_SUQUERY_2       |     6 |       |     3   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN         | SUBQUERY_T1_IDX_01 |     2 |    10 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1 / T2@SEL$1
   2 - SEL$1 / T2@SEL$1
   3 - SEL$2 / T1@SEL$2

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

   2 - access("C1">=20000 AND "C1"<=20004)
       filter( IS NOT NULL)
   3 - access("T1"."C4"=:B1)

실행결과를 보면

서브쿼리가 먼저 수행된것으로 나오는데
서브쿼리의 조건을 보면 메인 쿼리의 값을 알아야만
수행할수 있는 연관쿼리인데,
어떻게 서브쿼리부터 수행되었을까요 ?
수행 순서가 불가능해 보이는데...

선배님들의 조언 부탁드립니다.
감사합니다.
수고하세요

by 이재현 [2015.09.14 15:07:22]

2번 부터 풀린거에요

2 - 3 - 1 이렇게 풀린거에요

서버쿼리가 제공자 처럼 풀린거로 보이는데 필터로 풀렸어요.

근거

3 - access("T1"."C4"=:B1)


by 제로 [2015.09.14 16:28:32]

쿼리변환(push_subq)에 의하여 서브쿼리부터 실행된것으로 보입니다.

실행계획의 outline data 를 확인해 보시면 PUSH_SUBQ(@"SEL$2") 힌트절이 보일거라 보여집니다.

즉, 서브쿼리를 먼저 실행하여 대상을 줄인후에 제공자 역할을 하는 서브쿼리로 전환하여 메인쿼리를 실행한다고 볼수 있을것 같습니다.

 

 


by 이재현 [2015.09.15 13:06:30]

PUSH_SUBQ 힌트가 먹었다고 해서 제공자로 풀리는게 아닙니다.

메인에 여러게의 집합 ( 테이블 ) 있을때 우선 서브 쿼리가 먼저 드라이빙 되라고하는것은 맞는데.

그 상단에서 필터로 푼다면 메인 -> 서브퀄 -> 메인 다른 테이블 -> 메인 다른 테이블 이런식으로 풀립니다.


by 제로 [2015.09.15 13:43:55]

네..그러네요...
이재현님 말씀대로 실행계획은 2 -> 3 -> 1 로 풀리는게 맞네요~
서브쿼리가 최초 우선 실행된건 아니며 제공자 쿼리로 수행된것 역시 아니에요..

Early Filter 서브쿼리로 인덱스 필터링을 먼저 수행함으로 테이블 랜덤 Access를 줄이고자 위와 같이 실행계획이 수립된것으로 확인됩니다.

즉...
메인쿼리상의 인덱스(2번)를 스캔 후에 테이블 Access 가 아닌 서브쿼리의 인덱스(3번)을 Access하여 우선 필터링(push_subq) 한 후 해당 row에 대해서 테이블(1번)을 램덤 Access 하는 플랜이 되겠네요~

 

서브쿼리의 인덱스(3번)가 제일 오른쪽에 보이는건 메인쿼리상의 테이블 Access 보다 우선 실행함을 보여주기 위한것 아닐까요? 메인쿼리의 인덱스(2번) 스캔과 동일한 레벨로 놓을수가 없어서 일까요?

 

 

 


by 마농 [2015.09.15 09:32:43]

기본 순서를 무시하는 실행계획이 종종 있는 것 같습니다.
1. 스칼라서브쿼리는 가장 먼저 수행되는 것처럼 제일 상단에 표시되지만...
  - 논리적으로 본다면 그럴 수가 없죠. 가장 나중에 수행됩니다.
2. NO_UNEST된 상관관계 서브쿼리도 마찬가지 인듯 합니다.
  - 메인의 조건이 없다면 절대로 먼저 수행될 수가 없죠.
  - 그런데도 불구하고 실행계획상 더 안쪽(오른쪽)으로 표시가 되어 있어 먼저 수행되는 것처럼 표현되어 있네요.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입