SlideShare a Scribd company logo
1 of 9
Download to read offline
50│2013 기술백서 White Paper
SQL Profile을 이용한 SQL Plan 변경
㈜엑셈 컨설팅본부/DB컨설팅팀 오 경렬
본 문서는 DBMS_SQLTUNE Package 를 이용하여 SQL Plan 을 변경하는
PLAN_SET_OUTLINE (가칭) User Define Procedure 에 관한 글로 다음과 같은 내용을 포함
한다.
 SQL Plan 변경의 필요성
 SQL Plan 변경을 위한 기능은 9i 부터 제공
 뭐가 다른가?
 SQL Profile 이란
 OUTLINE 이란
 PLAN_SET_OUTLINE Source
 사용 예
 주의사항 & 고급 사용
1. SQL Plan 변경의 필요성
Oracle 을 사용하는 사이트라면 SQL 성능이슈를 한번쯤을 겪어봤을 것이다. 보통 비효율 SQL
을 수정하고 Application 에 반영하여 정상적인 서비스를 운영하기 까지는 많은 시간이 소요될
수 있다. 해당 SQL 이 수행되는 업무와 관련된 업무들이 영향을 받기 때문에 서비스를 일시 정
지 해야 하는 경우도 있고 비효율 SQL 이 어느 소스에서 수행되는지 파악하는 시간으로 인해
쉽게 해결될 일이 장애 상황까지 발전할 수도 있다. 가장 흔하게는 통계정보 생성에 의한 경우
부터 소스 배포 과정에서 검증되지 않은 SQL 이 배포되는 경우까지 비효율 SQL 이 발생할 수
있는 케이스는 다양하다.
Part 1 ORACLE │51
2. SQL Plan 변경을 위한 기능은 9i부터 제공
Oracle 은 이미 9i 버전부터 Stored Outline 을 이용해서 SQL 플랜을 변경하는 방법을 제공했
다. 아이러니하게도 Oracle 9i 에서는 Stored Outline 을 이용한 플랜 변경은 실 운영환경에서
(적어도 필자의 경험에서는) 정상 동작하지 않는다. 9i 에서 등장한 Stored Outline 을 이용한
SQL 플랜 변경은 10g 버전부터 정상적으로 동작한다. Oracle 10g 에는 SQL Profile 이라는 것
을 새롭게 등장한다. 간단하게 개념을 잡는다면 SQL Profile 은 Stored Outline 을 포함하는 더
큰 틀이라 할 수 있다.
3. 뭐가 다른가?
이미 온라인상에는 SQL Plan 변경을 위한 이론과 방법이 정리된 수많은 기술문서가 존재한다.
하지만 안타깝게도 실 환경에서 사용하기에는 뭔가 복잡하고 손이 많이 간다. SQL Plan 변경
이 필요한 경우에 빠른 해결이 중요한 포인트이다. 10g 에서 SQL Profile 을 이용해서 플랜을
변경하려면 Outline 을 하나하나 적어줘야 하는데 여간 귀찮은 작업이 아니다.
필자의 Procedure 는 사용이 매우 간단하다.
EXEC PLAN_SET_OUTLINE(‘개선 전 SQLID’, ‘개선 후 SQLID’);
플랜이 변경되었습니다.
4. SQL Profile 이란
SQL Profile 은 특정 SQL 문에 연결할 수 있는 SQL 컴파일러 통계의 모음을 말한다. SQL
Profile 이 현재 SQL 문에 생성되면, SQL 분석 (컴파일)을 수행할 때 프로파일의 통계는 컴파일
러에 의해 사용된다. SQL 문장의 정규화된 텍스트가 SQL 프로파일 작성시에 제공된 SQL 텍스
트와 일치하는 경우프로파일이 SQL 컴파일 사용되는 것이다. SQL 텍스트의 정규화란, 모든 비
Literal 텍스트를 대문자로 변경하고 빈 공간이 없애는 것을 말한다. 컴파일을 수행한 세션에서
는 SQL 프로파일이 생성된 카테고리 및 Parameter 에 대해서 동일한 값을 가지고 있어야 한다.
52│2013 기술백서 White Paper
카테고리는 여러 프로파일이 동일한 SQL 문에 존재하는 것을 허용한다. 한 세션에서 특정 카테
고리 네임스페이스의 프로파일을 만들어 비공개 프로파일을 테스트 할 수 있습니다.
SQL 프로파일은 다음과 같은 SQL 문장에 대해서 사용 가능하다.
 SELECT statements
 UPDATE statements
 INSERT (but only with a SELECT clause) statements
 DELETE statements
 CREATE TABLE (but only with the AS SELECT clause)
 MERGE statements (the upsert operation)
Data Dictionary 에서 내부적으로 수행된 SQL 문(재귀 SQL)에 대해서는 프로파일을 사용할 수
없다. 또한, 데이터베이스가 오픈 되기 전에 수행되는 모든 SQL 역시 프로파일을 검색, 사용 할
수 없다.
5. OUTLINE 이란
백문이 불 여 일견이다. 생성된 Outline 을 먼저 살펴보자.
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
DB_VERSION('11.2.0.3')
OPT_PARAM('_optim_peek_user_binds' 'false')
PUSH_PRED(@"SEL$1" "PLAN"@"SEL$1" 11 10 9)
OUTLINE(@"SEL$1")
NO_ACCESS(@"SEL$1" "PLAN"@"SEL$1")
USE_NL(@"SEL$1" "C"@"SEL$1")
PUSH_SUBQ(@"SEL$4")
NLJ_BATCHING(@"SEL$4" "PL"@"SEL$4")
END_OUTLINE_DATA
Part 1 ORACLE │53
*/
Outline 은 Oracle Optimizer 가 최적의 플랜을 만들기 위해서 수행한 작업의 결과라고 할 수 있
다. 실제로 OUTLINE 정보는 10053 Trace 에서 가장 마지막에 확인 할 수 있다. OUTLINE 은
DBMS_XPLAN Package 를 통해서도 확인 가능하다.
6. PLAN_SET_OUTLINE Source
-- GRANT ADMINISTER SQL MANAGEMENT OBJECT to USER; 권한 필요
create or replace procedure PLAN_SET_OUTLINE(v_sql_id_asis in varchar2, v_sql_id_tobe
in varchar2)
is
l_sql_fulltext clob;
l_hint_table sys.dbms_debug_vc2coll;
l_profile_hints sys.sqlprof_attr := sys.sqlprof_attr();
i pls_integer;
begin
select sql_fulltext
INTO l_sql_fulltext
from v$sqlarea
where sql_id = v_sql_id_asis;
with a as (
select
rownum as r_no
, a.*
from
table(
dbms_xplan.display_cursor(
v_sql_id_tobe
, null
, 'OUTLINE'
54│2013 기술백서 White Paper
)
) a
)
select substr(plan_table_output, 7) outln
bulk collect into l_hint_table
from a
where r_no between ( select min(r_no) from a where instr(a.PLAN_TABLE_OUTPUT,
'BEGIN_OUTLINE_DATA') = 7)
and ( select min(r_no) from a where instr(a.PLAN_TABLE_OUTPUT,
'END_OUTLINE_DATA') = 7)
order by r_no;
i := l_hint_table.first;
while i is not null
loop
if l_hint_table.exists(i + 1) then
if substr(l_hint_table(i + 1), 1, 1) = ' ' then
l_hint_table(i) := l_hint_table(i) || trim(l_hint_table(i + 1));
l_hint_table.delete(i + 1);
end if;
end if;
i := l_hint_table.next(i);
end loop;
i := l_hint_table.first;
while i is not null
loop
l_profile_hints.extend;
l_profile_hints(l_profile_hints.count) := l_hint_table(i);
i := l_hint_table.next(i);
end loop;
dbms_sqltune.import_sql_profile(
name => 'PROFILE_'||v_sql_id_asis
,replace => TRUE
,sql_text => l_sql_fulltext
,profile => l_profile_hints
);
end PLAN_SET_OUTLINE;
/
Part 1 ORACLE │55
7. 사용 예
[1] TEST 용 데이터 생성
create table exem_t1
as
select level c1, level c2, LPAD(LEVEl, 100, '_') C3 from dual
connect by level <= 1000;
create index ix_exem_t1_01 on exem_t1(c1);
create index ix_exem_t1_02 on exem_t1(c2);
<Trace 수행을 위한 Parameter 적용>
alter session set statistics_level = 'ALL';
[2] 비효율 SQL 의 SQL ID 확인.
select * from exem_t1 t1
where c1 in (select c1 from exem_t1 where c2 <= 10);
select prev_sql_id, (select substr(sql_text,1,64) text from v$sqlarea where sql_id =
prev_sql_id) text from v$session where sid = userenv('sid');
PREV_SQL_ID TEXT
-------------- ---------------------------------------------------------------------
0h60tr4xc2mub select * from exem_t1 t1 where c1 in (select c1 from exem_t1 whe
select * from table(dbms_xplan.display_cursor('0h60tr4xc2mub', null, 'typical allstats
last'));
-----------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 |00:00:00.01 |
|* 1 | HASH JOIN RIGHT SEMI | | 1 | 10 |00:00:00.01 |
| 2 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 |00:00:00.01 |
|* 3 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 |00:00:00.01 |
| 4 | TABLE ACCESS FULL | EXEM_T1 | 1 | 1000 |00:00:00.01 |
-------------------------------------------------------------------------------------------
56│2013 기술백서 White Paper
[3] 개선된 SQL 의 SQL ID 확인.
select /*+ LEADING(exem_t1@SEL$2) USE_NL(t1) */ * from exem_t1 t1
where c1 in (select /*+ UNNEST */ c1 from exem_t1 where c2 <= 10);
select prev_sql_id, (select substr(sql_text,1,64) text from v$sqlarea where sql_id =
prev_sql_id) text from v$session where sid = userenv('sid');
PREV_SQL_ID TEXT
-------------- ---------------------------------------------------------------------
0bjfkr111hxpa select /*+ LEADING(exem_t1@SEL$2) USE_NL(t1) */ * from exem_t1 A
where c1
select * from table(dbms_xplan.display_cursor('0bjfkr111hxpa', 0, 'typical allstats
last'));
-----------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 00:00:00.01 |
| 1 | NESTED LOOPS | | 1 | 10 | 00:00:00.01 |
| 2 | NESTED LOOPS | | 1 | 10 | 00:00:00.01 |
| 3 | SORT UNIQUE | | 1 | 10 | 00:00:00.01 |
| 4 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 | 00:00:00.01 |
|* 5 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 | 00:00:00.01 |
|* 6 | INDEX RANGE SCAN | IX_EXEM_T1_01 | 10 | 10 | 00:00:00.01 |
| 7 | TABLE ACCESS BY INDEX ROWID | EXEM_T1 | 10 | 10 | 00:00:00.01 |
-----------------------------------------------------------------------------------
[4] SQL Profile 교체
-- PLAN_SET_OUTLINE('ASIS_SQL_ID', 'TOBE_SQL_ID')
exec PLAN_SET_OUTLINE('0h60tr4xc2mub', '0bjfkr111hxpa');
[5] Outline 적용 확인
<DBMS_XPLAN note 항목을 통한 확인>
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 |00:00:00.01 |
Part 1 ORACLE │57
| 1 | NESTED LOOPS | | 1 | 10 |00:00:00.01 |
| 2 | NESTED LOOPS | | 1 | 10 |00:00:00.01 |
| 3 | SORT UNIQUE | | 1 | 10 |00:00:00.01 |
| 4 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 |00:00:00.01 |
|* 5 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 |00:00:00.01 |
|* 6 | INDEX RANGE SCAN | IX_EXEM_T1_01 | 10 | 10 |00:00:00.01 |
| 7 | TABLE ACCESS BY INDEX ROWID | EXEM_T1 | 10 | 10 |00:00:00.01 |
--------------------------------------------------------------------------------------
Note
-----
- SQL profile PROFILE_0h60tr4xc2mub used for this statement
<V$SQLAREA.sql_profile 을 이용한 확인>
select sql_id, sql_profile
from v$sqlarea
where sql_id = '0h60tr4xc2mub';
SQL_ID SQL_PROFILE
------------- ---------------------
0h60tr4xc2mub PROFILE_0h60tr4xc2mub <<-- 프로파일 적용된 이후에 쿼리가 수행하면서
sql_profile 칼럼에 표시됨
[6] Profile Drop
<profile 확인>
select name, category, substr(sql_text, 1, 64) text
from DBA_SQL_PROFILES;
name, category, text
PROFILE_0h60tr4xc2mub DEFAULT "select * from exem_t1 t1 where c1 in (select c1
from exem_t1 whe"
<profile 삭제>
exec dbms_sqltune.drop_sql_profile('PROFILE_dgbmvzfktnt7w');
58│2013 기술백서 White Paper
8. 주의사항 & 고급사용
비효율 쿼리를 개선하는 과정에서 쿼리를 REWRITE 하는 경우 개선 후 쿼리와 같은 플랜으로
적용되지 않는다. 쿼리에 없던 Alias 를 적용하는 경우와 QB_NAME 힌트를 사용하는 경우에도
플랜이 적용되지 않는다.
Oracle 쿼리는 Parsing 과정에서 Query Block 단위로 나눠진다. 우리가 사용한 USE_NL(T1
T2) 힌트를 OUTLINE 에서 확인해보면 아래와 같이 쿼리 블록을 이용하고 있음을 확인 할 수
있다.
USE_NL(@"SEL$5DA710D3" "T1"@"SEL$1")
USE_NL(@"SEL$5DA710D3" "T2"@"SEL$1")
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
4 - SEL$5DA710D3 / EXEM_T1@SEL$2
5 - SEL$5DA710D3 / EXEM_T1@SEL$2
6 - SEL$5DA710D3 / T1@SEL$1
7 - SEL$5DA710D3 / T2@SEL$1
느낌이 오는가? QB_NAME 힌트를 사용하지 않고 SEL$1 이름을 그대로 사용할 수 있다.
Optimizer 는 기본적으로 메인 쿼리 블록부터 SEL$1 SEL$2 순으로 블록을 지정한다. 따라서
한 쿼리 안에 같은 테이블이 여러 번 등장하거나, 동일한 Alias 가 여러 번 등장하여도 내부적으
로 사용하는 Query Block Name 을 이용하여 OUTLINE 교체가 가능하다.

More Related Content

What's hot

SQL PlAN MANAGEMENT 활용_Wh oracle
SQL PlAN MANAGEMENT 활용_Wh oracleSQL PlAN MANAGEMENT 활용_Wh oracle
SQL PlAN MANAGEMENT 활용_Wh oracle엑셈
 
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracleBind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle엑셈
 
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracleSPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle엑셈
 
KEEP BUFFER 활용 방안_Wh oracle
KEEP BUFFER 활용 방안_Wh oracleKEEP BUFFER 활용 방안_Wh oracle
KEEP BUFFER 활용 방안_Wh oracle엑셈
 
NLJ BATCH와 부분범위 처리_Wh oracle
NLJ BATCH와 부분범위 처리_Wh oracleNLJ BATCH와 부분범위 처리_Wh oracle
NLJ BATCH와 부분범위 처리_Wh oracle엑셈
 
BlOOM FILTER의 이해와 활용방법_Wh oracle
BlOOM FILTER의 이해와 활용방법_Wh oracleBlOOM FILTER의 이해와 활용방법_Wh oracle
BlOOM FILTER의 이해와 활용방법_Wh oracle엑셈
 
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3Seok-joon Yun
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL TuningPgDay.Seoul
 
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)탑크리에듀(구로디지털단지역3번출구 2분거리)
 
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1Seok-joon Yun
 
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2Seok-joon Yun
 
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개PgDay.Seoul
 
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstatSeok-joon Yun
 
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracleTABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle엑셈
 
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링Jiho Lee
 
오렌지6.0 교육자료
오렌지6.0 교육자료오렌지6.0 교육자료
오렌지6.0 교육자료Seok-joon Yun
 
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQLPgDay.Seoul
 
효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차희동 강
 
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4Seok-joon Yun
 

What's hot (20)

SQL PlAN MANAGEMENT 활용_Wh oracle
SQL PlAN MANAGEMENT 활용_Wh oracleSQL PlAN MANAGEMENT 활용_Wh oracle
SQL PlAN MANAGEMENT 활용_Wh oracle
 
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracleBind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle
Bind Peeking 한계에 따른 Adaptive Cursor Sharing 등장_Wh oracle
 
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracleSPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle
SPA(SQL Performance Analyze)를 이용한 통계 정보 수집_Wh oracle
 
KEEP BUFFER 활용 방안_Wh oracle
KEEP BUFFER 활용 방안_Wh oracleKEEP BUFFER 활용 방안_Wh oracle
KEEP BUFFER 활용 방안_Wh oracle
 
NLJ BATCH와 부분범위 처리_Wh oracle
NLJ BATCH와 부분범위 처리_Wh oracleNLJ BATCH와 부분범위 처리_Wh oracle
NLJ BATCH와 부분범위 처리_Wh oracle
 
BlOOM FILTER의 이해와 활용방법_Wh oracle
BlOOM FILTER의 이해와 활용방법_Wh oracleBlOOM FILTER의 이해와 활용방법_Wh oracle
BlOOM FILTER의 이해와 활용방법_Wh oracle
 
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3
[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning
 
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)
#1.SQL초보에서 Schema Objects까지(SQL학원/오라클학원/IT실무교육학원/재직자/실업자교육학원추천)
 
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1
[2015-06-12] Oracle 성능 최적화 및 품질 고도화 1
 
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2
[2015-06-19] Oracle 성능 최적화 및 품질 고도화 2
 
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개
 
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat
[2015-07-10-윤석준] Oracle 성능 관리 & v$sysstat
 
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...
오라클 커서(Cursor) 개념 및 오라클 메모리 구조_PL/SQL,오라클커서강좌,SGA, PGA, UGA, Shared Pool, Sha...
 
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracleTABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
 
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링
Pg 클러스터 기반의 구성 및 이전, 그리고 인덱스 클러스터링
 
오렌지6.0 교육자료
오렌지6.0 교육자료오렌지6.0 교육자료
오렌지6.0 교육자료
 
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
 
효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차
 
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4
[2015 07-06-윤석준] Oracle 성능 최적화 및 품질 고도화 4
 

Viewers also liked

TCP 연결 과정_Wh apm
TCP 연결 과정_Wh apmTCP 연결 과정_Wh apm
TCP 연결 과정_Wh apm엑셈
 
IBM JVM GC_Wh apm
IBM JVM GC_Wh apmIBM JVM GC_Wh apm
IBM JVM GC_Wh apm엑셈
 
스위치의 분류 및 역할_Wh apm
스위치의 분류 및 역할_Wh apm스위치의 분류 및 역할_Wh apm
스위치의 분류 및 역할_Wh apm엑셈
 
Class Loader_Wh apm
Class Loader_Wh apmClass Loader_Wh apm
Class Loader_Wh apm엑셈
 
All about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apmAll about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apm엑셈
 
Runtime Data Areas_Wh apm
Runtime Data Areas_Wh apmRuntime Data Areas_Wh apm
Runtime Data Areas_Wh apm엑셈
 
JVM Synchronization_Wh apm
JVM Synchronization_Wh apmJVM Synchronization_Wh apm
JVM Synchronization_Wh apm엑셈
 
네트워크 기반 통신 및 계층 구조_Wh apm
네트워크 기반 통신 및 계층 구조_Wh apm네트워크 기반 통신 및 계층 구조_Wh apm
네트워크 기반 통신 및 계층 구조_Wh apm엑셈
 
TP-Monitor_Wh apm
TP-Monitor_Wh apmTP-Monitor_Wh apm
TP-Monitor_Wh apm엑셈
 
Hotspot JVM GC_Wh apm
Hotspot JVM GC_Wh apmHotspot JVM GC_Wh apm
Hotspot JVM GC_Wh apm엑셈
 
웹 서버의 기능 및 역할_Wh apm
웹 서버의 기능 및 역할_Wh apm웹 서버의 기능 및 역할_Wh apm
웹 서버의 기능 및 역할_Wh apm엑셈
 
WAS의 동작과 WEB, Servlet, JSP_Wh apm
WAS의 동작과 WEB, Servlet, JSP_Wh apmWAS의 동작과 WEB, Servlet, JSP_Wh apm
WAS의 동작과 WEB, Servlet, JSP_Wh apm엑셈
 
SSD 개념 및 활용_Wh oracle
SSD 개념 및 활용_Wh oracleSSD 개념 및 활용_Wh oracle
SSD 개념 및 활용_Wh oracle엑셈
 

Viewers also liked (13)

TCP 연결 과정_Wh apm
TCP 연결 과정_Wh apmTCP 연결 과정_Wh apm
TCP 연결 과정_Wh apm
 
IBM JVM GC_Wh apm
IBM JVM GC_Wh apmIBM JVM GC_Wh apm
IBM JVM GC_Wh apm
 
스위치의 분류 및 역할_Wh apm
스위치의 분류 및 역할_Wh apm스위치의 분류 및 역할_Wh apm
스위치의 분류 및 역할_Wh apm
 
Class Loader_Wh apm
Class Loader_Wh apmClass Loader_Wh apm
Class Loader_Wh apm
 
All about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apmAll about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apm
 
Runtime Data Areas_Wh apm
Runtime Data Areas_Wh apmRuntime Data Areas_Wh apm
Runtime Data Areas_Wh apm
 
JVM Synchronization_Wh apm
JVM Synchronization_Wh apmJVM Synchronization_Wh apm
JVM Synchronization_Wh apm
 
네트워크 기반 통신 및 계층 구조_Wh apm
네트워크 기반 통신 및 계층 구조_Wh apm네트워크 기반 통신 및 계층 구조_Wh apm
네트워크 기반 통신 및 계층 구조_Wh apm
 
TP-Monitor_Wh apm
TP-Monitor_Wh apmTP-Monitor_Wh apm
TP-Monitor_Wh apm
 
Hotspot JVM GC_Wh apm
Hotspot JVM GC_Wh apmHotspot JVM GC_Wh apm
Hotspot JVM GC_Wh apm
 
웹 서버의 기능 및 역할_Wh apm
웹 서버의 기능 및 역할_Wh apm웹 서버의 기능 및 역할_Wh apm
웹 서버의 기능 및 역할_Wh apm
 
WAS의 동작과 WEB, Servlet, JSP_Wh apm
WAS의 동작과 WEB, Servlet, JSP_Wh apmWAS의 동작과 WEB, Servlet, JSP_Wh apm
WAS의 동작과 WEB, Servlet, JSP_Wh apm
 
SSD 개념 및 활용_Wh oracle
SSD 개념 및 활용_Wh oracleSSD 개념 및 활용_Wh oracle
SSD 개념 및 활용_Wh oracle
 

Similar to SQL Profile을 이용한 SQL Plan 변경_Wh oracle

Database 튜닝 교육 110124
Database 튜닝 교육 110124Database 튜닝 교육 110124
Database 튜닝 교육 110124한 경만
 
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Fundamentals of Oracle SQL
Fundamentals of Oracle SQLFundamentals of Oracle SQL
Fundamentals of Oracle SQLJAEGEUN YU
 
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천탑크리에듀(구로디지털단지역3번출구 2분거리)
 
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기Kenu, GwangNam Heo
 
제1회 Tech Net Sql Server 2005 T Sql Enhancements
제1회 Tech Net Sql Server 2005 T Sql Enhancements제1회 Tech Net Sql Server 2005 T Sql Enhancements
제1회 Tech Net Sql Server 2005 T Sql Enhancementsbeamofhope
 
04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)Hankyo
 
My sql tde kr_v1.0
My sql tde kr_v1.0My sql tde kr_v1.0
My sql tde kr_v1.0Sumi Ryu
 

Similar to SQL Profile을 이용한 SQL Plan 변경_Wh oracle (20)

3.3 실행계획 SQL 연산 (Count,Count Stopkey/Filter)
3.3 실행계획 SQL 연산 (Count,Count Stopkey/Filter)3.3 실행계획 SQL 연산 (Count,Count Stopkey/Filter)
3.3 실행계획 SQL 연산 (Count,Count Stopkey/Filter)
 
3.5 실행계획 SQL 연산 (HASH SEMI-JOIN)
3.5 실행계획 SQL 연산 (HASH SEMI-JOIN)3.5 실행계획 SQL 연산 (HASH SEMI-JOIN)
3.5 실행계획 SQL 연산 (HASH SEMI-JOIN)
 
2.1 optimizer mode를 변경하는 힌트(rule)
2.1 optimizer mode를 변경하는 힌트(rule)2.1 optimizer mode를 변경하는 힌트(rule)
2.1 optimizer mode를 변경하는 힌트(rule)
 
3.2 실행계획 sql 연산 (concatenation)
3.2 실행계획 sql 연산 (concatenation)3.2 실행계획 sql 연산 (concatenation)
3.2 실행계획 sql 연산 (concatenation)
 
1.8 튜닝의도구 dbms xplan
1.8 튜닝의도구 dbms xplan1.8 튜닝의도구 dbms xplan
1.8 튜닝의도구 dbms xplan
 
Database 튜닝 교육 110124
Database 튜닝 교육 110124Database 튜닝 교육 110124
Database 튜닝 교육 110124
 
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천
#25.SQL초보에서 Schema Objects까지_구로IT학원/국비지원IT학원추천/구로디지털단지IT학원/재직자환급교육추천
 
Fundamentals of Oracle SQL
Fundamentals of Oracle SQLFundamentals of Oracle SQL
Fundamentals of Oracle SQL
 
1.7 튜닝의도구 sql autorace
1.7 튜닝의도구 sql autorace1.7 튜닝의도구 sql autorace
1.7 튜닝의도구 sql autorace
 
Sql기초강좌2_SET AUTOTRACE_SQL교육
Sql기초강좌2_SET AUTOTRACE_SQL교육Sql기초강좌2_SET AUTOTRACE_SQL교육
Sql기초강좌2_SET AUTOTRACE_SQL교육
 
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
 
3.8 실행계획 SQL 연산 (MERGE JOIN, MERGE SEMI JOIN)
3.8 실행계획 SQL 연산 (MERGE JOIN, MERGE SEMI JOIN)3.8 실행계획 SQL 연산 (MERGE JOIN, MERGE SEMI JOIN)
3.8 실행계획 SQL 연산 (MERGE JOIN, MERGE SEMI JOIN)
 
5.2 비트맵 인덱스
5.2 비트맵 인덱스5.2 비트맵 인덱스
5.2 비트맵 인덱스
 
3.4 실행계획 SQL 연산 (Hash Anti-Join)
3.4 실행계획 SQL 연산 (Hash Anti-Join)3.4 실행계획 SQL 연산 (Hash Anti-Join)
3.4 실행계획 SQL 연산 (Hash Anti-Join)
 
6.2 hints for access paths(cluster)
6.2 hints for access paths(cluster)6.2 hints for access paths(cluster)
6.2 hints for access paths(cluster)
 
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기
ecdevday8 웹개발자의 약한고리 SQL 뛰어넘기
 
제1회 Tech Net Sql Server 2005 T Sql Enhancements
제1회 Tech Net Sql Server 2005 T Sql Enhancements제1회 Tech Net Sql Server 2005 T Sql Enhancements
제1회 Tech Net Sql Server 2005 T Sql Enhancements
 
04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)
 
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
 
My sql tde kr_v1.0
My sql tde kr_v1.0My sql tde kr_v1.0
My sql tde kr_v1.0
 

SQL Profile을 이용한 SQL Plan 변경_Wh oracle

  • 1. 50│2013 기술백서 White Paper SQL Profile을 이용한 SQL Plan 변경 ㈜엑셈 컨설팅본부/DB컨설팅팀 오 경렬 본 문서는 DBMS_SQLTUNE Package 를 이용하여 SQL Plan 을 변경하는 PLAN_SET_OUTLINE (가칭) User Define Procedure 에 관한 글로 다음과 같은 내용을 포함 한다.  SQL Plan 변경의 필요성  SQL Plan 변경을 위한 기능은 9i 부터 제공  뭐가 다른가?  SQL Profile 이란  OUTLINE 이란  PLAN_SET_OUTLINE Source  사용 예  주의사항 & 고급 사용 1. SQL Plan 변경의 필요성 Oracle 을 사용하는 사이트라면 SQL 성능이슈를 한번쯤을 겪어봤을 것이다. 보통 비효율 SQL 을 수정하고 Application 에 반영하여 정상적인 서비스를 운영하기 까지는 많은 시간이 소요될 수 있다. 해당 SQL 이 수행되는 업무와 관련된 업무들이 영향을 받기 때문에 서비스를 일시 정 지 해야 하는 경우도 있고 비효율 SQL 이 어느 소스에서 수행되는지 파악하는 시간으로 인해 쉽게 해결될 일이 장애 상황까지 발전할 수도 있다. 가장 흔하게는 통계정보 생성에 의한 경우 부터 소스 배포 과정에서 검증되지 않은 SQL 이 배포되는 경우까지 비효율 SQL 이 발생할 수 있는 케이스는 다양하다.
  • 2. Part 1 ORACLE │51 2. SQL Plan 변경을 위한 기능은 9i부터 제공 Oracle 은 이미 9i 버전부터 Stored Outline 을 이용해서 SQL 플랜을 변경하는 방법을 제공했 다. 아이러니하게도 Oracle 9i 에서는 Stored Outline 을 이용한 플랜 변경은 실 운영환경에서 (적어도 필자의 경험에서는) 정상 동작하지 않는다. 9i 에서 등장한 Stored Outline 을 이용한 SQL 플랜 변경은 10g 버전부터 정상적으로 동작한다. Oracle 10g 에는 SQL Profile 이라는 것 을 새롭게 등장한다. 간단하게 개념을 잡는다면 SQL Profile 은 Stored Outline 을 포함하는 더 큰 틀이라 할 수 있다. 3. 뭐가 다른가? 이미 온라인상에는 SQL Plan 변경을 위한 이론과 방법이 정리된 수많은 기술문서가 존재한다. 하지만 안타깝게도 실 환경에서 사용하기에는 뭔가 복잡하고 손이 많이 간다. SQL Plan 변경 이 필요한 경우에 빠른 해결이 중요한 포인트이다. 10g 에서 SQL Profile 을 이용해서 플랜을 변경하려면 Outline 을 하나하나 적어줘야 하는데 여간 귀찮은 작업이 아니다. 필자의 Procedure 는 사용이 매우 간단하다. EXEC PLAN_SET_OUTLINE(‘개선 전 SQLID’, ‘개선 후 SQLID’); 플랜이 변경되었습니다. 4. SQL Profile 이란 SQL Profile 은 특정 SQL 문에 연결할 수 있는 SQL 컴파일러 통계의 모음을 말한다. SQL Profile 이 현재 SQL 문에 생성되면, SQL 분석 (컴파일)을 수행할 때 프로파일의 통계는 컴파일 러에 의해 사용된다. SQL 문장의 정규화된 텍스트가 SQL 프로파일 작성시에 제공된 SQL 텍스 트와 일치하는 경우프로파일이 SQL 컴파일 사용되는 것이다. SQL 텍스트의 정규화란, 모든 비 Literal 텍스트를 대문자로 변경하고 빈 공간이 없애는 것을 말한다. 컴파일을 수행한 세션에서 는 SQL 프로파일이 생성된 카테고리 및 Parameter 에 대해서 동일한 값을 가지고 있어야 한다.
  • 3. 52│2013 기술백서 White Paper 카테고리는 여러 프로파일이 동일한 SQL 문에 존재하는 것을 허용한다. 한 세션에서 특정 카테 고리 네임스페이스의 프로파일을 만들어 비공개 프로파일을 테스트 할 수 있습니다. SQL 프로파일은 다음과 같은 SQL 문장에 대해서 사용 가능하다.  SELECT statements  UPDATE statements  INSERT (but only with a SELECT clause) statements  DELETE statements  CREATE TABLE (but only with the AS SELECT clause)  MERGE statements (the upsert operation) Data Dictionary 에서 내부적으로 수행된 SQL 문(재귀 SQL)에 대해서는 프로파일을 사용할 수 없다. 또한, 데이터베이스가 오픈 되기 전에 수행되는 모든 SQL 역시 프로파일을 검색, 사용 할 수 없다. 5. OUTLINE 이란 백문이 불 여 일견이다. 생성된 Outline 을 먼저 살펴보자. /*+ BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS OPTIMIZER_FEATURES_ENABLE('11.2.0.3') DB_VERSION('11.2.0.3') OPT_PARAM('_optim_peek_user_binds' 'false') PUSH_PRED(@"SEL$1" "PLAN"@"SEL$1" 11 10 9) OUTLINE(@"SEL$1") NO_ACCESS(@"SEL$1" "PLAN"@"SEL$1") USE_NL(@"SEL$1" "C"@"SEL$1") PUSH_SUBQ(@"SEL$4") NLJ_BATCHING(@"SEL$4" "PL"@"SEL$4") END_OUTLINE_DATA
  • 4. Part 1 ORACLE │53 */ Outline 은 Oracle Optimizer 가 최적의 플랜을 만들기 위해서 수행한 작업의 결과라고 할 수 있 다. 실제로 OUTLINE 정보는 10053 Trace 에서 가장 마지막에 확인 할 수 있다. OUTLINE 은 DBMS_XPLAN Package 를 통해서도 확인 가능하다. 6. PLAN_SET_OUTLINE Source -- GRANT ADMINISTER SQL MANAGEMENT OBJECT to USER; 권한 필요 create or replace procedure PLAN_SET_OUTLINE(v_sql_id_asis in varchar2, v_sql_id_tobe in varchar2) is l_sql_fulltext clob; l_hint_table sys.dbms_debug_vc2coll; l_profile_hints sys.sqlprof_attr := sys.sqlprof_attr(); i pls_integer; begin select sql_fulltext INTO l_sql_fulltext from v$sqlarea where sql_id = v_sql_id_asis; with a as ( select rownum as r_no , a.* from table( dbms_xplan.display_cursor( v_sql_id_tobe , null , 'OUTLINE'
  • 5. 54│2013 기술백서 White Paper ) ) a ) select substr(plan_table_output, 7) outln bulk collect into l_hint_table from a where r_no between ( select min(r_no) from a where instr(a.PLAN_TABLE_OUTPUT, 'BEGIN_OUTLINE_DATA') = 7) and ( select min(r_no) from a where instr(a.PLAN_TABLE_OUTPUT, 'END_OUTLINE_DATA') = 7) order by r_no; i := l_hint_table.first; while i is not null loop if l_hint_table.exists(i + 1) then if substr(l_hint_table(i + 1), 1, 1) = ' ' then l_hint_table(i) := l_hint_table(i) || trim(l_hint_table(i + 1)); l_hint_table.delete(i + 1); end if; end if; i := l_hint_table.next(i); end loop; i := l_hint_table.first; while i is not null loop l_profile_hints.extend; l_profile_hints(l_profile_hints.count) := l_hint_table(i); i := l_hint_table.next(i); end loop; dbms_sqltune.import_sql_profile( name => 'PROFILE_'||v_sql_id_asis ,replace => TRUE ,sql_text => l_sql_fulltext ,profile => l_profile_hints ); end PLAN_SET_OUTLINE; /
  • 6. Part 1 ORACLE │55 7. 사용 예 [1] TEST 용 데이터 생성 create table exem_t1 as select level c1, level c2, LPAD(LEVEl, 100, '_') C3 from dual connect by level <= 1000; create index ix_exem_t1_01 on exem_t1(c1); create index ix_exem_t1_02 on exem_t1(c2); <Trace 수행을 위한 Parameter 적용> alter session set statistics_level = 'ALL'; [2] 비효율 SQL 의 SQL ID 확인. select * from exem_t1 t1 where c1 in (select c1 from exem_t1 where c2 <= 10); select prev_sql_id, (select substr(sql_text,1,64) text from v$sqlarea where sql_id = prev_sql_id) text from v$session where sid = userenv('sid'); PREV_SQL_ID TEXT -------------- --------------------------------------------------------------------- 0h60tr4xc2mub select * from exem_t1 t1 where c1 in (select c1 from exem_t1 whe select * from table(dbms_xplan.display_cursor('0h60tr4xc2mub', null, 'typical allstats last')); ----------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | A-Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 10 |00:00:00.01 | |* 1 | HASH JOIN RIGHT SEMI | | 1 | 10 |00:00:00.01 | | 2 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 |00:00:00.01 | |* 3 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 |00:00:00.01 | | 4 | TABLE ACCESS FULL | EXEM_T1 | 1 | 1000 |00:00:00.01 | -------------------------------------------------------------------------------------------
  • 7. 56│2013 기술백서 White Paper [3] 개선된 SQL 의 SQL ID 확인. select /*+ LEADING(exem_t1@SEL$2) USE_NL(t1) */ * from exem_t1 t1 where c1 in (select /*+ UNNEST */ c1 from exem_t1 where c2 <= 10); select prev_sql_id, (select substr(sql_text,1,64) text from v$sqlarea where sql_id = prev_sql_id) text from v$session where sid = userenv('sid'); PREV_SQL_ID TEXT -------------- --------------------------------------------------------------------- 0bjfkr111hxpa select /*+ LEADING(exem_t1@SEL$2) USE_NL(t1) */ * from exem_t1 A where c1 select * from table(dbms_xplan.display_cursor('0bjfkr111hxpa', 0, 'typical allstats last')); ----------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | A-Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 10 | 00:00:00.01 | | 1 | NESTED LOOPS | | 1 | 10 | 00:00:00.01 | | 2 | NESTED LOOPS | | 1 | 10 | 00:00:00.01 | | 3 | SORT UNIQUE | | 1 | 10 | 00:00:00.01 | | 4 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 | 00:00:00.01 | |* 5 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 | 00:00:00.01 | |* 6 | INDEX RANGE SCAN | IX_EXEM_T1_01 | 10 | 10 | 00:00:00.01 | | 7 | TABLE ACCESS BY INDEX ROWID | EXEM_T1 | 10 | 10 | 00:00:00.01 | ----------------------------------------------------------------------------------- [4] SQL Profile 교체 -- PLAN_SET_OUTLINE('ASIS_SQL_ID', 'TOBE_SQL_ID') exec PLAN_SET_OUTLINE('0h60tr4xc2mub', '0bjfkr111hxpa'); [5] Outline 적용 확인 <DBMS_XPLAN note 항목을 통한 확인> ------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | A-Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 10 |00:00:00.01 |
  • 8. Part 1 ORACLE │57 | 1 | NESTED LOOPS | | 1 | 10 |00:00:00.01 | | 2 | NESTED LOOPS | | 1 | 10 |00:00:00.01 | | 3 | SORT UNIQUE | | 1 | 10 |00:00:00.01 | | 4 | TABLE ACCESS BY INDEX ROWID| EXEM_T1 | 1 | 10 |00:00:00.01 | |* 5 | INDEX RANGE SCAN | IX_EXEM_T1_02 | 1 | 10 |00:00:00.01 | |* 6 | INDEX RANGE SCAN | IX_EXEM_T1_01 | 10 | 10 |00:00:00.01 | | 7 | TABLE ACCESS BY INDEX ROWID | EXEM_T1 | 10 | 10 |00:00:00.01 | -------------------------------------------------------------------------------------- Note ----- - SQL profile PROFILE_0h60tr4xc2mub used for this statement <V$SQLAREA.sql_profile 을 이용한 확인> select sql_id, sql_profile from v$sqlarea where sql_id = '0h60tr4xc2mub'; SQL_ID SQL_PROFILE ------------- --------------------- 0h60tr4xc2mub PROFILE_0h60tr4xc2mub <<-- 프로파일 적용된 이후에 쿼리가 수행하면서 sql_profile 칼럼에 표시됨 [6] Profile Drop <profile 확인> select name, category, substr(sql_text, 1, 64) text from DBA_SQL_PROFILES; name, category, text PROFILE_0h60tr4xc2mub DEFAULT "select * from exem_t1 t1 where c1 in (select c1 from exem_t1 whe" <profile 삭제> exec dbms_sqltune.drop_sql_profile('PROFILE_dgbmvzfktnt7w');
  • 9. 58│2013 기술백서 White Paper 8. 주의사항 & 고급사용 비효율 쿼리를 개선하는 과정에서 쿼리를 REWRITE 하는 경우 개선 후 쿼리와 같은 플랜으로 적용되지 않는다. 쿼리에 없던 Alias 를 적용하는 경우와 QB_NAME 힌트를 사용하는 경우에도 플랜이 적용되지 않는다. Oracle 쿼리는 Parsing 과정에서 Query Block 단위로 나눠진다. 우리가 사용한 USE_NL(T1 T2) 힌트를 OUTLINE 에서 확인해보면 아래와 같이 쿼리 블록을 이용하고 있음을 확인 할 수 있다. USE_NL(@"SEL$5DA710D3" "T1"@"SEL$1") USE_NL(@"SEL$5DA710D3" "T2"@"SEL$1") Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$5DA710D3 4 - SEL$5DA710D3 / EXEM_T1@SEL$2 5 - SEL$5DA710D3 / EXEM_T1@SEL$2 6 - SEL$5DA710D3 / T1@SEL$1 7 - SEL$5DA710D3 / T2@SEL$1 느낌이 오는가? QB_NAME 힌트를 사용하지 않고 SEL$1 이름을 그대로 사용할 수 있다. Optimizer 는 기본적으로 메인 쿼리 블록부터 SEL$1 SEL$2 순으로 블록을 지정한다. 따라서 한 쿼리 안에 같은 테이블이 여러 번 등장하거나, 동일한 Alias 가 여러 번 등장하여도 내부적으 로 사용하는 Query Block Name 을 이용하여 OUTLINE 교체가 가능하다.