반갑습니다.
질문만 자꾸올리네요.
환경은 :
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)
실행결과를 보면
서브쿼리가 먼저 수행된것으로 나오는데
서브쿼리의 조건을 보면 메인 쿼리의 값을 알아야만
수행할수 있는 연관쿼리인데,
어떻게 서브쿼리부터 수행되었을까요 ?
수행 순서가 불가능해 보이는데...
선배님들의 조언 부탁드립니다.
감사합니다.
수고하세요
네..그러네요...
이재현님 말씀대로 실행계획은 2 -> 3 -> 1 로 풀리는게 맞네요~
서브쿼리가 최초 우선 실행된건 아니며 제공자 쿼리로 수행된것 역시 아니에요..
Early Filter 서브쿼리로 인덱스 필터링을 먼저 수행함으로 테이블 랜덤 Access를 줄이고자 위와 같이 실행계획이 수립된것으로 확인됩니다.
즉...
메인쿼리상의 인덱스(2번)를 스캔 후에 테이블 Access 가 아닌 서브쿼리의 인덱스(3번)을 Access하여 우선 필터링(push_subq) 한 후 해당 row에 대해서 테이블(1번)을 램덤 Access 하는 플랜이 되겠네요~
서브쿼리의 인덱스(3번)가 제일 오른쪽에 보이는건 메인쿼리상의 테이블 Access 보다 우선 실행함을 보여주기 위한것 아닐까요? 메인쿼리의 인덱스(2번) 스캔과 동일한 레벨로 놓을수가 없어서 일까요?