Subquery Pushing과 Execute Call

2023. 10. 18.·Oracle/Performance

Subquery Pushing으로 동작하는 비상관 단일 행 서브쿼리를 액세스 조건으로 사용하면서브 쿼리가 Execute Call 단계에서 수행됩니다. 이를 통해 쿼리의 성능을 개선한 사례를 살펴보겠습니다.

 

테스트를 위해 아래와 같이 테이블과 인덱스를 생성하겠습니다.

-- 1
DROP TABLE t1 PURGE;
DROP TABLE t2 PURGE;

CREATE TABLE t1 (c1, c2, c3)
AS
SELECT CEIL (ROWNUM / 100000), NVL (NULLIF (MOD (ROWNUM, 100000), 0), 100000), LPAD ('X', 100, 'X')
  FROM XMLTABLE ('1 to 1000000');

CREATE TABLE t2 (c1, c2, c3)
AS
SELECT CEIL (ROWNUM / 100000), NVL (NULLIF (MOD (ROWNUM, 100000), 0), 100000), LPAD ('X', 100, 'X')
  FROM XMLTABLE ('1 to 1000000');

CREATE INDEX t1_x1 ON t1 (c1);
CREATE INDEX t2_x1 ON t2 (c1, c2);

 

아래 예제는 서브 쿼리가 필터 조건으로 사용되어 1,785개의 블록 I/O가 발생합니다. 

-- 2-1
VAR b1 NUMBER = 1

-- 2-2
SELECT *
  FROM t1
 WHERE c1 = :b1
   AND c2 = (SELECT c2 FROM t2 WHERE c1 = :b1 AND c2 > 100000 AND ROWNUM = 1)
   AND ROWNUM = 1;

-----------------------------------------------------------------------------------------------
| Id  | Operation                            | Name  | Starts | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |       |      1 |      0 |00:00:00.03 |    1785 | -- (6)
|*  1 |  COUNT STOPKEY                       |       |      1 |      0 |00:00:00.03 |    1785 | -- (5)
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T1    |      1 |      0 |00:00:00.03 |    1785 | -- (2)
|*  3 |    INDEX RANGE SCAN                  | T1_X1 |      1 |    100K|00:00:00.01 |     197 | -- (1)
|*  4 |    COUNT STOPKEY                     |       |      1 |      0 |00:00:00.01 |       3 | -- (4)
|*  5 |     INDEX RANGE SCAN                 | T2_X1 |      1 |      0 |00:00:00.01 |       3 | -- (3)
-----------------------------------------------------------------------------------------------

Outline Data
-------------
      PUSH_SUBQ(@"SEL$2")

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM=1)
   2 - filter("C2"=)
   3 - access("C1"=:B1)
   4 - filter(ROWNUM=1)
   5 - access("C1"=:B1 AND "C2">100000 AND "C2" IS NOT NULL)

 

서브쿼리를 액세스 조건으로 사용할 수 있도록 t1_x2 인덱스를 생성하고 쿼리를 다시 수행하면 블록 I/O가 3으로 감소합니다.

-- 3-1
CREATE INDEX t1_x2 ON t1 (c1, c2);

-- 3-2
SELECT *
  FROM t1
 WHERE c1 = :b1
   AND c2 = (SELECT c2 FROM t2 WHERE c1 = :b1 AND c2 > 100000 AND ROWNUM = 1)
   AND ROWNUM = 1;

-----------------------------------------------------------------------------------------------
| Id  | Operation                            | Name  | Starts | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |       |      1 |      0 |00:00:00.01 |       3 | -- (6)
|*  1 |  COUNT STOPKEY                       |       |      1 |      0 |00:00:00.01 |       3 | -- (5)
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T1    |      1 |      0 |00:00:00.01 |       3 | -- (4)
|*  3 |    INDEX RANGE SCAN                  | T1_X2 |      1 |      0 |00:00:00.01 |       3 | -- (1)
|*  4 |     COUNT STOPKEY                    |       |      1 |      0 |00:00:00.01 |       3 | -- (3)
|*  5 |      INDEX RANGE SCAN                | T2_X1 |      1 |      0 |00:00:00.01 |       3 | -- (2)
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM=1)
   3 - access("C1"=:B1 AND "C2"=)
   4 - filter(ROWNUM=1)
   5 - access("C1"=:B1 AND "C2">100000 AND "C2" IS NOT NULL)

 

아래 10046 트레이스에서 필터 조건으로 사용된 서브쿼리는 Fetch Call 단계, 액세스 조건으로 사용된 서브쿼리는 Execute Call 단계에서 수행되는 것을 확인할 수 있습니다.

-- 2-2: 2
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.02       0.02          0       1785          0           0 -- !
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.03       0.02          0       1785          0           0

-- 3-2: 3
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          3          0           0 -- !
Fetch        1      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.00       0.00          0          3          0           0
저작자표시 비영리 변경금지 (새창열림)
'Oracle/Performance' 카테고리의 다른 글
  • SQL Patch 적용 사례
  • OR Expansion을 사용한 부정형 조건 성능 개선
  • SCN_ASCENDING 힌트와 Direct Path Read
  • UNUSABLE 인덱스 파티션에 의한 Join Factorization 쿼리 변환
정희락
정희락
2007년부터 Oracle Database 성능 최적화에 관심을 가져왔습니다. 현재 한국오라클 Engineered Systems Solution Engineering 팀에서 Solution Engineer로 근무하고 있습니다. 이 블로그는 개인적인 연구 목적으로 운영되며 Oracle 사의 공식적인 입장을 대변하지 않습니다.
  • 정희락
    TunA
    정희락
  • 전체
    오늘
    어제
    • 분류 전체보기 (201)
      • Oracle (173)
        • SQL (33)
        • PLSQL (10)
        • Performance (74)
        • Administration (37)
        • Installation (3)
        • Utilities (1)
        • JSON (8)
        • Vector (7)
      • Exadata (15)
      • SQL*Plus (2)
      • Linux (5)
      • Resources (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 도서

    • 불친절한 SQL 프로그래밍
    • 불친절한 PL/SQL 프로그래밍
  • 링크

    • Connor McDonald
    • Frits Hoogland
    • Jonathan Lewis
    • Julian Dontcheff
    • Julian Dyke
    • Kun Sun
    • Maria Colgan
    • Martin Bach
    • Mike Dietrich
    • Tanel Poder
  • 공지사항

  • 인기 글

  • 태그

    12c
    19c
    21c
    23ai
    case study
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정희락
Subquery Pushing과 Execute Call
상단으로

티스토리툴바