SQL Profile

SQL Profile은 Oracle 10g부터 도입된 기능으로 그 내부는 Stored Outline과 유사한 방식으로 구현됐다. Stored Outline이 실행계획을 고정해 튜닝하는 것이 목적이라고 본다면 SQL Profile은 실질적인 SQL Tuning이라고 보면 되며 그 절차는 다음과 같다.

  • 1. 성능 이슈가 있는 SQL의 실행계획에서 쿼리 블록을 가리키는 SEL$ 정보를 확인한다.
  • 2. 튜닝된 SQL의 실행계획에서 쿼리 블록을 가리키는 SEL$ 정보를 확인한다.
  • 3. 튜닝하고자 하는 SEL$ 정보에 대한 수정 부분을 Hidden Procedure인 DBMS_SQLTUNE. IMPORT_SQL_PROFILE을 이용해 수정한다.
  • 4. Outline을 적용 후 실행계획이 의도대로 변경됐는지를 확인한다.

SQL Profile을 이용하는 튜닝 절차는 Stored Outline과 조금 다르지만 Outline을 변경해 튜닝한다는 점에서 그 기능이 유사하다.

튜닝할 부분의 Outline 구간을 정확히 인식한다면 Stored Outline보다 쉽게 변경할 수 있는 장점이 있다.

그럼 이를 이용해 어떻게 튜닝을 진행하면 되는지 알아보자. [리스트 1]은 실행계획 및 SQL_ID와 Outline을 확인하는 단계로 성능 이슈가 있는 구간을 탐색하는 방법을 보여주고 있다. 이 예제에서는 성능 이슈가 중첩루프 조인에서 발생된다고 가정해보자.

  • [리스트 1] 성능 이슈가 되는 SQL 구문 조회
  • ?

    SELECT /*+ USE_NL(A B) */

           A.EMPLOYEE_ID, A.FIRST_NAME, B.DEPARTMENT_ID, B.DEPARTMENT_NAME

      FROM EMPLOYEES A, DEPARTMENTS B

     WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID

       AND A.JOB_ID = 'SA_REP' AND A.DEPARTMENT_ID > 1;

        

        

    -- 생략 --

    SELECT PLAN_TABLE_OUTPUT 

      FROM TABLE(dbms_xplan.DISPLAY_CURSOR('', '', 'OUTLINE'));

    ----------------------------------------------------------

    SQL_ID  88j03p40kgkwt, child number 0

     

     

    /*+   -- 생략 --

    ALL_ROWS

    OUTLINE_LEAF(@"SEL$1")

    INDEX_RS_ASC(@"SEL$1" "B"@"SEL$1" ("DEPARTMENTS". "DEPARTMENT_ID"))

    INDEX(@"SEL$1" "A"@"SEL$1" ("EMPLOYEES"."JOB_ID" "EMPLOYEES"."DEPARTMENT_ID"))

    LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")

    USE_NL(@"SEL$1" "A"@"SEL$1")

    END_OUTLINE_DATA

    */

[리스트 2]는 [리스트 1]을 튜닝한 결과에 대해 실행계획 및 Outline을 확인하는 단계를 보여준다. 이 예제에서는 성능 이슈를 해시 조인으로 해결한다고 가정해보자.

  • [리스트 2] 성능 이슈가 되는 SQL 구문 튜닝
  • ?

    SELECT /*+ USE_HASH(A B) */

           A.EMPLOYEE_ID, A.FIRST_NAME, B.DEPARTMENT_ID, B.DEPARTMENT_NAME

      FROM EMPLOYEES A, DEPARTMENTS B

     WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID

       AND A.JOB_ID = 'SA_REP' 

       AND A.DEPARTMENT_ID > 1;

        

    --------------------------------------------------------

    |   0 | SELECT STATEMENT                |               | 

    |*  1 |  HASH JOIN                      |               | 

    |   2 |   TABLE ACCESS BY INDEX ROWID   | DEPARTMENTS   |

    |*  3 |    INDEX RANGE SCAN             | DEPT_ID_PK    |

    |*  4 |   TABLE ACCESS FULL             | EMPLOYEES     |

    --------------------------------------------------------

     

     

    SELECT PLAN_TABLE_OUTPUT 

      FROM TABLE(dbms_xplan.DISPLAY_CURSOR('', '', 'OUTLINE')) ;

      /*+  -- 생략 --

          ALL_ROWS

          OUTLINE_LEAF(@"SEL$1")

          INDEX_RS_ASC(@"SEL$1" "B"@"SEL$1" ("DEPARTMENTS". "DEPARTMENT_ID"))

          FULL(@"SEL$1" "A"@"SEL$1")

          LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")

          USE_HASH(@"SEL$1" "A"@"SEL$1")

          END_OUTLINE_DATA

     */

[리스트 3]은 성능 이슈 SQL_ID의 FULLTEXT를 찾아 이슈 구간의 쿼리 블록을 가리키는 SEL$ 정보에 대해 튜닝 적용 후의 Profile 정보로 등록해주는 예제다.

  • [리스트 3] Profile 수정
  • ?

    declare L_SQLTEXT CLOB;

    begin

    -- 튜닝전 SQL_ID

    SELECT SQL_FULLTEXT INTO L_SQLTEXT

      FROM V$SQL

     WHERE SQL_ID='88j03p40kgkwt';

       

      dbms_sqltune.import_sql_profile

      ( sql_text=> L_SQLTEXT

      , profile => sqlprof_attr('USE_HASH(@"SEL$1" "A"@"SEL$1")') );

    end;  /

[리스트 4]는 [리스트 3]에서 Profile 등록 후 동일한 SQL이 재수행될 때 SQL Profile(SYS_SQLPROF_014efe78724 e0006)을 참조해 실행계획이 수행되는지를 보여주는 예제다.

  • [리스트 4] 중첩루프 조인 시 SQL Profile을 참조해 해시 조인으로 수행
  • ?

    SELECT /*+ USE_NL(A B) */

           A.EMPLOYEE_ID, A.FIRST_NAME, B.DEPARTMENT_ID, B.DEPARTMENT_NAME

      FROM EMPLOYEES A, DEPARTMENTS B

     WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID

       AND A.JOB_ID = 'SA_REP' AND A.DEPARTMENT_ID > 1;

    ---------------------------------------------------------

    |   0 | SELECT STATEMENT                 |               |

    |*  1 |  HASH JOIN                       |               |

    |   2 |   TABLE ACCESS BY INDEX ROWID    | DEPARTMENTS   |

    |*  3 |    INDEX RANGE SCAN              | DEPT_ID_PK    | 

    |*  4 |   TABLE ACCESS FULL              | EMPLOYEES     |  

    ---------------------------------------------------------

    Note

    - SQL profile "SYS_SQLPROF_014efe78724e0006" used for this statement

비교적 간단하게 Outline 수정으로 실행계획을 최적으로 유도해 성능을 개선하는 방법을 설명했다.

이는 긴급하게 성능 개선이 필요할 때 유용하게 쓰일 수는 있으나 Outline은 의미 그대로 요약본을 저장하고 있다가 이를 참조해 실행계획을 수립하는 것이므로 상황에 따라 옵티마이저에 의해 100% 동작하지 않을 수 있음을 감안해야 한다.

 

여러분이 관리하는 운영 시스템에서 수정이 불가한 애플리케이션에 문제가 발생했을 때 이런 제어 방법을 알고 있다면 장애요인 예방이나 안정적인 운영에 큰 도움이 되리라 생각한다.

'ORACLE > SQL' 카테고리의 다른 글

피벗(2) - PIVOT, UNPIVOT, (행을 열로, 열을 행으로)  (0) 2020.12.29
FETCH .. BULK COLLECT INTO  (0) 2020.07.22
SQL trace _ 참조  (0) 2019.10.02
복수행 함수 (그룹 함수)  (0) 2018.12.13
윈도우 함수(WINDOW FUNCTION)  (0) 2018.11.01

+ Recent posts