ORACLE/ADMIN2014. 3. 23. 22:45
반응형

04 커서공유


(1) 커서란?

공유 커서 (shared cursor) : 라이브러리 캐시에 공유돼 있는 Shared SQL Area
세션 커서 (session cursor) : Private SQL AREA에 저장된 커서
애플리케이션 커서 (application cursor) : 세션 커서를 가리키는 핸들

그림 7

라이브러리 캐시에 공유돼 있는 커서를 실행할 때는 우선 PGA 영역에 메모리를 할당
Private SQL area 라고 하는데 , Persistent Area 와 Runtime Area로 나뉜다.
Shared SQL Area를 읽어 커서를 실행하는 데 필요한 정보들을 Private SQL Area에 담고,
공유 커서를 가리키는 포인터를 유지한다.그리고 커서의 상태정보도 관리한다.
커서 를 실행하기 위한 이런 준비과정을 "커서를 오픈한다" 고 표현하고,
PGA에 저장된 커서 정보(즉,파싱된 SQL문과 문장을 수행하능데 필요한 기타 정보)를 또
한 '커서' 라고부른다.

PGA에 있는 커서를 핸들링하려면 JAVA, VB, Pro*C, PL!SQL 같은 클라이언트 애플리케이션에도
리소스를 할당

(2) 커서 공유

######################
커서 공유 테스트
######################

-- sys유저 접속
SQL> grant select_catalog_role to scott;
Statement Processed.

SQL> alter system flush shared_pool;
Statement Processed.

-- SCOTT유저 접속
SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL> select sql_id, parse_calls, loads, executions, invalidations 
      , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
from v$sql 
where sql_text like '%cursor test%' 
and sql_text not like '%v$sql%';

SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
------------- ----------- --------- ---------- ------------- --------- 
896pksq7c53f2           1         1          1             0         0

1 rows selected.

SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL> select sql_id, parse_calls, loads, executions, invalidations 
      , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
from v$sql 
where sql_text like '%cursor test%' 
and sql_text not like '%v$sql%';

SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
------------- ----------- --------- ---------- ------------- --------- 
896pksq7c53f2           3         1          3             0         0

1 rows selected.

  • parse_calls: 라이브러리 캐시에서 SQL 커서를찾으려는요청 횟수
  • loads: 하드파싱을 거친 SQL 실행계획을 라이브러리 캐시에 적재한 횟수
  • executions : SQL을 수행한 횟수
  • invalidations : 커서가 무효화된 횟수. 커서가 참조하고 있는 오브젝트에 중요한 변
    화가일어났음을의미함
#####################################
다른세션 접속후 커서공유 테스트
#####################################

SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.


SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL> select sql_id, parse_calls, loads, executions, invalidations 
      , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
from v$sql 
where sql_text like '%cursor test%' 
and sql_text not like '%v$sql%';

SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
------------- ----------- --------- ---------- ------------- --------- 
896pksq7c53f2           5         1          5             0         0

1 rows selected.

다른 세션에서 같은 SQL을 수행할 때도 이전 세션에서 적재한 커서를 재사용했음을
알수있다.

###################################
통계 재생성후 커서공유 테스트
###################################

SQL> execute DBMS_STATS.GATHER_TABLE_STATS  
(ownname => USER, tabname => 'EMP' 
,no_invalidate => FALSE 
);

PL/SQL executed.
SQL Execution Time > 00:00:05.367

SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL Execution Time > 00:00:00.062
Total Elapsed Time > 00:00:00.062

SQL> select /* cursor test */ empno, ename, job, sal, deptno 
from emp 
where empno = 7788;

EMPNO ENAME      JOB       SAL       DEPTNO 
----- ---------- --------- --------- ------ 
 7788 SCOTT      ANALYST        1000     20

1 rows selected.

SQL Execution Time > 00:00:00.062
Total Elapsed Time > 00:00:00.062

-------------------------[Start Time: 2014/03/04 18:39:12]-------------------------
SQL> select sql_id, parse_calls, loads, executions, invalidations 
      , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
from v$sql 
where sql_text like '%cursor test%' 
and sql_text not like '%v$sql%';

SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
------------- ----------- --------- ---------- ------------- --------- 
896pksq7c53f2           2         2          2             1         1

1 rows selected.

SQL Execution Time > 00:00:00.031
Total Elapsed Time > 00:00:00.047

쿼리를 다시 수행한 후에 v$sql을 다시 조회해 보면, 적재 횟수가 아래처럼 2로 증가한
것을볼수있다.

라이브러리 캐시에 있는 커서틀이 여러 세션에 의해 공유되면서 반복 재사용되는 것
공유된 커서를 사용할 때는 최적화 및 Row-Source Generation 단계를 생략하고
곧바로 실행 단계로 넘어가므로 보다 효율적이고 빠르게 SQL을 수행한다

커서가 공유되려면 커서를 식별하는 키 값이 같아야 함
-> 라이브러리 캐시에서 커서를 식별하기 위해 시용되는 키 값은 'SQL 문장 그 자체'
-> SQL문을 구성하는 전체 문자열이 이름 역할을 한다는 뜻
-> SQL_ID와 SQL FULLTEXT는 1:1로 대응
SQL문 중간에 작은 공백문자 하나만 추가하더라도 서로 다른 SQL 문장으로 인식해 새로운
SQL_ID를발급받게 된다. 즉 커서가 공유되지 않는다.

(3) Child 커서를 공유하지 못하는 경우

8QL마다 하나의 Parent 커서를 가지며, Child 커서는 여러 개일 수 있다.
실제 수행에 필요한 정보는 Child 커서에 담기므로 적어도 한 개의 Child 커서를 갖는다.
v$sqlarea는 Parent 커서 정보를 보여주고36) ' v$sql은 Child 커서 정보를 보여준다.
아래는 SC0TT과 HR 스키마 각각에 EMP 테이블을 만들고 각 계정으로 로그인 해서
select * from emp 쿼리를 수행한 후에 v$sqlarea와 v$sql을 쿼리했을 때의 결과를 보
이고 있다.

##########################
자식커서의 공유 테스트
##########################

C:\WINDOWS\system32>sqlplus "/as sysdba"


SQL> conn /as sysdba
연결되었습니다.
SQL> create table hr.emp as select * from scott.emp;

테이블이 생성되었습니다.

SQL> alter system flush shared_pool;

시스템이 변경되었습니다.

SQL> conn scott/tiger
연결되었습니다.
SQL> select * from emp where empno=7698;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30

SQL> conn hr/hr
연결되었습니다.
SQL> select * from emp where empno=7698;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30


== v$sqlarea는 부모커서를 확인
SQL>  conn /as sysdba
연결되었습니다.
SQL> select sql_id, version_count, optimizer_mode, address, hash_value
  2  from v$sqlarea
  3  where sql_text like 'select * from emp where%'
  4  and sql_text  not like 'v$sql';

SQL_ID        VERSION_COUNT OPTIMIZER_ ADDRESS  HASH_VALUE
------------- ------------- ---------- -------- ----------
5tq0u8y4zd3ta             2 ALL_ROWS   3D9C5BFC 2314637098


== v$sql는 자식커서를 확인
SQL> select sql_id, child_number, optimizer_mode, address, hash_value, parsing_user_id
  2  from v$sql
  3  where sql_text like 'select * from emp where%'
  4   and sql_text  not like 'v$sql';

SQL_ID        CHILD_NUMBER OPTIMIZER_ ADDRESS  HASH_VALUE PARSING_USER_ID
------------- ------------ ---------- -------- ---------- ---------------
5tq0u8y4zd3ta            0 ALL_ROWS   3D9C5BFC 2314637098              84
5tq0u8y4zd3ta            1 ALL_ROWS   3D9C5BFC 2314637098              85


== v$sqlarea 에 동일문장의 버전이 몇개인지 볼수 있다.
select * from v$sqlarea order by version_count desc;

하나의 SQL문장이 여러개 Child 커서를 갖게 되는 대표적인 이유
1. SQL에서 참조하는 오브젝트명이 같지만 SQL을 실행한 사용자에 따라 다른 오브젝트를 가리킬때
2. 참조 오브젝트가 변경돼 커서가 무효화되면 이후 그 커서를 처음 사용하려는 세션에
의해 다시 하드파싱돼야 하는데 특정 세션이 아직 기존 커서를 사용 중(Pin)일 때
3. 옵티마이저 모드를 비롯해 옵티마이저 관련 파라미터가 다를 때
4. 입력된 바인드 값의 길이가 크게 다를 때
5. NLS 파라미터를 다르게 설정했을 때
6. SQL 트레이스를활성화했을때

해당 딕셔너리를 참조해라. ====> V$SQL_SHARED_CURSOR

SQL> conn scott/tiger
연결되었습니다.
SQL> conn /as sysdba
연결되었습니다.
SQL> alter system flush shared_pool;

시스템이 변경되었습니다.

SQL> conn scott/tiger
연결되었습니다.
SQL> alter session set optimizer_mode=first_rows;

세션이 변경되었습니다.

SQL> select * from emp where empno=7698;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30

SQL> alter session set optimizer_mode=all_rows;

세션이 변경되었습니다.

SQL> select * from emp where empno=7698;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30


SQL> conn /as sysdba
연결되었습니다.
SQL> select sql_id, version_count, optimizer_mode, address, hash_value
  2  from v$sqlarea
  3  where sql_text like 'select * from emp where%'
  4  and sql_text  not like 'v$sql';

SQL_ID        VERSION_COUNT OPTIMIZER_ ADDRESS  HASH_VALUE
------------- ------------- ---------- -------- ----------
5tq0u8y4zd3ta             2 ALL_ROWS   3D9C5BFC 2314637098



SQL> select child_number, child_address, optimizer_mode_mismatch, optimizer_mismatch
  2  from V$SQL_SHARED_CURSOR
  3  where SQL_ID = '5tq0u8y4zd3ta'
  4  and ADDRESS  = '3D9C5BFC';

CHILD_NUMBER CHILD_AD O O
------------ -------- - -
           0 37DF4684 N N
           1 37FF5A94 Y N


SQL> select *
  2  from V$SQL_SHARED_CURSOR
  3  where SQL_ID = '5tq0u8y4zd3ta'
  4  and ADDRESS  = '3D9C5BFC';

SQL_ID        ADDRESS  CHILD_AD CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U
 T N F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
------------- -------- -------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5tq0u8y4zd3ta 3D9C5BFC 37DF4684            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N
 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
5tq0u8y4zd3ta 3D9C5BFC 37FF5A94            1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N
 N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N

Version Count 수치가 높은 SQL 일수록 커서를 탐색하는 데 더 많은 시간을 소비하므
로 library cache 래치에 대한 경합 발생 가능성을 증가시킨다.

v$sql_shared_cursor 다이나믹 뷰는 새로운 Child 커서가 왜 기존 Child 커서와 공유
못하는지 확인

(4) Parent 커서를 공유하지 못하는 경우

1. 공백 문자 또는 줄바꿈
SELECT * FROM CUSTOMER;
SELECT *   FROM CUSTOMER;
2 . 대소문자구분
SELECT * FROM CUSTOMER;
SELECT * FROM Customer;
3. 태이블 Owner 명시
SELECT * FROM CUSTOMER;
SELECT * FROM HR.CUSTOMER;
4. 주석 (Comment)
SELECT * FROM CUSTOMER;
SELECT /* 주석문 */ * FROM CUSTOMER;
5. 용티마이져 힌트 사용
SELECT * FROM CUSTOMER;
SELECT /*+ all_rows */ * FROM CUSTOMER;
6. 조건 절 비교값
SELECT * FROM CUSTOMER WHERE CUST_ID = '0000001';
SELECT * FROM CUSTOMER WHERE CUST_ID = '0000002';
이 외에도 더 다양한 케이스가 있을 것이다. 1. 2. 4번은 그 실행계획이 100% 같다.

그럼에도 문자열을 조금 다르게 기술했다는 이유 때문에 서로 다른 SQL로서 각각
하드파싱을 일으카고 서로 다른 공간을 차지하면서 Shared Pool을 낭비하게 된다. 이런
비효율을 줄이고 공유 가능한 형태로 SQL을 작성하려면 개발 초기에 SQL 작성 표준을
정해 이를 준수하도록 해야 한다.

5번은 의도적으로 실행계획을 달리 가져가려는 것이므로 논외로 하고 라이브러리 캐시
효율과 직접 관련이 큰 것은 6번 같은 패턴이다. 즉 조건절에 바인드 변수를 사용하지 않
고 서로 다른 Literal 값으로 문자열을 대체하는 경우다.
만약 OLTP성 업무를 처리하는 애플리케이션에서 6번과 같은 패턴으로 SQL을 개발한
다변 결코 좋은 성능을 보장받을 수 없다. 개별 쿼리 성능으로 보면 잘 느끼지 못하지만
동시 트랜잭션이 몰리는 peak 시간대에 시스템을 장애 상황으로 몰고 가는 주범이다.

==================================================================================================================
공유풀은 힙(heap)으로 불리는 OS메모리 공간으로 구성됨.
힙(heap)은 헤더와 하나이상의 메모리익스텐트로으로 구성됨.
메모리익스텐트는 지속적으로 할당과 반납이 반복되며 여러개 작은조각으로 나누어짐.
메모리 영역이 작은단위로 나누어 지는 것을 공유풀단편화(FRAGMENTATION)이라 함.
단편화로 인해 쪼개진 영역은 청크라고 불리며 프리리스트에 의해 관리됨.
한번 사용된 청크는 다시 프리리스트에 등록되기 전까지 공유풀 LRU리스트에서 관리됨
LRU알고리즘을 이용하여 청크의 재사용률을 높이기 위해서임.

공유풀에 메모리 할당과정
1. 새로운 SQL에 대해 파스 수행하려면 힙영역 새로운 빈공간 할당받아야함.
2. 프리리스트에서 필요한 크기의 프리청크 서칭
3. 프리리스트 서칭후 있으면 힙영역 할당. 없으면 LRU리스트 사용가능 청크를 서칭
4. LRU리스트에도 없으면 4031에러 발생후 SQL파스 실패

예> SQL파스를 위해 256바이트가 필요할�
1. 쉐어드풀 래치획득후 프리리스트로 부터 256바이트의 청크를 검색.

  • 이과정에서 래치를 획득하지 못하면 latch:shared pool 대기 이벤트를 발생시키며 획득가능할때까지 대기.
    2. 256바이트의 프리청크를 찾았다면 해당 청크를 익스텐트에 할당.
  • 이과정에서 256바이트의 프리청크가 없어서 찾지 못했다면 더큰크기의 프리청크를 검색
    3. 400바이트의 프리청크를 찾았다면 필요한 크기의 256바이트와 144바이트의 크기로 쪼갬.
    256바이트 청크를 익스텐트에 할당. 144바이트의 청크는 프리리스트에 등록
  • 이과정에서 256바이트 보다 더 큰 프리청크를 찾지 못했다면 공유풀 LRU리스트로 부터 핀이 해제된 청크중 256바이트 보다 큰 청크를 검색 후 프리리스트 등록
    4. 공유풀LRU리스트 검색시 필요한 크기의 청크를 확인 못할시 4031에러와 SQL파스 실패

프리리스트에서 프리청크를 검색후 할당받기까지 모든단계에서 shared pool 래치를 할당 받아야 한다.
청크의 할당 해제가 빈번히 발생 한다면 청크는 더욱 작게 쪼개져 관리되어야 할 청크의 수가 증가 한다.
프리리스트를 검색하는 시간을 증가시키고 쉐어드풀 레치에 대한 경합을 증가시켜 성능저하를 유발 하며
4031에러를 발생시킨다.
==================================================================================================================

05 바인드 변수의 중요성

바인드 변수 사용에 따른 효과는 아주 분명
커서를 많이 생성하지 않고 하나를 반복 재사용하므로 메모리 사용량과 파싱 소요 시간을 불인다
궁극적으로 시스템전반의 메모리와 CPU사용률을 낮춰 데이터베이스 성능과 확장성을 높이는데 기여
특히 동시 사용자 접속이 많을 때는 그 영향력이 절대적이다

#################################
바인드 변수 사용의 필요성 테스트
#################################

SQL> create table t as select * from dba_objects;

테이블이 생성되었습니다.

SQL> update t set object_id = rownum;

72471 행이 갱신되었습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL> create unique index t_idx on t (object_id);

인덱스가 생성되었습니다.

SQL> analyze table t compute statistics;

테이블이 분석되었습니다.



set timing on 
declare 
  type rc is ref cursor; 
  l_rc rc;
  l_object_name t.object_name%type;
begin 
  for i in 1..20000
  loop
   open l_rc for
    'select /* TEST1 */ object_name
     from t
     where object_id = :x' using i;
   fetch l_rc into l_object_name;
   close l_rc;
  end loop;
end;
/
SQL> set timing on
SQL> declare
  2    type rc is ref cursor;
  3    l_rc rc;
  4    l_object_name t.object_name%type;
  5  begin
  6    for i in 1..20000
  7    loop
  8     open l_rc for
  9      'select /* TEST1 */ object_name
 10       from t
 11       where object_id = :x' using i;
 12     fetch l_rc into l_object_name;
 13     close l_rc;
 14    end loop;
 15  end;
 16  /

PL/SQL 처리가 정상적으로 완료되었습니다.

경   과: 00:00:00.79
SQL>

SQL> col sql_text format a50
SQL> select sql_text,loads,parse_calls,executions,fetches
  2  from v$sql
  3  where sql_text like '%TEST1%'
  4  and sql_text not like '%v$sql%'
  5  and sql_text not like 'declare%';

SQL_TEXT                                                LOADS PARSE_CALLS EXECUTIONS    FETCHES
-------------------------------------------------- ---------- ----------- ---------- ----------
select /* TEST1 */ object_name      from t      wh          1       20000      20000      20000
ere object_id = :x


경   과: 00:00:00.03


declare 
  type rc is ref cursor; 
  l_rc rc;
  l_object_name t.object_name%type;
begin 
  for i in 1..20000
  loop
   open l_rc for
    'select /* TEST2 */ object_name
     from t
     where object_id = '||i ;
   fetch l_rc into l_object_name;
   close l_rc;
  end loop;
end;
/

SQL> declare
  2    type rc is ref cursor;
  3    l_rc rc;
  4    l_object_name t.object_name%type;
  5  begin
  6    for i in 1..20000
  7    loop
  8     open l_rc for
  9      'select /* TEST2 */ object_name
 10       from t
 11       where object_id = '||i ;
 12     fetch l_rc into l_object_name;
 13     close l_rc;
 14    end loop;
 15  end;
 16  /

PL/SQL 처리가 정상적으로 완료되었습니다.

경   과: 00:00:07.54
SQL>


select sql_text,loads,parse_calls,executions,fetches
from v$sql
where sql_text like '%TEST2%'
and sql_text not like '%v$sql%'
and sql_text not like 'declare%';


select /* TEST2 */ object_name      from t      wh          1           1          1          1
ere object_id = 19110

select /* TEST2 */ object_name      from t      wh          1           1          1          1
ere object_id = 18922

select /* TEST2 */ object_name      from t      wh          1           1          1          1
ere object_id = 18476

select /* TEST2 */ object_name      from t      wh          1           1          1          1
ere object_id = 19948

select /* TEST2 */ object_name      from t      wh          1           1          1          1
ere object_id = 19051


2091 개의 행이 선택되었습니다.

경   과: 00:00:01.25

바인드 변수 사용원칙을 잘 지커지 않으면 라이브러리캐시 경합때문에 시스템 정상가동이
어려운 상황에 직면할 수 있다. cursor_sharing 파라미터를 변경 긴급처방

06 바인드 변수의 부작용과 해법

바인드 변수를 사용하면 최초 수행할 때 최적화를 거친 실행계획을 캐시에 적재하고,
실행시점에는 그것을 그대로 가져와 값을 다르게 바인딩하면서 반복 재사용하게 된다.
여기서, 변수를 바인딩하는 시점이 (최적화 시점보다 나중인) 실행시점이라는 사실을 아
는 것이 중요하다. 즉, SQL을 최적화하는 시점에 조건절 컬럼의 데이터 분포도를 활용하
지 못하는 문제점을 갖는다.

(1) 바인드 변수 Peeking

오라클은 9i부터 바인드 변수 Peeking 기능을 도입
SQL이 첫 번째 수행되면서 하드파싱될 때 함께 딸려 온 바인드 변수 값을 살짝 훔쳐 보고
그 값에 대한 컬럼 분포를 이용해 실행계획을 결정
문제점
잘못 수립된 실행계획 때문에 느린 애플리케이션도 문제지만 시스템 운영자 입장에서는
자주 실행계획이 바뀌어 어제와 오늘의 수행속도가 급격히 달라지는 현상

(2) 적응적 커서 공유(Adaptive Cursor Sharing)

오라클 11g도입된 이 기능이 작동하려면 기본적으로 조건절 컬럼에 히스토그램이 생성돼 있어야 한다.
그 상태에서,옵티마이저가 바인드 변수 값에 따라 실행계획을 달리 가져갈 필요가 있다고 판단면
SQL커서에 대해서 이 기능이 활성화
문제점
새로운 실행계획을 만들지 않는다
기존 커서의 실행계획을 그대로 사용해보고 성능이 나쁘다고 판단되면 모드를 전환

(3) 입력 값에 따라 SQL 분리

인텍스 액세스 경로(access Path)로서 중요하고 조건절 컬럼의 데이터 분포가 균일하지 않
은 상황에서 바인드 변수 시용에 따른 부작용을 피하려면 바인딩 되는 값에 따라 실행계
획을 아래와 같이 분리하는 방안을 고려해야 한다.

select /*+ full(a) */ *
from 아파트매물 a
where :city in ('서울','경기')
and 도시 = :city
union all
select /*+ index(a) */ *
from 아파트매물 a
where :city not in ('서울','경기')
and 도시 = :city;

문제점
union all을 이용해 SQL을 길게 작성하면 Parse 단계의 CPU 사용률을 높임.
-라이브러리 캐시는 문장을 저장함
-Syntax를 체크함
-파싱트리를 만들어 Semantic 체크도함
union all을 이용해 SQL을 길게 작성하면 Execute단계에서도 CPU 사용률을 높임.
-I/O를 일으키지 않을 뿐 실제실행은 일어나기 때문

(4) 예외적으로,Literal 상수값 사용

게다가 배치 프로그램이나 정보계 시스템에서 수행되는 SQL은 대부분 Long
Running 쿼리이므로 파싱 소요시간이 쿼리 총 소요시간에서 차지하는 비중에 매우 낮
고, 사용빈도도낮아하드파싱에 의한라이브러리 캐시 부하를크게 염려할펼요가없다.

07 세션 커서 캐싱

세션 커서 (session cursor)란
Shared Pool에 위치한 공유 커서 (shared cursor)를 실행하려고 PGA로 인스턴스화한 것

쿼리를 수행한 후에 커서를 닫으면,
세션 커서를 위해 할당된 메모리는 물론 공유 커서를 가리키는 포인터까지바로 해제,
그 다음에 같은 SQL을 수행하면 커서를 오픈하기 위한 라이브러리 캐시 탐색작업을 다시 해야 함.

세션 커서 캐싱(Session Cursor Cache)란
오라클은 자주 수행하는 SQL에 대한 세션 커서를 세션 커서 캐시 (Session cursor Cache)에 저장

커서를 닫는 순간 해당 커서의 Parse Call 횟수를 확인해 보고 그 값이 3보다 크거나 같으면,
세션 커서를 세션 커서 캐시로 옮긴다. 세션 커서 캐시에는 SQL 텍스트와 함께 공유 커서를
가리키는 포인터를 저장
커서는 닫힌 상태지만 공유 커서에 대한 참조를 유지하기 때문에 다음 수행 시 더 빨리
커서를 오픈(자주 수행되는 SQL문에 의해 발생하는 라이브러리 캐시 부히를 경감)

즉,
SQL문을 파싱해서 구문을 분석하고,
라이브러리 캐시에서 커서를 찾는 과정에서 소모되는 CPU 사용량을 줄일 수 있음은 물론,
소프트 파싱 과정에 발생하는 래치 요청 횟수를 감소시키는 효과

세션 커서 캐시 내에서도 LRU 알고리즘을 시용함으로써 새로운 엔트리를 위한 공간이 필요할 때마다
기존 세션 커서 중 사용 빈도가 낮은것부터 밀어낸다.

session_cached_cursors는 얼마나 많은 세션 커서를 캐싱할지를 지정하는 파라미터
로서 , 이 값을 O보다 크게 설정하면 Parse Call이 발생할 때마다 라이브러리 캐시를 탐색
하기 전에 세션 커서 캐시를 먼저 살펴본다.

  • users_opening: 공유 커서를 참조하고 있는 세션 커서의 수를 보여준다. 수행을 마
    쳐 커서 를 닫았더라도 참조를 버리지 않은 채 세션 커서 캐시로 옮겨진다면 여기에
    집계된다 .
  • users_executing : 해당 SQL을 현재 실행 중인, 즉 커서가 열려있는 세션 커서의
    수를 보여준다. DML일 때는 수행을 마칠 때 커서가 자동으로 닫히지만 select문은
    EOF(End of Fetch)에 도달했을 때 커서가 닫힌다
SQL> alter session set session_cached_cursors = 10;

세션이 변경되었습니다.

SQL> alter system flush shared_pool;

시스템이 변경되었습니다.

SQL> select * from scott.emp where empno=7788 ;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
---------- ---------- --------- ---------- -------- ---------- ----------
    DEPTNO
----------
      7788 SCOTT      ANALYST         7566 87/04/19       3000
        20


SQL> select parse_calls, users_opening, users_executing from v$sql
  2  where sql_text = 'select * from scott.emp where empno=7788 ';

PARSE_CALLS USERS_OPENING USERS_EXECUTING
----------- ------------- ---------------
          1             0               0

SQL> select * from scott.emp where empno=7788 ;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
---------- ---------- --------- ---------- -------- ---------- ----------
    DEPTNO
----------
      7788 SCOTT      ANALYST         7566 87/04/19       3000
        20


SQL> select parse_calls, users_opening, users_executing from v$sql
  2  where sql_text = 'select * from scott.emp where empno=7788 ';

PARSE_CALLS USERS_OPENING USERS_EXECUTING
----------- ------------- ---------------
          2             0               0

SQL> select * from scott.emp where empno=7788 ;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
---------- ---------- --------- ---------- -------- ---------- ----------
    DEPTNO
----------
      7788 SCOTT      ANALYST         7566 87/04/19       3000
        20


SQL> select parse_calls, users_opening, users_executing from v$sql
  2  where sql_text = 'select * from scott.emp where empno=7788 ';

PARSE_CALLS USERS_OPENING USERS_EXECUTING
----------- ------------- ---------------
          3             1               0

세번 일어나는 순간 users_opening값이 0에서 1로 바뀐 것 확인
세번째 수행되기 전까지는 users_opening값이 0인것
커서를 닫자마자 공유커서에 대한 참조까지 곧바로 해제

users_opening에서 'open' 의 의미가 실제 커서가 열려 있음을 의미하는 것이 아님을
기억할 필요가 있다. 커서는 닫힌 상태지만 공유 커서에 대한 참조를 유지하기 때문에 다
음수행 시 더 빨리 커서를오픈할수있는것이다.

create table t(x number);

select a.name, b.value  
from   v$statname a, v$mystat b 
where  a.name in ('session cursor cache hits','parse count (total)')
and    b.statistic# = a.statistic#; 


alter session set session_cached_cursors=0;

declare 
   i number; 
 begin 
   for i in 1..10000 
    loop 
    execute immediate 'insert into t values('||mod(i,100)||')'; 
    end loop; 
 
 commit; 
end; 
/  


select a.name, b.value  
from   v$statname a, v$mystat b 
where  a.name in ('session cursor cache hits','parse count (total)')
and    b.statistic# = a.statistic#; 

alter session set session_cached_cursors=100;

declare 
   i number; 
 begin 
   for i in 1..10000 
    loop 
    execute immediate 'insert into t values('||mod(i,100)||')'; 
    end loop; 
 
 commit; 
end; 
/  


select a.name, b.value  
from   v$statname a, v$mystat b 
where  a.name in ('session cursor cache hits','parse count (total)')
and    b.statistic# = a.statistic#; 

출처: http://wiki.gurubee.net/pages/viewpage.action?pageId=28115145


반응형
Posted by [PineTree]
ORACLE/TroubleShooting2014. 3. 23. 22:21
반응형


SHARED POOL에 대한 점검 사항들

제품 : ORACLE SERVER




SHARED POOL에 대한 점검 사항들
======================


PURPOSE
-------
다음은 shared pool에 관련된 performance 에 대한 점검 사항들이다.


Explanation
-----------

1. literal SQL Statements

SELECT      substr(sql_text,1,40) "SQL", count(*) ,
sum(executions) "TotExecs"
FROM      v$sqlarea
WHERE      executions < 5
     GROUP BY substr(sql_text,1,40)
     HAVING count(*) > 30
ORDER BY 2
/

shared SQL문들 중에서 literal SQL문들을 찾아내어 bind variable을
사용할 수 있는 경우 bind variable로 전환하도록 한다.
ORACLE cost based optimizer는 bind variable 보다 literal value를
사용하는 SQL에 대하여 보다 최적화된 execution plan을 결정하게 된다.
하지만 과도한 literal SQL문들을 사용하게 되면 hard parsing 이
빈번하게 되고 library cache와 dictionary cache의 사용율을 높이게 된다.


2. Library cahe hit ratio

SELECT to_char(trunc(sum(reloads)/sum(pins)*100, 5),99.99999)||
'%(less than 1%)' "Library Cache MISS RATIO"
FROM v$librarycache
/

만일 miss ratio가 1%보다 큰 경우 library cache miss를 줄이는 노력이
필요하다. 예를 들어 적절한 크기의 shared pool을 사용하거나 dynamic SQL
(literal SQL) 사용을 줄이도록 한다.


3. Checking hash chain lengths
SELECT hash_value, count(*)
FROM v$sqlarea
GROUP BY hash_value
HAVING count(*) > 5
/

위 query에 대한 결과가 없어야 한다. 만일 동일한 HASH_VALUE를 갖는
sql 수가 많다면 다음의 query를 이용하여 이 hach chain에 의하여 관리되는
sql 들을 확인하여 본다.
대부분 literal sql문들에 의하여 이런 문제가 발생하는 경우가 많다.

SELECT sql_text FROM v$sqlarea WHERE hash_value= <XXX>;


4. Checking for high version counts

     SELECT      address, hash_value,
     version_count ,
users_opening ,
users_executing
sql_text
FROM v$sqlarea
WHERE version_count > 10
     /

SQL의 version은 문장 상으로 완벽히 일치하지만 참조 object가 틀리는
SQL문들을 의미한다. 만일 이해할 수 없을 정도의 version count를 갖는
row가 있다면 한국 오라클 기술지원팀으로 문의하도록 한다.


5. Finding statement/s which use lots of shared pool memory

SELECT      substr(sql_text,1,40) "Stmt", count(*),
sum(sharable_mem) "Mem",
sum(users_opening) "Open",
sum(executions) "Exec"
FROM v$sql
GROUP BY substr(sql_text,1,40)
HAVING sum(sharable_mem) > <MEMSIZE>
/


6. Allocations causing shared pool memory to be 'aged' out

SELECT      *
FROM      sys.x$ksmlru
WHERE      ksmlrnum>0
/

x$ksmlru는 shared pool의 object에 대한 list로 object 할당 시 age out된
object 수에 정보를 담고 있어 age out으로 인한 응답율 저하나 latch
병합들의 원인을 추적하는 데 유용하다.
이 table은 8i부터 sys user로만 조회가 가능하며 한번 조회되면 reset된다.

(x$ksmlru.ksmlrnum : Number of items flushed from the shared pool)


Example
-------


Reference Documents
-------------------

반응형
Posted by [PineTree]
ORACLE/RAC2014. 3. 12. 17:08
반응형

출처 : http://www.commit.co.kr/101

 

Single_to_RAC(Converting).pdf

 

반응형
Posted by [PineTree]
ORACLE/RAC2014. 2. 22. 12:10
반응형

Steps to Remove Node from Cluster When the Node Crashes Due to OS/Hardware Failure and cannot boot up (Doc ID 466975.1) To BottomTo Bottom

Modified:16-Nov-2012Type:HOWTO

Rate this document Email link to this document Open document in new window Printable Page


In this Document

Goal

Fix

  Summary

  Example Configuration

  Initial Stage

  Step 1 Remove oifcfg information for the failed node

  Step 2 Remove ONS information

  Step 3 Remove resources

  Step 4 Execute rootdeletenode.sh

  Step 5 Update the Inventory

References

APPLIES TO:


Oracle Server - Enterprise Edition - Version 10.2.0.1 to 11.1.0.6 [Release 10.2 to 11.1]

Oracle Server - Standard Edition - Version 10.2.0.1 to 11.1.0.6 [Release 10.2 to 11.1]

Information in this document applies to any platform.

Oracle Server Enterprise Edition - Version: 10.2.0.1 to 11.1.0.6

Oracle Clusterware



GOAL


This document is intented to provide the steps to be taken to remove a node from the Oracle cluster. The node itself is unavailable due to some OS issue or hardware issue which prevents the node from starting up. This document will provide the steps to remove such a node so that it can be added back after the node is fixed.


The steps to remove a node from a Cluster is already documented in the Oracle documentation at


Version Documentation Link

10gR2 http://download.oracle.com/docs/cd/B19306_01/rac.102/b14197/adddelunix.htm#BEIFDCAF

11gR1 http://download.oracle.com/docs/cd/B28359_01/rac.111/b28255/adddelclusterware.htm#BEIFDCAF

This note is different because the documentation covers the scenario where the node is accessible and the removal is a planned procedure. This note covers the scenario where the Node is unable to boot up and therefore it is not possible to run the clusterware commands from this node.


For 11gR2, refer to note 1262925.1


 


FIX


Summary


Basically all the steps documented in the Oracle Clusterware Administration and Deployment Guide must be followed. The difference here is that we skip the steps that are to be executed on the node which is not available and we run some extra commands on the other node which is going to remain in the cluster to remove the resources from the node that is to be removed.


Example Configuration


 All steps outlined in this document were executed on a cluster with the following configuration:


Item Value

Node Names lc2n1, lc2n2, lc2n3

Operating System Oracle Enterprise Linux 5 Update 4

Oracle Clusterware Release 10.2.0.5.0

ASM & Database Release 10.2.0.5.0

Clusterware Home /u01/app/oracle/product/10.2.0/crs ($CRS_HOME)

ASM Home /u01/app/oracle/product/10.2.0/asm

Database Home /u01/app/oracle/product/10.2.0/db_1

 Cluster Name lc2

 


 Assume that node lc2n3 is down due to a hardware failure and cannot even boot up. The plan is to remove it from the clusterware, fix the issue and then add it again to the Clusterware. In this document, we will cover the steps to remove the node from the clusterware


Please note that for better readability instead of 'crs_stat -t' the sample script 'crsstat' from 

  Doc ID 259301.1 CRS and 10g/11.1 Real Application Clusters 

was used to query the state of the CRS resources. This script is not part of a standard CRS installation.

 


Initial Stage


At this stage, the Oracle Clusterware is up and running on nodes lc2n1 & lc2n2 (good nodes) . Node lc2n3 is down and cannot be accessed. Note that the Virtual IP of lc2n3 is running on Node 1. The rest of the lc2n3 resources are OFFLINE:


[oracle@lc2n1 ~]$ crsstat

Name                                     Target     State      Host      

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

ora.LC2DB1.LC2DB11.inst                  ONLINE     ONLINE     lc2n1     

ora.LC2DB1.LC2DB12.inst                  ONLINE     ONLINE     lc2n2     

ora.LC2DB1.LC2DB13.inst                  ONLINE     OFFLINE              

ora.LC2DB1.LC2DB1_SRV1.LC2DB11.srv       ONLINE     ONLINE     lc2n1     

ora.LC2DB1.LC2DB1_SRV1.LC2DB12.srv       ONLINE     ONLINE     lc2n2     

ora.LC2DB1.LC2DB1_SRV1.LC2DB13.srv       ONLINE     OFFLINE              

ora.LC2DB1.LC2DB1_SRV1.cs                ONLINE     ONLINE     lc2n1     

ora.LC2DB1.db                            ONLINE     ONLINE     lc2n2     

ora.lc2n1.ASM1.asm                       ONLINE     ONLINE     lc2n1     

ora.lc2n1.LISTENER_LC2N1.lsnr            ONLINE     ONLINE     lc2n1     

ora.lc2n1.gsd                            ONLINE     ONLINE     lc2n1     

ora.lc2n1.ons                            ONLINE     ONLINE     lc2n1     

ora.lc2n1.vip                            ONLINE     ONLINE     lc2n1     

ora.lc2n2.ASM2.asm                       ONLINE     ONLINE     lc2n2     

ora.lc2n2.LISTENER_LC2N2.lsnr            ONLINE     ONLINE     lc2n2     

ora.lc2n2.gsd                            ONLINE     ONLINE     lc2n2     

ora.lc2n2.ons                            ONLINE     ONLINE     lc2n2     

ora.lc2n2.vip                            ONLINE     ONLINE     lc2n2     

ora.lc2n3.ASM3.asm                       ONLINE     OFFLINE              

ora.lc2n3.LISTENER_LC2N3.lsnr            ONLINE     OFFLINE              

ora.lc2n3.gsd                            ONLINE     OFFLINE              

ora.lc2n3.ons                            ONLINE     OFFLINE              

ora.lc2n3.vip                            ONLINE     ONLINE     lc2n1     

[oracle@lc2n1 ~]$

 


Step 1 Remove oifcfg information for the failed node


Generally most installations use the global flag of the oifcfg command and therefore they can skip this step. They can confirm this using:


[oracle@lc2n1 bin]$ $CRS_HOME/bin/oifcfg getif

eth0  192.168.56.0  global  public

eth1  192.168.57.0  global  cluster_interconnect

If the output of the command returns global as shown above then you can skip the following step (executing the command below on a global defination will return an error as shown below.


If the output of the oifcfg getif command does not return global then use the following command


[oracle@lc2n1 bin]$ $CRS_HOME/bin/oifcfg delif -node lc2n3 

PROC-4: The cluster registry key to be operated on does not exist.

PRIF-11: cluster registry error

 


Step 2 Remove ONS information


Execute the following command to find out the remote port number to be used


[oracle@lc2n1 bin]$ cat $CRS_HOME/opmn/conf/ons.config

localport=6113 

remoteport=6200 

loglevel=3

useocr=on

and remove the information pertaining to the node to be deleted using:


[oracle@lc2n1 bin]$ $CRS_HOME/bin/racgons remove_config lc2n3:6200

 


Step 3 Remove resources


In this step, the resources that were defined on this node have to be removed. These resources include Database Instances, ASm, Listener and Nodeapps resources. A list of these can be acquired by running crsstat (crs_stat -t) command from any node


[oracle@lc2n1 ~]$ crsstat |grep OFFLINE

ora.LC2DB1.LC2DB13.inst                  ONLINE     OFFLINE              

ora.LC2DB1.LC2DB1_SRV1.LC2DB13.srv       ONLINE     OFFLINE              

ora.lc2n3.ASM3.asm                       ONLINE     OFFLINE              

ora.lc2n3.LISTENER_LC2N3.lsnr            ONLINE     OFFLINE              

ora.lc2n3.gsd                            ONLINE     OFFLINE              

ora.lc2n3.ons                            ONLINE     OFFLINE             

 Before removing any resource it is recommended to take a backup of the OCR:


[root@lc2n1 ~]# cd $CRS_HOME/cdata/lc2

[root@lc2n1 lc2]# $CRS_HOME/bin/ocrconfig -export ocr_before_node_removal.exp

[root@lc2n1 lc2]# ls -l ocr_before_node_removal.exp

-rw-r--r-- 1 root root 151946 Nov 15 15:24 ocr_before_node_removal.exp

 Use 'srvctl' from the database home to delete the database instance on node 3:


[oracle@lc2n1 ~]$ . oraenv

ORACLE_SID = [oracle] ? LC2DB1

[oracle@lc2n1 ~]$ $ORACLE_HOME/bin/srvctl remove instance -d LC2DB1 -i LC2DB13

Remove instance LC2DB13 from the database LC2DB1? (y/[n]) y

 Use 'srvctl' from the ASM home to delete the ASM instance on node 3:


[oracle@lc2n1 ~]$ . oraenv

ORACLE_SID = [oracle] ? +ASM1

[oracle@lc2n1 ~]$ $ORACLE_HOME/bin/srvctl remove asm -n lc2n3

Next remove the listener resource.


Please note that there is no 'srvctl remove listener' subcommand prior to 11.1 so this command will not work in 10.2. Using 'netca' to delete the listener from a down node also is not an option as netca needs to remove the listener configuration from the listener.ora.

10.2 only:


The only way to remove the listener resources is to use the command 'crs_unregister', please use this command only in this particular scenario:


[oracle@lc2n1 lc2]$ $CRS_HOME/bin/crs_unregister ora.lc2n3.LISTENER_LC2N3.lsnr

 11.1 only:


 Set the environment to the home from which the listener runs (ASM or database):


[oracle@lc2n1 ~]$ . oraenv

ORACLE_SID = [oracle] ? +ASM1

[oracle@lc2n1 lc2]$ $ORACLE_HOME/bin/srvctl remove listener -n lc2n3 

  As user root stop the nodeapps resources:


[root@lc2n1 oracle]# $CRS_HOME/bin/srvctl stop nodeapps -n lc2n3

[root@lc2n1 oracle]# crsstat |grep OFFLINE

ora.lc2n3.LISTENER_LC2N3.lsnr            OFFLINE    OFFLINE              

ora.lc2n3.gsd                            OFFLINE    OFFLINE              

ora.lc2n3.ons                            OFFLINE    OFFLINE              

ora.lc2n3.vip                            OFFLINE    OFFLINE        

 Now remove them:


[root@lc2n1 oracle]#  $CRS_HOME/bin/srvctl remove nodeapps -n lc2n3

Please confirm that you intend to remove the node-level applications on node lc2n3 (y/[n]) y

 At this point all resources from the bad node should be gone:


[oracle@lc2n1 ~]$ crsstat 

Name                                     Target     State      Host      

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

ora.LC2DB1.LC2DB11.inst                  ONLINE     ONLINE     lc2n1     

ora.LC2DB1.LC2DB12.inst                  ONLINE     ONLINE     lc2n2     

ora.LC2DB1.LC2DB1_SRV1.LC2DB11.srv       ONLINE     ONLINE     lc2n1     

ora.LC2DB1.LC2DB1_SRV1.LC2DB12.srv       ONLINE     ONLINE     lc2n2     

ora.LC2DB1.LC2DB1_SRV1.cs                ONLINE     ONLINE     lc2n1     

ora.LC2DB1.db                            ONLINE     ONLINE     lc2n2     

ora.lc2n1.ASM1.asm                       ONLINE     ONLINE     lc2n1     

ora.lc2n1.LISTENER_LC2N1.lsnr            ONLINE     ONLINE     lc2n1     

ora.lc2n1.gsd                            ONLINE     ONLINE     lc2n1     

ora.lc2n1.ons                            ONLINE     ONLINE     lc2n1     

ora.lc2n1.vip                            ONLINE     ONLINE     lc2n1     

ora.lc2n2.ASM2.asm                       ONLINE     ONLINE     lc2n2     

ora.lc2n2.LISTENER_LC2N2.lsnr            ONLINE     ONLINE     lc2n2     

ora.lc2n2.gsd                            ONLINE     ONLINE     lc2n2     

ora.lc2n2.ons                            ONLINE     ONLINE     lc2n2     

ora.lc2n2.vip                            ONLINE     ONLINE     lc2n2  

 


Step 4 Execute rootdeletenode.sh


From the node that you are not deleting execute as root the following command which will help find out the node number of the node that you want to delete


[oracle@lc2n1 ~]$ $CRS_HOME//bin/olsnodes -n

lc2n1   1

lc2n2   2

lc2n3   3

this number can be passed to the rootdeletenode.sh command which is to be executed as root from any node which is going to remain in the cluster.


[root@lc2n1 ~]# cd $CRS_HOME/install

[root@lc2n1 install]# ./rootdeletenode.sh lc2n3,3

CRS-0210: Could not find resource 'ora.lc2n3.ons'.

CRS-0210: Could not find resource 'ora.lc2n3.vip'.

CRS-0210: Could not find resource 'ora.lc2n3.gsd'.

CRS-0210: Could not find resource ora.lc2n3.vip.

CRS nodeapps are deleted successfully

clscfg: EXISTING configuration version 3 detected.

clscfg: version 3 is 10G Release 2.

Successfully deleted 14 values from OCR.

Key SYSTEM.css.interfaces.nodelc2n3 marked for deletion is not there. Ignoring.

Successfully deleted 5 keys from OCR.

Node deletion operation successful.

'lc2n3,3' deleted successfully

[root@lc2n1 install]# $CRS_HOME/bin/olsnodes -n

lc2n1   1

lc2n2   2

 


Step 5 Update the Inventory


From the node which is going to remain in the cluster run the following command as owner of the CRS_HOME. The argument to be passed to the CLUSTER_NODES is a comma seperated list of node names of the cluster which are going to remain in the cluster. This step needs to be performed from once per home (Clusterware, ASM and RDBMS homes).


[oracle@lc2n1 install]$ $CRS_HOME/oui/bin/runInstaller -updateNodeList ORACLE_HOME=/u01/app/oracle/product/10.2.0/crs "CLUSTER_NODES={lc2n1,lc2n2}" CRS=TRUE  

Starting Oracle Universal Installer...


No pre-requisite checks found in oraparam.ini, no system pre-requisite checks will be executed.

The inventory pointer is located at /etc/oraInst.loc

The inventory is located at /u01/app/oracle/oraInventory

'UpdateNodeList' was successful.


[oracle@lc2n1 install]$ $CRS_HOME/oui/bin/runInstaller -updateNodeList ORACLE_HOME=/u01/app/oracle/product/10.2.0/asm "CLUSTER_NODES={lc2n1,lc2n2}"

Starting Oracle Universal Installer...


No pre-requisite checks found in oraparam.ini, no system pre-requisite checks will be executed.

The inventory pointer is located at /etc/oraInst.loc

The inventory is located at /u01/app/oracle/oraInventory

'UpdateNodeList' was successful.

[oracle@lc2n1 install]$ $CRS_HOME/oui/bin/runInstaller -updateNodeList ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1 "CLUSTER_NODES={lc2n1,lc2n2}"

Starting Oracle Universal Installer...


No pre-requisite checks found in oraparam.ini, no system pre-requisite checks will be executed.

The inventory pointer is located at /etc/oraInst.loc

The inventory is located at /u01/app/oracle/oraInventory

'UpdateNodeList' was successful.

반응형
Posted by [PineTree]
ORACLE/INSTALL2013. 10. 29. 16:02
반응형

 

11g NEWFEATURE.(upgrade).pdf

 

4-oracle-db-11g-best-practice-forum.pdf

 

반응형
Posted by [PineTree]
ORACLE/11G2013. 8. 20. 13:47
반응형

11g에 추가된 파티션 유형


Reference 파티셔닝

  • 상품 테이블을 상품대분류 기준으로 리스트 파티셔닝하고, 일별상품거래 테이블도 부모 테이블인 상품과 똑 같은 방식과 기준으로 파티셔닝
  • 이럴 때 10g 까지는 상품에 있는 상품대분류 컬럼을 일별 상품거래 테이블에 반정규화
  • 11g에서 부모 테이블 파티션 키를 이용해 자식 테이블을 파티셔닝하는 기능

Create table 상품 {
상품번호 number NOT NULL PRIMARY KEY
, 상품명 varchar2(50) not null
, 현재가격 number not null
, 상품대분류 varchar2(4) not null
, 등록일시 date not null
)
Partition by list(상품대분류) (
 Partition p1 values ('의류')
,partition p2 values ('식품')
,partition p3 values ('가전')
,partition 4 values ('컴퓨터')
);

create table 일별상품거래 (
  상품번호   number  NOT NULL, 거래일자   varchar2(8)
, 판매가격   number
, 판매수량   number
, 판매금액   number
, constraint 일별상품거래_fk foreign key(상품번호) references 상품
)
partition by reference (일별상품거래_fk);


Interval 파티셔닝

  • 11g 부터는 Range 파티션을 생성할 대 아래와 같이 interval, 기준을 정의함으로써 정해진 간격으로 파티션이 자동 추가되도록 할 수 있다.
  • 테이블을 일단위로 파티셔닝 했을때 유용하다.


create table 주문일자 (주문번호 number, 주문일시 date, ... )
partition by range(주문일시) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH')) 
(
, partition p200907 values less than(to_date('2009/08/01', 'yyyy/mm/dd'))
, partition p200908 values less than(to_date('2009/09/01', 'yyyy/mm/dd'))
, partition p200909 values less than(to_date('2009/10/01', 'yyyy/mm/dd'))
, partition p200910 values less than(to_date('2009/11/01', 'yyyy/mm/dd'))
);

 

create table 고객 (고객번호 number, 고객명 varchar2(20), ... )
partition by range(고객번호) INTERVAL (100000)
( partition p_cust1 values less than ( 100001 )
, partition p_cust2 values less than ( 200001 )
, partition p_cust3 values less than ( 300001 )
) ;

반응형
Posted by [PineTree]
ORACLE/ADMIN2013. 8. 6. 10:45
반응형
(로그 위치를 변경하지 않았다면)
$ORACLE_HOME/network/log 디렉토리에 보면, 
listener.log 가 꾸준히 또는 급격하게 사이즈가 증가할 경우가 있다.  

이럴 경우, 

lsnrctl  ->

lsnrctl> set current_listener <리스너명> --구성된 리스너명이 Listener 가 아닌 경우, 지정해 줌.

lsnrctl> set log_status off -- listener.log 파일에 로그를 기록하지 않는다.  

lsnrctl> set log_status on -- listener.log 파일에 로그를 기록.

set log_status off 로 변경하고, 파일 제거 또는 백업하고 listener.log 파일 생성 (생성하지 않아도 자동 생성) 
출처 - http://jmkjb.tistory.com/entry/ListenerlogManage
 
명령어는 lnsrctl start /stop/ status 사용
서비스이름 확인후 tnsping service_name //host ip주소확인 상태확인
반응형
Posted by [PineTree]
ORACLE/ADMIN2013. 7. 25. 07:33
반응형

오라클

srvctl stop home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac1


root로
cd /app/11g/grid/crs/install
./rootcrs.pl -unlock

oracle로

/app/11g/grid/OPatch/opatch napply -oh /app/11g/grid/ -local /home/oracle/16459322/

/app/11g/grid/OPatch/opatch apply -oh /app/11g/grid/ -local /home/oracle/16056267

/home/oracle/16459322/custom/server/16459322/custom/scripts/prepatch.sh -dbhome /app/oracle/11g/db

DB패치 oracle로
opatch napply -oh /app/oracle/11g/db -local /home/oracle/16459322/custom/server/16459322

opatch apply -oh /app/oracle/11g/db -local /home/oracle/16056267

/home/oracle/16459322/custom/server/16459322/custom/scripts/postpatch.sh -dbhome /app/oracle/11g/db

root로

cd /app/11g/grid/rdbms/install/

./rootadd_rdbms.sh

cd /app/11g/grid/crs/install

./rootcrs.pl -patch

oracle로

srvctl start home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac1

###########################################################################################################################

###########################################################################################################################

2번 노드에서

 

oracle유저로
srvctl stop home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac2


root로
cd /app/11g/grid/crs/install
./rootcrs.pl -unlock

oracle로

/app/11g/grid/OPatch/opatch napply -oh /app/11g/grid/ -local /home/oracle/16459322/

/app/11g/grid/OPatch/opatch apply -oh /app/11g/grid/ -local /home/oracle/16056267

/home/oracle/16459322/custom/server/16459322/custom/scripts/prepatch.sh -dbhome /app/oracle/11g/db

DB패치 oracle로
opatch napply -oh /app/oracle/11g/db -local /home/oracle/16459322/custom/server/16459322

opatch apply -oh /app/oracle/11g/db -local /home/oracle/16056267

/home/oracle/16459322/custom/server/16459322/custom/scripts/postpatch.sh -dbhome /app/oracle/11g/db

root로

cd /app/11g/grid/rdbms/install/

./rootadd_rdbms.sh

cd /app/11g/grid/crs/install

./rootcrs.pl -patch

oracle로

srvctl start home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac2

반응형

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

04 커서공유  (0) 2014.03.23
[ORACLE]Listener.log 관리  (0) 2013.08.06
shrink 대상 선정 및 shrink작업  (1) 2013.06.03
(10gR2)Full UNDO tablespace_언두 메커니즘  (0) 2013.05.19
10g SYSAUX tablespace 크기 줄이기  (0) 2013.03.04
Posted by [PineTree]
ORACLE2013. 6. 25. 11:13
반응형

오라클 평생 제품지원 정책

조회수 : 4245 | 2006/01/17

모든 오라클 소프트웨어 제품군에 대해서 보장하는 가장 혁신적인 기술지원 정책

 

오라클 평생 제품지원 정책

 

노동현│한국오라클 기술서비스본부

 

2005년 9월 샌프란시스코에서 개최된 오라클 오픈 월드 행사에서는 새로운 오라클 제품지원 정책인‘평생 제품지원 정책(Lifetime Support Policy)’이 발표되었다. 이 정책은 그 이전까지 제공하던 제품지원 정책에 비해서 혁신적으로 발전된 내용을 담고 있어 동종업체와 고객사의 많은 관심을 끌고 있다.

 

오라클 평생 제품지원 정책의 개요

 

오라클의 평생 제품지원 정책(Lifetime Support Policy)은 데이터베이스, 미들웨어부터 애플리케이션에 이르기까지의 모든 오라클 제품군에 대해서 해당 제품을 사용하는 전 기간 동안 전문가의 기술지원과 제품 버전 업그레이드를 제공함으로써 오라클 사용자의 소중한 투자자산을 보호하고 월등한 혜택을 제공하는 새로운 제품지원 정책이다. 이는 업계 최초의 시도이며, 오직 오라클에서만 가능한 서비스 정책이다.

 

오라클의 평생 제품지원 정책은 기술지원 서비스 제공 시 매우 융통성 있는 방안을 제시함으로써 사용중인 제품의 업그레이드 계획과 예산 확보를 쉽게 수행할 수 있도록 해주는 장점이 있다. 사용자가 현재 어떠한 제품 버전을 사용하고 있든 유효한 기술 지원 계약만 맺고 있다면, 원하는 시기에 최신 버전으로의 업그레이드와 전문가의 조언을 받을 수 있으므로 업그레이드에 관련된 문제를 염려하지 않아도 된다.

 

이렇게 오라클 라이선스가 종료되는 시점까지 계속 제공되는 기술지원 서비스를 통해서 사용자는 시스템의 기술 수준과 비즈니스 운영을 조화롭게 발전시켜 나갈 수 있다. 또한 사용자의 시스템을 항상 사용 가능하고 안전한 상태로 유지할 수 있다.

 

오라클은 평생 제품지원 정책을 통해 다음 3가지 단계의 제품 지원 서비스를 제공한다<그림 1>.

 

Premier Support : 제품 출시 후 5년간 제공되는 가장 다양한 제품 지원 서비스
Extended Support : Premier Support 기간 이후 3년간 제공되는 제품지원 서비스
Sustaining Support : 오라클 라이선스가 종료되는 시점까지 제공되는 제품지원 서비스

 

 

Premier Support는 오라클의 테크놀러지 제품군(Oracle Database와 Oracle Fusion Middleware)과 애플리케이션제품군(Oracle E-Business Suite, PeopleSoft Enterprise, JD Edwards EnterpriseOne, 및JD Edwards World)에 대해서 제품 출시 후 5년간 제공된다. Premier Support 기간이 종료되면 제품과 버전에 따라서 3년동안 Extended Support 가제 공된 후에 Sustaining Support 가 제공된다. 하지만 제품과 버전에 따라서는 Premier Support 기간이 종료된 후에 Extended Support 기간없이바로Sustaining Support 만제공될수 도 있다. 단, Extended Support는 기본적인 서포트 요금 외에 추가적인 요금이 부과되며 이는 연차에 따라서 조금 다르다.

 

Premier Support : 소프트웨어 제품지원의 새로운 표준

 

오라클이 제공하는 기술지원 서비스는 여러 가지 장점을 가지고 있다. 전 세계에 구축된 엔지니어 조직, 축적된 지식의 방대한 양, 그리고 이러한 기술지원 자원과 고객을 가장 신속하고 편리하게 연결하는 Oracle MetaLink 시스템을 통해서 세계 최고의 제품에 걸맞는 기술지원 서비스를 제공한다. 특히 최근 인수한 피플소프트의 기술지원 서비스와 오라클의 기술지원 서비스의 결합은 새로운 Premier Support를 탄생시키는계기가되었다. Premier Support는 특히 다음과 같은 장점을 자랑한다.

 

시공을 초월하는 글로벌 지원

오라클의 지원 조직은 전 세계 거의 모든 국가에서 활동하고 있으며, 축적된 지식의 양과 조직의 규모 면에서 타의 추종을 불허한다. 사용자는 미션크리티컬한 문제에 대해서는 글로벌 지원센터를 통해서 24시간 연중무휴로 실시간 지원받을 수 있다. 오라클은 대륙별로 5개국에 걸쳐 17개의 중요 거점 허브를 운영하고 있으며, 이를 통해서 사용자가 어떠한 시간대에 있더라도 지원할 수 있으며, 데이터베이스에서 애플리케이션에 이르는 모든 단계의 제품군에 대해서 최적의 솔루션을 제공한다.


시대를 앞서가는 최신의 고객지원 기술

Premier Support는 엔지니어의 역량에만 의존하는 방식에서 자동화된 방식의 새로운 고객지원을 제공한다. 이러한 최신 기술에 의한 서비스는 사용자가 시스템에 발생한 문제를 가장 빨리 해결하거나 가장 효율적인 상태를 유지하도록 해줌으로써 총소유비용(TCO)을 최소화해 준다.


평생 보장되는 제품 업그레이드 권한

오라클은 Premier Support 기간이 지난 버전의 제품을 운영하는 사용자에게도 새로 출시되는 버전의 릴리즈를 제공한다. 따라서 사용자는 업그레이드 계획을 소프트웨어 공급자의 계획이 아닌 자신의 비즈니스 계획에 맞출 수 있으므로 가장 유리한 비즈니스 전략을 실행할 수 있게 된다.

 

오라클 Premier Support는 모든 오라클 제품에 대해서 제품 출시 후 5년간 다음과 같은 서비스를 제공한다.

 

• 주요 제품과 기술에 대한 신규 릴리즈
• 기술지원
• 메타링크 접속 권한
• 각종 업데이트, 패치 그리고 보안 안내
• 세금, 법률, 그리고 규제 관련 업데이트
• 업그레이드 스크립트
• 새로운 써드파티 제품/버전에 대한 인증

 

Extended Support

 

Extended Support는 Premier Support 서비스에서 제공되는 대부분의 서비스를 Premier Support 기간 이후에 3년 동안 추가로 제공하는 서비스이다. 이 서비스는 사용자에게 최적의 시스템 상태를 최대한 누리다가 가장 적절한 시기에 업그레이드할 수 있도록 하는 유연성을 제공하게 된다.

 

Extended Support는 다음과 같은 서비스를 제공한다.

 

• 주요 제품과 기술에 대한 신규 릴리즈
• 기술지원
• 메타링크 접속 권한
• 각종 업데이트, 패치 그리고 보안 안내
• 세금, 법률, 그리고 규제 관련 업데이트
• 업그레이드 스크립트

 

단, Extended Support는Premier Support에서제공하는 ‘새로 제공하지 않는다.

 

Extended Support의 대상이 되는 제품/버전은 미리 정해지게 되며 연차에 따라 별도의 요금이 부과된다. 또한 Extended Support의대상이되지않는제품/버전에대해서는Premier Support 기간 후에 바로 Sustaining Support 서비스가 제공된다.

 

Sustaining Support

 

오라클의 Sustaining Support는 오라클 라이선스 기간이 종료될 때까지 - 즉 영구사용 라이선스를 가진 경우에는 평생 - 기술지원과 업그레이드 릴리즈 등을 제공하는 서비스이다. 따라서 사용자는 사용중인 제품에 대한 업그레이드 일정을 자유롭게 결정할 수 있어 사용자의 역량을 본연의 비즈니스 전략 실천에 집중할 수 있다. 또한 Sustaining Support는 Premier Support의 요금 외에 별도의 요금이 부과되지 않는다.

 

Sustaining Support는 다음과 같은 서비스를 제공한다.

 

• 주요 제품과 기술에 대한 신규 릴리즈
• 기술지원
• 메타링크 접속 권한
• 이미 만들어진 패치 제공

 

Sustaining Support는 다음과 같은 서비스는 제공하지 않는다.

 

• 새로운 업데이트, 패치 그리고 보안 안내
• 새로운 세금, 법률, 그리고 규제 관련 업데이트
• 새로운 써드파티 제품/버전에 대한 인증
• 다른 오라클 제품과 연동해서 사용하는 것에 대한 인증

 

Sustaining Support는 Premier Support의 요금 외에 별도의 요금이 부과되지 않는다. 하지만 특정 패치에 대해서는 추가 요금이 예외적으로 부과될 수 있다.

 

제품/버전별 평생 지원 일정

 

<표 1>, <표 2>, <표 3>은 한국에서 가장 널리 사용되고 있는 오라클 제품에 대한 평생 지원 일정을 정리한 것이다.

 

참고로, 일부 출시 시기가 오래된 제품은 이미 서포트 종료를 공지했기 때문에 새로운 평생 제품지원 정책을 따르지 않고 Sustaining Support가 종료될 수 있다.

 

그리고, 제품/버전별 평생 제품지원에 대한 더 자세한 정보는 Oracle MetaLink를 참고하거나 오라클 서포트 홈페이지 (http://www.oracle.com/support/library/oracle-lifetime- support-policy-faq.pdf)를 참조하기 바란다.

 

 

평생 제품지원 정책에 대한 FAQ

 

Q> 기존의Oracle Standard Support 계약기간 중에 있다면, 지금 Premier Support 계약을 다시 맺어야 하는가?

그렇지 않다. Premier Support는 현재 보유하고 있는 Standard Support를 대체하며, Software Update License and Support에 대한 내용을 포함한다. 따라서 기존 계약이 끝나기 전에 다시 계약을 맺을 필요는 없다.

 

Q> 기존의 Oracle Extended Maintenance Support와 평생 제품 지원 정책의 Extended Support에서 제공하는 서비스의 차이점은 무엇인가?

기존의 Oracle Extended Maintenance Support는 데이터베이스 제품에 대해서만 제공되던 서비스이다. 이 서비스는 다음과 같은 조건하에 제공되었다.

 

• 추가적인 요금 부과
• Standard Support 종료 후 2년 이내에 구매
• 데이터베이스 버전별로 서로 다른 지원 스케줄

 

이러한 Oracle Extended Maintenance Support는 평생 제품지원 정책 내의 Extended Support로 대체되었으며, 이 는 오라클 데이터베이스뿐만 아니라 미들웨어, 애플리케이션에 이르는 모든 오라클 제품군에 대해서 추가 비용을 내는 조건으로 동일하게 제공된다. 새로운 Extended Support는 일관된 지원 스케줄이 짜여져 있으므로 사용자는 업그레이드에 대해서 더 편안하게 계획을 세울 수 있게 되었다.

 

종전의 Extended Support 는 다음과 같은 조건 하에 제공되던 서비스이다.

 

• 여러 가지 제품에 대해서 상이한 지원 스케쥴
• 제품별 지원중단 예고에 따른 지원 스케쥴 결정
• 제품과 버전별로 서로 다른 지원 스케쥴

 

이러한 Extended Support는 평생 제품지원 정책의 Sustaining Support로 대체되었으며, 이는 모든 오라클 제품에 대해서 제공된다

 

Q> 오라클은 왜 Sustaining Support 기간부터는 소프트웨어 패치를 새로 만들어 주지 않는가?

5년간의 Premier Support 기간이 끝난 뒤에도 소프트웨어 패치가 계속 필요하다면 Extended Support 서비스를 계약하게 될 것이다. 이러한 Extended Support까지 끝난 8년 후에는 새로 문제가 발견되는 경우가 매우 적다. 그러나 반대로 모든 제품군에 대해서 계속 신규 소프트웨어 패치를 제공하기 위한 비용은 매우 커지게 된다. 따라서 오라클은 Sustaining Support 기간부터는 수많은 제품군에 대해서 영구적으로 신규 소프트웨어 패치를 개발, 보급하는 대신 이미 개발된 패치와 기술지원을 제공하고 있다. 따라서 사용자는 Premier Support와 Extended Support 기간 안에 최신 버전으로의 업그레이드를 마치는 것이 가장 바람직할 것이다.

 

기술지원에서도 앞서가는 오라클

 

지금까지 오라클은 항상 혁신적인 제품과 기술을 통해서 정보기술 업계를 선도해왔으며 정보기술 발전에 이바지해왔다. 이제 평생 제품지원 정책을 통해서 모든 오라클 제품 사용자에게 가장 포괄적이고 유연한 기술지원을 제공함으로써 고객의 비즈니스 성공을 도와주면서 기술지원 측면에서 계속 업계를 선도해 나갈 것이다.

 

평생 제품지원 정책에 대한 더욱 상세한 정보 :

• 오라클 서포트 홈페이지
http://www.oracle.com/support/premier/lifetime-support-policy.html

 

제공 : DB포탈사이트 DBguide.net

반응형
Posted by [PineTree]
ORACLE/TUNING2013. 6. 23. 21:52
반응형

출처 : http://www.bysql.net/index.php?document_srl=18171

1. 10046 Event가 갖지 못한 DBMS_XPLAN.DISPLAY, DBMS_XPLAN.DISPLAY_CURSOR의 장점

  • Query Block Name / Object Alias : 쿼리 블록 정보
  • Outline Date : 오라클 내부 Hint
  • Predicate Information : Access 조건 및 조인 조건, Filter 조건
  • Column Projection Information : Operation Id 별로 Select된 컬럼 정보
  • Format : 자신에게 맞는 Format 설정이 자유로움

2. DBMS_XPLAN

3. DBMS_XPLAN.DISPLAY_CURSOR

  • Function Parameter
    • FUNCTION DISPLAY_CURSOR(SQL_ID VARCHAR2 DEFAULT NULL,
                              CURSOR_CHILD_NO INTEGER DEFAULT 0,
                              FORMAT VARCHAR2 DEFAULT 'TYPICAL')
  • 파라미터 설명
  • 파라미터

    설명

     SQL_ID

     

     

     실제 수행된 SQL의 SQL_ID 값을 입력하면 해당 SQL의 실행계획을 볼 수 있다.

     SQL_ID 값은 V$SQL, V$SQLAREA에서 확인할 수 있다.

     SQL_ID 값을 명시하지 않으면 해당 세션의 마지막에 실행된 문장을 의미한다.

     CHILD_NUMBER

     

     해당 SQL_ID의 CHILD NUMBER 값을 지정한다.

     CURSOR_CHILD_NO 값을 명시하지 않으면 해당 SQL_ID의 첫번째 CURSOR_CHILD_NO 값을 가져온다.

     FORMAT

    저장된 PLAN을 어떤 Format으로 보여줄 지 결정하는 파라미터

  • FORMAT 옵션

    구분

    FORMAT
    내용

     예측 내용

     

     

    BASIC
    가장 기본적인 정보만 보여준다.
    TYPICAL
    FORMAT의 DEFAULT 값인 TYPICAL은 SQL 투닝에 필요한 NORMAL한 정보를 보여 준다. SQL 튜닝에 가장 유용하게 사용되는 PREDICATE INFORMATION이 제공된다.
    ALL
    TYPICAL  FORMAT에 QUERY BLOCK NAME과 COLUMN PROJECTION INFORMATION이 추가로 제공된다.
    OUTLINE
    TYPICAL FORMAT에 추가적으로 HIDDEN HINT인 OUTLINE GLOBAL HINT를 제공한다.
    ADVANCE
    ALL FORMAT에 OUTLINE FORMAT를 합친 정보를 제공한다.

     실측 내용

     

    ALLSTATS
    실제 엑세스한 로우수와 수행시간, CP, PR, PW 정보를 보여준다.
    수행횟수에 따라 누적된 값을 보여준다.
    ALLATATS LAST
    실제 엑스스한 로우수와 수행시간, CP, PR, PW 정보를 보여준다.
    마지막에 수행된 값을 보여준다.
    ADVANCED ALLSTATS LSAT
    DBMS_XPLAN.DISPLAY_CURSOR에서 지원하는 모든 FORMAT의 정보를 보여준다.


4. DBMS_XPLAN.DISPLAY_CURSOR 사용방법

  • PLAN 정보 기록
    • 'GATHER_PLAN_STATISTICS' HINT 사용

      SELECT /*+GATHER_PLAN_STATISTICS*/

                       *
        FROM (SELECT E.*
                FROM EMPLOYEE E
               WHERE E.DEPARTMENT_ID = 50
               ORDER BY E.EMPLOYEE_ID)
       WHERE ROWNUM <= 100

    • STSTISTICS_LEVEL를 ALL로 설정
    • '_ROWWOURCE_EXECUTION_STATISTICS' 파라미터를 TRUE로 설정\
  • PLAN 정보 조회

     SELECT *

       FROM TABLE( DBMS_XPLAN.DISPLAY_CURSOR( NULL, NULL, 'ADVANCED ALLSTATS LAST')) 


5. Plan 상의 항목들에 대한 설명

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |      1 |        |       |     4 (100)|          |     45 |00:00:00.01 |       3 |       |       |          |
|*  1 |  COUNT STOPKEY                 |                   |      1 |        |       |            |          |     45 |00:00:00.01 |       3 |       |       |          |
|   2 |   VIEW                         |                   |      1 |     45 |  5985 |     4  (25)| 00:00:01 |     45 |00:00:00.01 |       3 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY       |                   |      1 |     45 |  3105 |     4  (25)| 00:00:01 |     45 |00:00:00.01 |       3 |  6144 |  6144 | 6144  (0)|
|   4 |     TABLE ACCESS BY INDEX ROWID| EMPLOYEE          |      1 |     45 |  3105 |     3   (0)| 00:00:01 |     45 |00:00:00.01 |       3 |       |       |          |
|*  5 |      INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |      1 |     45 |       |     1   (0)| 00:00:01 |     45 |00:00:00.01 |       1 |       |       |          |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2
   4 - SEL$2 / E@SEL$2
   5 - SEL$2 / E@SEL$2
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$2")
      OUTLINE_LEAF(@"SEL$1")
      NO_ACCESS(@"SEL$1" "from$_subquery$_001"@"SEL$1")
      INDEX_RS_ASC(@"SEL$2" "E"@"SEL$2" ("EMPLOYEE"."DEPARTMENT_ID"))
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<=100)
   3 - filter(ROWNUM<=100)
   5 - access("E"."DEPARTMENT_ID"=50)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "from$_subquery$_001"."EMPLOYEE_ID"NUMBER,22, "from$_subquery$_001"."FIRST_NAME"VARCHAR2,20, "from$_subquery$_001"."LAST_NAME"VARCHAR2,25,
       "from$_subquery$_001"."EMAIL"VARCHAR2,25, "from$_subquery$_001"."PHONE_NUMBER"VARCHAR2,20, "from$_subquery$_001"."HIRE_DATE"DATE,7,
       "from$_subquery$_001"."JOB_ID"VARCHAR2,10, "from$_subquery$_001"."SALARY"NUMBER,22, "from$_subquery$_001"."COMMISSION_PCT"NUMBER,22,
       "from$_subquery$_001"."MANAGER_ID"NUMBER,22, "from$_subquery$_001"."DEPARTMENT_ID"NUMBER,22
   2 - "from$_subquery$_001"."EMPLOYEE_ID"NUMBER,22, "from$_subquery$_001"."FIRST_NAME"VARCHAR2,20, "from$_subquery$_001"."LAST_NAME"VARCHAR2,25,
       "from$_subquery$_001"."EMAIL"VARCHAR2,25, "from$_subquery$_001"."PHONE_NUMBER"VARCHAR2,20, "from$_subquery$_001"."HIRE_DATE"DATE,7,
       "from$_subquery$_001"."JOB_ID"VARCHAR2,10, "from$_subquery$_001"."SALARY"NUMBER,22, "from$_subquery$_001"."COMMISSION_PCT"NUMBER,22,
       "from$_subquery$_001"."MANAGER_ID"NUMBER,22, "from$_subquery$_001"."DEPARTMENT_ID"NUMBER,22
   3 - (#keys=1) "E"."EMPLOYEE_ID"NUMBER,22, "E"."DEPARTMENT_ID"NUMBER,22, "E"."FIRST_NAME"VARCHAR2,20, "E"."LAST_NAME"VARCHAR2,25,
       "E"."EMAIL"VARCHAR2,25, "E"."PHONE_NUMBER"VARCHAR2,20, "E"."HIRE_DATE"DATE,7, "E"."JOB_ID"VARCHAR2,10, "E"."SALARY"NUMBER,22,
       "E"."COMMISSION_PCT"NUMBER,22, "E"."MANAGER_ID"NUMBER,22
   4 - "E"."EMPLOYEE_ID"NUMBER,22, "E"."FIRST_NAME"VARCHAR2,20, "E"."LAST_NAME"VARCHAR2,25, "E"."EMAIL"VARCHAR2,25, "E"."PHONE_NUMBER"VARCHAR2,20,
       "E"."HIRE_DATE"DATE,7, "E"."JOB_ID"VARCHAR2,10, "E"."SALARY"NUMBER,22, "E"."COMMISSION_PCT"NUMBER,22, "E"."MANAGER_ID"NUMBER,22,
       "E"."DEPARTMENT_ID"NUMBER,22
   5 - "E".ROWIDROWID,10, "E"."DEPARTMENT_ID"NUMBER,22


1) Basics 항목

  • Id : 각 Operationd의 ID임. *가 달려있는 경우는 Predicate Informatio에 Access 및 Filter에 관한 정보를 표시함
  • Operation : 각각 실행되는 JOB
  • Name : Operationdl 엑세스 하는 Table 및 Index

2) Query Optimizer Estimations 항목(예상치)

  • E-Rows : 각 Operation이 끝났을 때 return 되는 건수.
  • E-Bytes : 각 Operation이 Temporany Space를 사용한 양
  • Cost(%CPU) : 각 Operation의 Cost. 괄호 안의 내용은 CPU Cost의 백분율임. 이 값은 Child Operation의 Cost를 합친 누적치.
  • E-Time : 수행시간

3) Runtime Statistics 항목

  • Starts : 각 Operation을 반복 수행한 건수
  • A-Rows : 각 Operation이 Return 한 건수
  • A-Time : 실제 실행시간. 0.01초까지 나타남(HH:MM:SS.FF).  Child Operation의 A-Time을 합친 누적치

4) I/O Statistics

  • Buffers : 각 Operation이 memory에서 읽은 Block 수.
  • Reads : 각 Operation이 Disk에서 Read한 Block 수.
  • Writes : 각 Operation이 Disk에서 White한 Block 수.

5) Memory Utilization Statistics(hash 작업이나 sort 작업 시 사용한 메모리 통계)

  • OMen : Optimal Execution에 필요한 Memory
    • SQL 실행 메모리가 최적의 크기를 가졌을때의 메모리. 여기서 메모리가 최적의 크기를 갖는다는 것은 예를 들어, disk에 write하지 않고 sort 작업을 수행하는 경우를 의미한다.
  • 1Mem : One-pass Execution에 필요한 Momory
    • SQL 실행 메모리가 1 pass의 크기를 가졌을 때의 메모리. 여기서 메모리가 1 pass의 크기를 갖는다는 의미는, 예를 들어 sort의 경우 disk에 임시 결과를 한번은 저장하고 결과를 merge해서 sort 작업을 마치는 경우를 의미한다.
  • O/1/M : 각 Operation이 실행한 Optmal/One-pass/Multipass 횟수가 순서대로 표시됨
                O 일 경우 메모리공간(hash_area_size)이 부족하지 않아 temp 영역(disk)을 
                사용하지 않고 처리 되었다는 의미임. 
    • multipass 횟수 : SQL 실행 메모리가 2 pass 이상의 크기를 가졌던 횟수.
  • Used-mem : 마지막 실행 시 사용한 PGA -Memory
  • Used-Tmp : 마지막 실행 시 메모리가 부족하여 Temporary Space를 대신 사용할 때 나타남. 보이는 값에 1024를 곱해야 함.
  • Max-Tmp : 메모리가 부족하여 Temporary Space를 사용할 때 최대 Temp 사용량. Used-Tmp와 다른 점은 마지막 수행시가 아니라 SQL을 여러 번 수행했을 경우에 항상 최대값만 보인다는 것. 보이는 값에 1024를 곱해야 함.

 

6) 쿼리블록 정보 : Plan 상의 Id별로 쿼리블럭 및 Alias 정보를 출력.,


7) Outline Date : 오라클이 내부적으로 사용한 힌트.


8) Predicate Information : Plan 상의 Id 별로 인덱스 액세스, Filter, 조인정보 등을 표출


9) Column Projection Information : Plan 상의 Id 별로 Select 되는 컬럼의 정보.



6. 쿼리 변형이 없는 단순 쿼리 튜닝의 경우는 최대한 단순화.

SELECT *
  FROM TABLE( DBMS_XPLAN.DISPLAY_CURSOR( NULL, NULL, 'ALLSTATS LAST -ROWS +PREDICATE'))  

  • Format : 'allstats last -rows +predicate'로 설정
    • 예측 Row 수(E-row) 생략. 실행통계와 Predicate Information만 출력

--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Starts | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  1 |  COUNT STOPKEY                 |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|   2 |   VIEW                         |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY       |                   |      1 |     45 |00:00:00.01 |       3 |  6144 |  6144 | 6144  (0)|
|   4 |     TABLE ACCESS BY INDEX ROWID| EMPLOYEE          |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  5 |      INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |      1 |     45 |00:00:00.01 |       1 |       |       |          |
--------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<=100)
   3 - filter(ROWNUM<=100)
   5 - access("E"."DEPARTMENT_ID"=50)



7.쿼리 변형이 발생하거나 복잡한 쿼리 튜닝시 쿼리블럭과 힌트정보를 추가로 출력

 SELECT *
  FROM TABLE( DBMS_XPLAN.DISPLAY_CURSOR( NULL, NULL, 'ALLSTATS LAST -ROWS +ALIAS +OUTLINE +PREDICATE'))  

  • Format : 'allstats last -rows +alias +outline +predicate'로 설정
  • Query Block Name / Object Alias 정보와 Outline Data 정보가 추가로 출력
  • +alias : 쿼리블록 추가
  • +outline : 오라클리 내부적으로 사용한 힌트정보를 출력

 --------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Starts | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  1 |  COUNT STOPKEY                 |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|   2 |   VIEW                         |                   |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY       |                   |      1 |     45 |00:00:00.01 |       3 |  6144 |  6144 | 6144  (0)|
|   4 |     TABLE ACCESS BY INDEX ROWID| EMPLOYEE          |      1 |     45 |00:00:00.01 |       3 |       |       |          |
|*  5 |      INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |      1 |     45 |00:00:00.01 |       1 |       |       |          |
--------------------------------------------------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2
   4 - SEL$2 / E@SEL$2
   5 - SEL$2 / E@SEL$2
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$2")
      OUTLINE_LEAF(@"SEL$1")
      NO_ACCESS(@"SEL$1" "from$_subquery$_001"@"SEL$1")
      INDEX_RS_ASC(@"SEL$2" "E"@"SEL$2" ("EMPLOYEE"."DEPARTMENT_ID"))
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<=100)
   3 - filter(ROWNUM<=100)
   5 - access("E"."DEPARTMENT_ID"=50)


반응형
Posted by [PineTree]