태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

왜 V$ 뷰보다 X$ 테이블을 더 좋아할 수 밖에 없는가?

오라클 2009. 10. 8. 15:25
오라클 성능 문제를 다루다 보면 V$ 뷰(Dynamic Performance View)를 반드시 사용하게 됩니다. 하지만 V$ 뷰를 한동안 사용하다보면 반드시라고 해도 좋을 만큼 X$ 테이블을 사용하고자 하는 욕심이 생깁니다.

왜 그럴까요? 왜 암호와 같은 못생긴 X$ 테이블을 나중에는 더 좋아하게 되는걸까요? 제 경험으로는 세 가지 정도의 이유가 있는 것 같습니다.

  1. V$ 뷰의 정의 자체를 더 잘 이해하게 도와준다.
  2. 성능면에서 더 효과적이다.
  3. V$ 뷰가 보여주지 않는 정보를 보여준다.
간단한 예를 들어 설명해 보겠습니다.

1. V$ 뷰의 정의 자체를 더 잘 이해하게 도와준다.

아래는 매뉴얼에서 설명하는 V$SESSION_WAIT.STATE 컬럼의 의미입니다.

V$SESSION_WAIT.STATE 	VARCHAR2(19) 	Wait state:
 WAITING - Session is currently waiting
 WAITED UNKNOWN TIME - Duration of the last wait is unknown; this is the value when the parameter TIMED_STATISTICS is set to false
 WAITED SHORT TIME - Last wait was less than a hundredth of a second
 WAITED KNOWN TIME - Duration of the last wait is specified in the WAIT_TIME column
무슨 말인지 알기는 하겠지만 가슴에 안와닿죠. 하지만 V$SESSION_WAIT 뷰의 정의를 보면 가슴에 딱 와닿습니다.
SYS@ukja1021> select view_name, view_definition
  2  from v$fixed_view_definition
  3  where view_name = upper('&1')
  4  ;
old   3: where view_name = upper('&1')
new   3: where view_name = upper('GV$SESSION_WAIT')

select s.inst_id,s.indx,s.ksussseq,e.kslednam, e.ksledp1,s.ksussp1,s.ksussp1r,e.
ksledp2, s.ksussp2,s.ksussp2r,e.ksledp3,s.ksussp3,s.ksussp3r, e.ksledclassid, e.
ksledclass#, e.ksledclass, decode(s.ksusstim,0,0,-1,-1,-2,-2,   decode(round(s.k
susstim/10000),0,-1,round(s.ksusstim/10000))), s.ksusewtm, 
decode(s.ksusstim, 0, 'WAITING', 
                          -2, 'WAITED UNKNOWN TIME',  
                          -1, 'WAITED SHORT TIME', 
                          decode(round(s.ksusstim/10000),0,'WAITED SHORT TIME','WAITED KNOWN TIME')) 
from x$ksusecst s
, x$ksled e where bitand(s.ksspaflg,1)!=0 and bitand(s.ksuseflg,1)!=0 and s.ksus
sseq!=0 and s.ksussopc=e.indx
V$ 뷰란 X$ 테이블을 베이스로 하는 뷰일뿐입니다. 따라서 뷰의 정의를 보면 마치 어플리케이션의 소스 코드를 보는 것 같은 효과를 얻을 수 있습니다.

2. 성능면에서 더 효과적이다.

버퍼 헤더 정보를 나타내는 V$BH 뷰와 X$BH 테이블에 대한 동일한 SQL문의 실행 계획을 비교해보면 다음과 같습니다.

UKJA@ukja1021> explain plan for
  2  select * from v$bh
  3  where file#=:b1 and block#=:b2
  4  ;

-------------------------------------------------------------------------- 
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     | 
-------------------------------------------------------------------------- 
|   0 | SELECT STATEMENT  |      |     1 |   138 |     1 (100)| 00:00:01 | 
|*  1 |  HASH JOIN OUTER  |      |     1 |   138 |     1 (100)| 00:00:01 | 
|*  2 |   FIXED TABLE FULL| X$BH |     1 |   108 |     0   (0)| 00:00:01 | 
|   3 |   FIXED TABLE FULL| X$LE |   100 |  3000 |     0   (0)| 00:00:01 | 
-------------------------------------------------------------------------- 
                                                                           
UKJA@ukja1021> explain plan for
  2  select * from sys.x$bh
  3  where file#=:b1 and dbablk=:b2
  4  ;

-------------------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |   533 |     0   (0)| 00:00:01 |
|*  1 |  FIXED TABLE FULL| X$BH |     1 |   533 |     0   (0)| 00:00:01 |
-------------------------------------------------------------------------
X$BH 테이블을 사용하는 것이 더 효율적이라는 것을 알 수 있습니다.

3. V$ 뷰가 보여주지 않는 정보를 보여준다.

가장 중요한 이유가 됩니다. 정보는 많을수록 좋은 법이죠. V$ 뷰는 사용자 편의성을 위해 일부 정보를 감춥니다. 하지만 이 감추어진 정보가 보고 싶을 때가 있습니다.

간단한 예로 설명해 보겠습니다. 다음과 같이 대량의 파싱을 수행하는 세션이 있습니다.

declare
  v_cursor      number;
begin
  for idx in 1 .. 200000 loop
    v_cursor := dbms_sql.open_cursor;
    dbms_sql.parse(v_cursor, 'select /* cursor_share */ * from t1 where c1 = :b1', dbms_sql.native);
    dbms_sql.close_cursor(v_cursor);
  end loop;
end;
/
이 세션이 어떤 Latch를 획득하는지를 조사합니다. V$LATCHHOLDER 뷰를 이용하면 됩니다.
SYS@ukja1021> desc v$latchholder
           Name                            Null?    Type
           ------------------------------- -------- ----------------------------
    1      PID                                      NUMBER
    2      SID                                      NUMBER
    3      LADDR                                    RAW(4)
    4      NAME                                     VARCHAR2(64)
    5      GETS                                     NUMBER
V$LATCHHOLDER 뷰의 정의는 다음과 같습니다.
SYS@ukja1021> @fixed_view GV$LATCHHOLDER
SYS@ukja1021> set long 100000
SYS@ukja1021> 
SYS@ukja1021> select view_name, view_definition
  2  from v$fixed_view_definition
  3  where view_name = upper('&1')
  4  ;
old   3: where view_name = upper('&1')
new   3: where view_name = upper('GV$LATCHHOLDER')

VIEW_NAME
------------------------------
VIEW_DEFINITION
--------------------------------------------------------------------------------
GV$LATCHHOLDER
select inst_id,ksuprpid,ksuprsid,ksuprlat,ksuprlnm,ksulagts from x$ksuprlat
베이스 테이블이 X$KSUPRLAT 테이블이죠. 정의는 다음과 같습니다.
SYS@ukja1021> desc sys.x$ksuprlat
           Name                            Null?    Type
           ------------------------------- -------- ----------------------------
    1      ADDR                                     RAW(4)
    2      INDX                                     NUMBER
    3      INST_ID                                  NUMBER
    4      KSUPRPID                                 NUMBER
    5      KSUPRSID                                 NUMBER
    6      KSUPRLLV                                 NUMBER
    7      KSUPRLTY                                 NUMBER
    8      KSUPRLAT                                 RAW(4)
    9      KSUPRLNM                                 VARCHAR2(64)
   10      KSUPRLMD                                 VARCHAR2(64)
   11      KSULAWHY                                 NUMBER
   12      KSULAWHR                                 NUMBER
   13      KSULAGTS                                 NUMBER
V$LATCHHOLDER 뷰에 존재하지 않는 다양한 정보들을 제공합니다. 이 중에서 KSULAWHR 컬럼은 소스코드의 어디에서 요청되었는가를 의미하고 KSULAWHY 컬럼은 부가적인 이유를 나타냅니다.

과도한 파싱을 수행하는 세션에 대해 V$LATCHHOLDER 뷰를 통해 분석한 경우와 X$KSUPRLAT 테이블을 통해 분석한 경우를 비교해 볼까요? 우선 V$LATCHHOLDER 뷰를 이용한 경우(prof_latch.sql)는 다음과 같습니다.

UKJA@ukja1021> @prof_latch 200000 159 %

       SID LADDR    NAME                                 HITS
---------- -------- ------------------------------ ----------
       159 3253DE80 library cache                       12037
       159 3253E0F0 library cache lock                   1595
       159 3253DFB8 library cache pin                     883
평면적이죠. X$KSUPRLAT 테이블을 이용한 경우(prof_latch2.sql)는 다음과 같습니다.
UKJA@ukja1021> @prof_latch2 200000 159 %

 SID LADDR    CALLED            NAME              OBJECT               HITS
---- -------- ----------------- ----------------- ----------------- -------
 159 3253DFB8 kglpnal: child: a library cache pin                 2    1066
              lloc space

 159 3253DFB8 kglpndl           library cache pin                 2     402
 159 3253E0F0 kgllkal: child: m library cache loc                 2     862
              ultiinstance      k

 159 3253E0F0 kgllkdl: child: c library cache loc                 2     930
              leanup            k

 159 3253DE80 kglhdgc: child:   library cache                     2    1176

 SID LADDR    CALLED            NAME              OBJECT               HITS
---- -------- ----------------- ----------------- ----------------- -------
 159 3253DE80 kglhdgn: child:   library cache                     2     737
 159 3253DE80 kgllkdl: child: n library cache                     2    2523
              o lock handle

 159 3253DE80 kglpin: child: he library cache                     2    7206
              ap processing

 159 3253DE80 kglpndl: child: b library cache                     2    3293
              efore processing
V$LATCHHOLDER 뷰가 감춘 정보를 이용함으로써 훨씬 입체적인 정보를 얻을 수 있습니다.

X$ 테이블에 대한 정보를 얻는 가장 좋은 방법은 V$ 뷰의 정의를 V$FIXED_VIEW_DEFINITION 뷰를 통해 확인해 보는 것입니다. 몇 가지를 시도해보면 의외의 좋은 정보를 많이 얻게 됩니다. 보다 깊은 레벨로 가고자 하는 분들은 꼭 시도해보세요.

Trackbacks 0 : Comments 1
  1. [Challenge] 2010.10.28 18:34 신고 Modify/Delete Reply

    아주 공감이 가는 자료이네요.. ㅎㅎ;;

    그리고 좋은 자료 감사합니다.. ^^

Write a comment