반응형

DB 점검 도중, 약 60만건의 테이블에(담당자가 메인테이블이라고..) index가 20개 이상이 걸려 있는 것을 확인했다.

 

그리고 대부분 index들이 결합인덱스보다는 단일인덱스 인 것을 확인하고,

담당자에게 모두 필요한 index라고 물어보니

필요에 의해서 해당 테이블과 연관된 담당자들에 의해서 생성한 거라고,

자기도 잘 모른다고 하더군...

 

흠...내가 소속 DBA가 아닌 파견도..아닌 협력업체...DBA이다 보니..

이러지도 저러지도 못하는 상황..

 

보고는 하였지만..그래도 나는 DBA의 지부심이 있기에!!!내가 주체가 되어...제안....

"우리 INDEX 모니터링 걸어서 불필요한 거는 제거하고,

필요한 거는 새로 걸자고 제안....

 

index monitoring 관련 쿼리를 확인해 봤다.

 

1. index monitoring 여부 확인

 

-- 해당 user 라면 아래 쿼리를 이용하여 확인이 가능

SELECT table_name,
       index_name,
       monitoring
FROM   v$object_usage
WHERE  table_name = UPPER('&1')
AND    index_name = DECODE(UPPER('&2'), 'ALL', index_name, UPPER('&2'));

 

--나는 DBA다!!!!

col owner for a10
col index_name for a20
col table_name for a20

 

SELECT U.NAME OWNER,
IO.NAME INDEX_NAME,
T.NAME TABLE_NAME,
DECODE(BITAND(I.FLAGS, 65536), 0, 'NO', 'YES') MORNITORING,
DECODE(BITAND(OU.FLAGS, 1), 0, 'NO', 'YES') USED,
OU.START_MONITORING,
OU.END_MONITORING
FROM SYS.USER$ U,
SYS.OBJ$ IO,
SYS.OBJ$ T,
SYS.IND$ I,
SYS.OBJECT_USAGE OU
WHERE I.OBJ# = OU.OBJ#
AND IO.OBJ# = OU.OBJ#
AND T.OBJ# = I.BO#
AND U.USER# = IO.OWNER#;

 

-- v$object_usage는 자신의 index 만 확인 가능하기에 이 점 유의!!

 

2. index에 모니터링이 걸려 있지 않으면 아래 쿼리를 이용하여 명령문을 만들 수 있다.

 

-- owner 와 table_name 을 입력해야 함

 

SELECT 'ALTER INDEX "' || i.owner || '"."' || i.index_name || '" MONITORING USAGE;'
FROM   dba_indexes i
WHERE  owner      = UPPER('&1')
AND    table_name = DECODE(UPPER('&2'), 'ALL', table_name, UPPER('&2'));

 

 

 

 

3. 다시 체크한 결과 (위의 index monitoring 으로 조회)

 

 

 

4. index에 모니터링이 걸려 있는 것에 대해 해제 하는 명령어

 

 
SELECT 'ALTER INDEX "' || i.owner || '"."' || i.index_name || '" NOMONITORING USAGE;'
FROM   dba_indexes i
WHERE  owner      = UPPER('&1')
AND    table_name = DECODE(UPPER('&2'), 'ALL', table_name, UPPER('&2'));

 

 

이렇게 하여 일단 체크를 진행하기 시작했다.

 

여기서 반은 걷어 냈으면 하는 바램이...

 

 

 

반응형

'Oracle > DBA' 카테고리의 다른 글

[Oracle] Process / Session 모니터링  (0) 2016.01.17
[펌][ORACLE] ORA-에러  (0) 2015.12.22
[Oracle] Partition Local Index 테스트  (0) 2015.12.02
[ORACLE] ASM 에 Datafile 추가  (1) 2015.11.25
[Oracle] OWI Latch & Lock 정리  (0) 2015.11.24
반응형

아흐..

지난 주 스터디 하면서 자신있게 Partition Table 과 관련하여 발표 도중

Partition Local index 에서 맨붕이 와버렸다..


그래도 내가 알려주는거에 대한 책임감(??변명..) 때문에 다음에 다시 발표하겠다 한 후 

이제서야 테스트 하면서 결과에 대해서 공유해 본다.


1. 파티션 테이블 생성


SQL> create table test_a

(col1 number,

col2 number,

col3 varchar2(20))

Partition by range (col1, col2)

(Partition part_test_a_1 values less than (10, 100),

Partition part_test_a_2 values less than (20, 200) ,

Partition part_test_a_3 values less than (30, 300) ,

Partition part_test_a_4 values less than (40, 400) );


2. Local Index 생성
(여기서 맨붕이 왔다. 내가 테스트한 부분은 아래와 같이 생성하였으며 이렇게 생성해야만 하는걸로 알고 있었다..)

SQL> create Index ix_test_a on test_a(col1, col2) Local

(Partition in_test_a_1 ,

Partition in_test_a_2 ,

Partition in_test_a_3 ,

Partition in_test_a_4 );


조회해 보면 아래와 같다



하지만 책에는 아래와 같이 나와 있다.

SQL> create index ix_test_a on test_a(col1, col2) local;



확인해 보면 partition_name 만 틀릴 뿐 나머지는 동일하다.


partition name 은 어떻게 되는걸까?

Table를 다시 생성해 본다


SQL> create table test_c

(col1 number,

col2 number,

col3 varchar2(20))

Partition by range (col1, col2)

(Partition test_c_1 values less than (10, 100),

Partition test_c_2 values less than (20, 200) ,

Partition test_c_3 values less than (30, 300) ,

Partition test_c_4 values less than (40, 400) );


SQL> create index ix_test_c on test_c(col1, col2) local;



Index Partition_Name은 명시해 줄 경우 명시된 partition 이름으로 가며, 

명시안하는 경우 Partition Table의 partition name을 따라가는 것을 확인할 수 있다.



왜 이렇게 쉬운 부분에서 멘붕이 오냐고 질책할 수 있지만...내 잘못입니다...ㅠㅠ

테스트 꼭 해보고 책도 한번씩 쿼리 다 작성해서 결과확인 후 진행 하도록 하겠습니다.

죄송합니다.ㅠ


한가지 더 테스트로 Local index 를 명시하되, 파티션 table과 동일한 갯수로 생성을 안하면 어떻게 되는걸까,


SQL> create Index ix_test_a on test_a(col1, col2) Local

(Partition in_test_a_1 ,

Partition in_test_a_2 ,

Partition in_test_a_3);



우리가 책에서 배웠듯이 에러가 발생한다.


아래는 내가 어떤 자료를 보고 정리한 내용이다.



구분

적용 기준 및 고려 사항

비 파티션

-       파티션 키 칼럼이 조건절에 누락되면 여러 인덱스 파티션을 액세스해야 하므로 비효율적. 특히, OLTP 환경에서 성능에 미치는 영향이 크므로 비파티셔닝 전략이 유용할 수 있음


-       NL Join 에서 파티션 키에 대한 넓은 범위검색 조건을 가진 Inner 테이블 액세스 용도로 인덱스 파티션이 사용된다면 효율적 -> 비파티션 인덱스 사용을 고려


-       파티션 인덱스를 이용하면 sort order by 대체 효과 상실. Sort 연산을 대체함으로써 부분범위 처리를 활용하고자 할 땐 비파티셔닝 전략이 유용


-       테이블 파티션 이동, 삭제 등의 작업 시 unusable 되므로 적용 시 주의

Global Prefixed

     - 인덱스 경합 분산에 효과적


     - 여러 Local 인덱스 파티션을 액세스하는 것이 비효율적일 때 대안으로 활용 가능


     - 테이블 파티션 이동, 삭제 등의 작업 시 unusable 되므로 적용 시 주의

Local Prefixed

-       관리적 특면에서 유용 : 테이블 파티션에 대한 추가, 삭제 등의 작업이 빈번할 때


-       이력성 데이터를 주로 관리하는 DB 환경에 효과적


-       파티션 키 칼럼이 “=” 조건으로 사용될 때 유용


-       파티셔닝 칼럼에 대한 검색 조건이 없으면, 인덱스 선두 칼럼이 조건절에 누락된 것이므로 정상적인 사용이 불가 (Index Full Scan 으로는 선택 가능)


-       파티션 키 칼럼(=인덱스 선두 칼럼)Like, Between, 부등호 같은 범위검색 조건일 때 불리

Local Non Prefixed

-       관리적 측면에서 유용 : 테이블 파티션에 대한 추가, 삭제 등의 작업이 빈번할 때


-       이력성 데이터를 주로 관리하는 DB 환경에 효과적


-       파티션 키 칼럼이 조건절에 사용될 때 유용


-       파티셔닝 칼럼에 대한 검색 조건이 없으면 인덱스 파티션 전체를 액세스하는 비효율이 발생할 수 있으므로 주의


-       파티션 키 칼럼이 범위검색 조건으로 자주 사용된다면 Local Prefixed 보다 Local NonPrefixed가 유리. 그렇더라도 좁은 범위검색이어야 함



반응형

'Oracle > DBA' 카테고리의 다른 글

[펌][ORACLE] ORA-에러  (0) 2015.12.22
[Oracle] Index monitoring  (0) 2015.12.14
[ORACLE] ASM 에 Datafile 추가  (1) 2015.11.25
[Oracle] OWI Latch & Lock 정리  (0) 2015.11.24
[펌][Oracle] 대용량 자료전환 시 튜닝 포인트 - Hash join  (0) 2015.11.19
반응형

가끔 Datafile 옮길...일이 없지만..

이번 운영 확인하다 보니, datafile 이 엔진쪽에...헉!!!!


HA 장비라서 엔진쪽에 있으면 안되는데...왜???누가???


에휴...고객사 장비라 누가 건든지 알수 없으니..

더 큰 문제가 생기기 전에 옮겨줘야겠다..


1. Database 로 진행 (DB Shutdown 필요)

2. Tablespace 로 진행 (DB Shutdown 필요 없음)


1. Database 로 진행

- Tablespace 및 Datafile 확인

- DB shutdown 후 Mount 로 startup 진행


SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.


SQL> startup mount

ORACLE instance started.


Total System Global Area  612368384 bytes

Fixed Size                  2079480 bytes

Variable Size             176162056 bytes

Database Buffers          427819008 bytes

Redo Buffers                6307840 bytes

Database mounted.


- 해당 Datafile 를 이동 후 rename 진행


SQL> alter database rename file 'E:\MASDBDEV\HG1.dbf' to 'E:\HG1.dbf';


- Database open 진행


SQL> alter database open;

Database altered.


- 확인

SQL> select file_name, tablespace_name from dba_data_files order by 2;


FILE_NAME                                TABLESPACE_NAME

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

E:\MASDBDEV\HG2.DBF                      HG

E:\HG1.DBF                               HG

E:\MASDBDEV\IMSI01.DBF                   IMSI

E:\MASDBDEV\SYSAUX01.DBF                 SYSAUX

E:\MASDBDEV\SYSTEM01.DBF                 SYSTEM

E:\MASDBDEV\TEST01.DBF                   TEST

E:\MASDBDEV\UNDOTBS01.DBF                UNDOTBS1

E:\MASDBDEV\USERS01.DBF                  USERS




2. Tablespace 로 진행


- Tablespace 및 Datafile 확인



- 옮기고자 하는 Datafile 의 Tablespace 를 offline 진행


SQL> alter tablespace HG offline;


- Offline 이 후 해당 Datafile 를 이동 후 rename 진행


SQL> alter tablespace HG rename datafile 'E:\HG1.dbf' to 'E:\MASDBDEV\HG1.dbf';


- Rename 까지 완료 되면 다시 online 진행


SQL> alter tablespace HG online;


- 옮겨 졌는지 확인 후 Test로 Talbe 를 Select 해 보자.


혹시라도 Tablespace offline 이 후 Table를 select 하면 아래와 같이 오류가 나니 가급적 업무 시간에는 진행하지 말자.


ERROR at line 1:

ORA-00376: file 7 cannot be read at this time

ORA-01110: data file 7: 'E:\HG1.DBF'



또한, SYSTEM, Rollback segment혹은 Temporary segment를 포함하는 테이블스페이스는 안되므로 이때는 Database로 진행


ERROR at line 1:

ORA-01541: system tablespace cannot be brought offline; shut down if necessary


오늘도 기초를 한번 더 상기해 보자!!

반응형
반응형

사실 내가 관리하는 사이트 들은 모두 File system을 사용한다.

(개발/관리 업무만 하던 이전 직장에 있다가 DB로 넘어온 후 File system / Raw device / Cluster가 뭔지 정말 생소한 단어들에 엄청 맘 고생하면서 찾아보고...물어보기도 창피하고 직급은 있는데...정말 그때 생각하면 아직도 가슴이 찡하다..이게 도대체 뭐라고 ㅋㅋㅋ)


하지만 동료들 사이트 보면 간간히 ASM 이 포함되어 있어서 이레저레 한두번 보기만 해봤다.

물론 테스트 디비랑은 다 구축해 놨지만 정작 구축만 하고 활용은 안했다는..


각설하고 이번에 ASM 에 datafile 추가하는데 file system 처럼 하면 되는데,

갑자기 왜 file 명이 이래요..? 이리 물어보니.. 어버버 거려서 이참에

한번 정리해 본다.


ASM 에 Tablespace 추가


sql) CREATE TABLESPACE TEST DATAFILE SIZE 10M;


이렇게 하면 자동으로 datafile 명시 안해줘도 disk group 아래에 생성이 된다.



cf) File system 에서는 아래와 같이 명시적으로 추가해 줘야한다

sql) CREATE TABLESPACE TEST DATAFILE '/DATA/ORCL/test_data01.dbf' SIZE 10m;


혹시라도 아래와 같은 에러가 발생할 수 있다.

ERROR at line 1:

ORA-01119: error in creating database file '+DATA'

ORA-17502: ksfdcre:4 Failed to create file +DATA

ORA-15001: diskgroup "DATA" does not exist or is not mounted

ORA-15001: diskgroup "DATA" does not exist or is not mounted


그러면 아래와 같이 경로를 확인해 보자.


SQL> show parameter db_create_file_dest



Disk Group 위치도 확인해 보자


SQL> select group_number, name, state from v$asm_diskgroup;

SQL> select b.name group_name, a.name disk_name, a.header_status , a.state, a.free_mb from v$asm_disk a, v$asm_diskgroup b
       where a.group_number = b.group_number;



이리 저리 봐도 DB_CREATE_FILE_DEST 가 잘못 설정되어 있는 것을 확인할 수 있다.

변경하자. 

변경 후에 DB는 재기동 할 필요가 없다.


SQL> alter system set db_create_file_dest='+DATA1';


이후 다시 Tablespace 생성 하면 문제 없이 생성 되는 것을 확인할 수 있다.




이번에는 Add datafile 진행을 해 보자.


SQL> alter tablespace TEST add datafile '+DATA1/orcl/datafile/test2.dbf' size 10m;


이렇게 추가는 가능하지만, Data guard 등에서 문제가 생길 수 있다고 하기에..

(이 부분은 찾아서 올리도록 하겠습니다.........[정중히ㅠ])


가급적 자동으로 생성 되도록 유도하자.(ASM 에서 A가 Automatic 이니깐!! Storage Management )


SQL> ALTER TABLESPACE TEST ADD DATAFILE SIZE 10m;

아래를 보면 명시한 파일명을 명시한 경우와 명시하지 않은 경우가 있다.

가급적 우리는 명시하지 않도록 하고 자동으로 관리하도록 하자.



추가적으로 확인해야 할 부분들도 많고 하지만..

차근차근 진행을 한 후 공유 하도록 해야겠다.


참고 사이트 : http://dinggur.tistory.com/201

반응형
반응형

틈틈히 OWI 책을 보면서 공부하는데..

가장 기본이 되는 Latch 와 Lock 관련하여 정리하여 올려본다.


아는 내용도 있지만 그래도 다시 한번 익히는 좋은기회겸..

또 몰랐던 내용도 알 수 있는 거라 공부하면서 Word 로 정리 해봤다.


흠....이쁘게 정리할 수도 있지만...그냥 편하게...ㅎㅎ

복사해서 필요한것만 find 하도록...


 

래치와 락 (latch & lock) - OWI

By. Louis Kim 

래치와 락의 존재 이유는 동시 작업으로 오라클의 자원을 보호하는 것

분류

래치(Latch)

(Lock)

목적

하나의 목적을 수행함 : 메모리 구조에 대한 배타적인 접근을 위함 ( 오라클 9i 부터cache buffers chains latch 들은 읽기 전용시에 공유가 가능함

두 가지 목적을 수행함: 락 모드가 호환가능하면 다수의 프로세스가 동일한 리소스를 공유하는 것을 허용하며, 락 모드가 호환 가능하지 않으면 리소스에 대한 배타적인 접근만 허용함

사용범위

SGA 내부의 데이터 구조에만 적용. 메모리 오브젝트를 임시적으로 보호함. 단일 오퍼레이션으로 메모리 구조에 대한 접근 제어. 트랜잭션 단위가 아님

테이블, 데이터 블록 및 state object와 같은 오브젝트를 보호함.

데이터베이스의 데이터 또는 베타데이터 접근 제어. 트랜잭션 단위

획득방식

두 가지 모드로 요청이 가능 : willing-to-wait 또는 no-wait

6가지 모드로 요청이 가능 : null, row share, row exclusive, share, share row exclusive 또는 exclusive

범위

SGA내부에 정보가 존재하며, 로컬 인스턴스에서만 볼 수 있음 래치는 인스턴스 레벨로 작동

데이터베이스 내부에 정보가 존재하며, 모든 인스턴스에서 볼 수 있음 락은 데이터베이스 레벨에서 작동

복잡도

단순한 명령어를 사용하여 구현됨. 일반적으로 test-and-set, compare-and-swap 또는 단순한 CPU명령어. 구현이 쉬움

문맥 교환(context switch)를 포함한 일련의 명령어들을 사용하여 구현됨, 구현이 복잡함

지속기간

아주 짧은 순간만 지속됨 (microsecond 단위)

일정 시간 동안 지속됨 (트랜잭션 동안)

프로세스가 래치 획득을 실패한 후 슬립(sleep) 상태로 들어갈 때, 해당 요청은 큐(queueu)로 관리되지 않으며, 요청한 순서대로 서비스되지 않음(latch wait list를 이용하여 큐 방식으로 사용되는 래치들은 예외임)

프로세스가 락 획득을 실패한 후, 해당 요청은 큐(queue)로 관리되며, 요청한 순서대로 서비스됨(no-wait 모드는 예외임)

데드락

래치는 데드락(deadlock)이 발생되지 않도록 구현됨

락은 큐(queue)방식을 사용하며, 데드락이 발생될 가능성이 높다. 데드락이 발생 될 때마다 트레이스 파일이 생김

 


 

Latch (래치)

-       가벼운 락(lightweight lock) 으로 분류 (아주 빠른 속도로 작동하게끔 구현된 경량화된 락)

-       Shared pool 영역에 존재하는 일종의 메모리 구조체

-       매우 간단하고 작은 메모리영역을 사용하며, 래치를 획득(get)하고 해제(release)하는 작업들 또한 하드웨어 맞게 극도로 최적화 되어 있음

-       래치를 획득하고 해제하는 과정은 원자성(atomicity)이 보장

-       래치 획득의 순서를 보장하지 않음. 순서가 보장되어야 하는 작업은 락에서 진행

-       래치는 SGA 리소스를 보호하기 위함

-       SQL문을 실행하고자 하는 프로세스는 SQLshared pool library cache 영역에 올려야하는데, 이 때 heap 메모리 영역을 할당받기 위해 반드시 shared pool 래치를 획득 필요

-       하나의 프로세스만이 힙으로부터 청크(chunk)를 할당받을 수 있음

-       select문의 경우 특정 데이터블록을 읽기 위해 데이터블록의 DBA Class에 해당하는 Hash chain에 접근하고자 하는 모든 프로세스는 반드시 Hash chain을 관장하는 cache buffers chains Latch를 획득해야 함

-       DML를 실행하기 위해서는 PGA영역에 Redo 데이터를 생성 / Redo dataRedo buffer로 복하기 위해 redo copy latch 가 필요

-       Latch 획득하기 위해서 특정 대기 이벤트가 필요 (latch free 대기 이벤트 / p1=address , p2=latch# 래치 이름 획득)

-       Child latch를 사용하는 메모리 영역들도 있음

-       Buffer cache 의 경우 각각의 hash chain을 독립적으로 관리할 수 있는 구조로 되어 있기에 복수개의 cache buffer chains latch 를 사용

Parent Latch(부모래치) : 여러 개의 자식 latch를 거느릴 수 있음

Solitary Latch (독립래치) : 전체 인스턴스에 단 하나만 존재하는 래치

Child Latch (자식 래치) : 부모 래치에 속한 래치

부모 래치와 독립 래치는 V$LATCH_PARENT 뷰를 이용하여 관찰 가능

자식 래치는 V$LATCH_CHILDREN 부를 통해 관찰 가능

-       In Memory Undo 의 경우 10g 이후부터 생긴 것이며 KTI-UNDO 영역을 보호하기 위한 in memory undo latch 가 있음


 

래치 동작 메커니즘

-       여러 프로세스가 동시에 래치를 획득하는 과정에서 데드락 현상 발생(서로 가지고 있는 래치를 요구하는 경우)

-       데드락 발생을 피하기 위해서 자신 보다 낮은 래치의 경우 no-wait 또는 자신이 획득한 래치 레벨보다 높은 레벨을 요청

래치 모드

-       래치는 기본적으로 Exclusive 모드 사용(한 순간에 하나의 프로세스만이 래치를 보유)

-       특정 래치에 대해서는 Shared mode 를 사용( Cache buffers chains Latch)

래치 획득

-       Willing-to wait 모드 래치 획득

n  래치 획득하기 위해서 기본적으로 willing-to-wait 모드를 사용(래치를 획득할 때까지 대기를 의미) – 실패 시 적절한 회수만큼 루프를 돌며 획득 시도 (_SPIN_COUNT 기본 2000) – 이후에도 실패 시 래치가 풀릴때가지 sleep

n  Sleep 을 바로 하지 않고 spin 하는 이유

1.     아주 빠른 시간안에 다른 프로세스가 래치를 해지할 것이라고 기대

2.     슬립 상태로 빠지게 되면 OS차원에서 Context switching이 발생(이것이 약간의 CPU를 소모하기 때문에 비용적인 측면에서 sleep 보다는 spin이 나음)
cf) spin
과정에서 Active 상태로 CPU를 계속 점유하기 위해서 일정 시간 소량의CPU를 소모(Active wait)  -> 래치 경합에 의해서 많은 수의 프로세스가 동시에 스핀을 수행할 경우 높은 CPU 사용율을 보일 수 있음(래치 경합을 줄이기 위해 CPU를 늘이는 것은 더욱더 상황을 악화 위험)

n  Sleep 에서 깨어나는 방법

1.     약속된 시간(타임아웃)

2.     Latch wait list에서 자신의 순서가 되어 다른 프로세스가 깨워주는 방법 (latch wait posting)

u  주로 sleep 상태에서 프로세스는 latch:xxx / latch free 이벤트를 대기

u  매번 슬립 시간이 두배로 증가함으로써 빠른 시간내에 래치 획득을 재시도하는 과정에서 지나친 스핀으로 인해 CPU를 과다하게 사용하는 것을 방지


 

No-wait 모드의 래치 획득

-       대부분의 latch 획득은 willing-to-wait 모드를 사용하지만 특수한 경우 no-wait 모드 사용

-       가장 최근에 획득한 래치보다 더 낮거나 같은 레벨의 래치를 획득하고자 할 때

-       데드락을 피하기 위함

-       No-wait 모드의 래치 획득에 실패할 경우 획득하고자 하는 래치보다 높은 레벨의 래치는 모두 해제하고 올바른 순서로 다시 획득 시도

Ex) 1,2,4 레벨의 레치를 획득 후 3레벨 래치 획득 시도 시 no-wait 시도 / 실패 시 1,2 레벨을 남기고 4 레벨 래치 포기 후 3레벨 순서로 획득

래치 cleanup

-       래치를 획득한 후 공유 메모리 영역을 변경하고자 하는 프로세스는 변경 전에 래치복구 영역에(latch recovery area) 자신의 목적에 대한 정보를 기록
이 후, 갑작스럽게 프로세스가 래치를 보유한 채로 종료되면 PMON에서 cleanup function을 호출하여 래치 복구영역에 기록된 정보를 이용하여 복구

 

래치 관련 Dynamic Views (V$LATCH)

-       v$latch_parent : 독립 래치에 대한 통계값을 제공

-       v$latch_children : 모든 개별 자식 래치들에 대한 통계값을 제공

컬럼

설명

GETS

Willing-to-wait 모드에서 슬립하기 전의 래치 요청회수

MISSES

Willing-to-wait 모드에서의 슬립하기 전의 래치 획득 실패 회수

SPIN_GETS

Willing-to-wait 모드에서 슬립하기 전의 스핀단계에서의 래치 획득 성공 회수

SLEEPS

Willing-to-wait 모드에서의 슬립 회수

IMMEDIATE_GETS

No-wait 모드에서 래치 획득 성공 회수

IMMEDIATE_MISSES

No-wait 모드에서 래치 획득 실패 회수

SLEEP1 ~ SLEEP4

1~3 회의 슬립회수와 4회 이상의 슬립 회수. 오라클 10gR2부터는 사용되지 않으며 V$EVENT_HISTOGRAM 뷰로 대체

WAITERS_WOKEN

Latch wait posting 을 사용할 경우 세션이 깨어난 회수. 오라클 10gR2 부터는 사용되지 않는다. Latch wait list 래치가 없어진 것과 같은 맥락으로 latch wait posting 알고리즘이 완전히 바뀌었음을 의미

WAIT_TIME

래치를 획득하기 위해 대기한 시간(microsecond) 단위

 

-       GETS MISSES 비율을 이용하여 경합이 있는지를 판단

-       Willing-to-wait 모드일 경우 MISSES / GETS , No-wait 모드일 경우에는 IMMEDIATE_MISSES / (IMMEDIATE_GETS + IMMEDIATE_MISSES) 값이 1% 이상이면 래치 경합이 발생한 것으로 판단

-       Wait_time 을 이용해 대기시간이 CPU 시간에 비해 어느 정도 높은 값을 보일 경우 래치 경합이 발생한 것으로 판단

 

일반적인 래치 관련 대기이벤트들

-       Latch: cache buffers chains : Buffer cache에서 특정 블록을 탐색하고자 하는 프로세스는 cache buffers chain Latch 를 반드시 필요 이 과정에서 경합이 발생 시 발생 이벤트

-       Latch: cache buffers lru chain : Buffer cache에서 free buffer dirty buffer를 탐색하고자 할 때 경합 발생시 발생되는 이벤트

-       Latch: shared pool : Shared pool Heep 영역에 chunk를 할당 받고자 할 때 경합 발생 시

-       Latch: library cache : Library cache 영역을 탐색하고 할 때 경합 발생 시 이벤트

-       Latch: redo copy : DML에 의한 변동사항을 Redo Buffer에 기록하고자 할 때 작업의 전 과정 동안 redo copy latch 획득 필요 이 때 경합 시 발생

Latch Free 대기 이벤트의 경우 P2의 값이 latch# 이므로 이 값을 V$LATCHNAME.LATCH# 과 조인하면 래치이름을 얻을 수 있음


 

(Lock)

락의 분류

1.     락에 대한 정확한 분류가 존재하지 않음

2.     Enqueue Lock과 일반 Lock과 정확한 구분이 존재하지 않음

-       DML Lock

n  Row Locks (TX)

n  Table Lock (TM)

-       DDL Lock

-       Latches and Internal Locks

n  Latches

n  Intercal locks

u  Dictionary Cache locks

u  File and Log Management Locks

u  Tablespace and Rollback Segment locks

Steve Adams Lock 분류

-       Row cache Enqueues

-       Library cache locks and Pins

-       DML Locks

-       Buffer Locks

-       Sort Locks

 

Enqueue Lock : Enqueue 구조로 관리되는 Lock (10g 부터는 Wait Event로 등록 (v$event_name)

Row cache lock : shared pool Row Cache 영역을 보호하기 위해 사용 ( Row cache 메모리 영역 자체에 보유 프로세스 목록 (Owner List) 와 대기프로세스 목록(Waiter List) 를 관리) -> Row cache Lock, Library cache Lock, Library cache pin, Buffer Lock 등이 있음


 

-       Enqueue Lock

n  User Type lock : TX, TM, UL

n  System Type Lock : CF, US, CI, TC, JS, …

-       일반 Lock

n  Row cache Lock

n  Library cache Lock, Library cache pin

n  Buffer lock

 

Lock 이 보호하는 Resource

-       Latch SGA 보호 / Lock Database 전체를 보호 (Table, Transaction, undo segment, tablespace, Job

-       TM Lock Table resource 보호 (ID1=object id)

-       TX Lock Transaction Resource 보호 (ID1=USN << 16|SLOT, ID2=Sequence)

-       US Lock Undo Segment Resource 보호 (ID1=USN)

-       HW Lock (ID1=Tablespace#, iD2=DBA of Undo Segment Header)

-       Enqueue LockV$LOCKTYPE, ID1, ID2 값이 resource 구분자 역할

 

V$SESSION_WAIT

-       대기현상이 잘생하는지 관찰 가능

-       Buffer lock 경합의 경우 Buffer busy waits Read by other session 이벤트에 대한 대기현상 발생

-       Row cache lock 경합은 row cache lock Event로 확인 가능

-       Library cache lock library cache pin 에서의 경합은 library cache lock Evnet, library cache pin Event 로 관찰 가능

 


 

Lock 동작 매커니즘

1.     Lock 모드

Mode

설명

0

None

1

Null(N)

2

Sub-Shared(SS) 또는 Row-Shared(RS)

3

Sub-Exclusive(SX) 또는 Row-Exclusive(RX)

4

Shared(S)

5

Shared-Sub-Exclusive(SSX) 또는 Shared-ROW-Exclusive(SRX)

6

Exclusive(X)

 

-       Table 변경의 경우 Exclusive Mode로 획득 해야 함

-       DML 의 경우 TM LockSub Exclusive 모드로 획득

-       Sub-Exclusive의 경우 상호 호환성이 있기 때문에, 동시에 여러프로세스가 하나의 테이블에 대해 DML 작업을 수행하는 것이 허용

-       Lock Mode 호환성

 

N

SS

SX

S

SSX

X

N

O

O

O

O

O

O

SS

O

O

O

O

O

X

SX

O

O

O

X

X

X

S

O

O

X

O

X

X

SSX

O

O

X

X

X

X

X

O

 

X

X

X

X

 

Ex1) Procedure 실행하는 process Library cache pinShared mode 로 획득 해야 함.

Ex2) Procedure compile 의 경우, library cache pinExclusive mode로 획득해야 함(호환성이 없기에 library cache pin에 의한 경합이 발생)

 

2.     Lock 획득

-       Enqueue Lock 획득에 실패한 프로세스는 Enqueue resource의 대기목록(Waiter list)에 등록

(3초 마다(timeout) 스스로 깨어나서 데드락 발생 여부 확인 후 sleep 또는 락을 보유한 프로세스가 락의 사용이 끝난 후 대기 모드 프로세스를 깨워 줌)

-       enq: XX – YYYYY 이벤트를 대기

TX Lock 경합

n  enq: TX – row lock contention

n  enq: TX – allocate ITL entry

n  enq: TX – index contention

n  enq: TX – contention

이벤트가 별도로 정의

-       Row cache lock과 같은 일반 lock Enqueue Lock 과 기본적으로 같은 방식으로 동작

-       Buffer lock은 타임아웃이 1

-       역속적으로 buffer lock 획득하기 위해 대기하는 경우 3초 타임아웃

-       Row cache lock 60초까지 대기

-       Library cache lock library cache pin 3초를 대기

-       PMON 프로세스는 타임아웃이 1

-       데드락의 경우 원천적으로 Latchlevel 매커니즘에 의해 방지하지만 lock 의 경우 데드락의 가능성이 항상 존재하며,
데드락 판정이 나면 데드락을 발견한 프로세스의 락 요청은 취소되며, 전체 Transaction 이 아닌 현재 SQLrollback 된다

 

Lock 관련 Dynamic Views

-       V$LOCK 에서 Enqueue Lock 관련 정보를 확인 가능

SID

Lock 을 보유중이거나 요청 중인 Session ID

LMODE > 0 이면 Lock을 보유중인 Session 이며, Request > 0 이면 Lock 요청중인 session

Type

Enqueue Lock Resoure Type (ex – TX, TM, UL, US, CI, TC, …etc)

ID1

Resource ID 1

ID2

Resource ID 2 <TYPE-ID1-ID2>Lock이 보호하는 Resource 구분자

LMODE

Lock 을 보유하고 있는 경우의 Mode (1~6 -> Lock 모드 참조)

REQUEST

Lock 을 요청중인 경우의 Mode (1~6 -> Lock 모드 참조)

CTIME

현재의 lock mode가 허용된 시간(second) Lock을 보유하거나 요청한 이후부터의 시간

Block

현재의 Lock이 다른 Lock을 블로킹하고 있는지의 여부.
1:
다른 Lock을 블로킹 중
0 :
다른 Lock을 블로킹 안하고 있음

 

V$LOCK_OBJECT

-       현재 시스템의 모든 Transaction에 의해 획득 중인 TM Lock에 대한 정보를 제공

-       OBJECT_ID를 이용하여 object를 직접 조회할 수 있음

-       Lock 이 걸린 테이블을 조회할 때 유용

V$ENQUEUE_LOCK

-       V$LOCK과 동일하지만, 실제 Enqueue 현상-Blocking 이 발생한 경우 Waiting session 에 대한 정보만 조회

-       어떠한 session lock을 대기하고 있는지 정보만 확인 가능

 

Library cache lock

-       DBA_DDL_LOCKS, DBA_KGLLOCK, X$KGLLK를 통해 관찰이 가능

Library cache pin

-       DBA_KGLLOCK, X$KGLPN 통해서 관찰이 가능

-       122793.1 메타링크 참조

1.     System Trace 를 이용한 분석

$sqlplus '/ as sysdba'

oradebug setmypid

oradebug unlimit

oradebug dump systemstate 266

 

행 걸린 SID 를 이용하여 PID 검색

select pid from v$process where addr=

(select paddr from v$session where sid= sid번호;

 

TRACE 파일에서 아래 PID로 검색하여 wait event 확인('waiting for' 를 검색)

PROCESS 위에서 확인한 PID

 

2.     X$KGLLK 테이블을 조사

select sid,saddr from v$session where event= 'library cache lock';

 

select kgllkhdl Handle,kgllkreq Request, kglnaobj Object

from x$kgllk where kgllkses = '위에서 찾은 saddr정보'

and kgllkreq > 0

--직접 만든 join

select a.kgllkhdl Handle,a.kgllkreq Request, a.kglnaobj Object

from x$kgllk a, v$session b

where b.event='library cache lock'

and b.saddr=a.kgllkses

and a.kgllkreq > 0;

 

또는

select sid,saddr from v$session where event= 'library cache lock';

 

select kgllkses saddr,kgllkhdl handle,kgllkmod mod,kglnaobj object

from x$kgllk lock_a

where kgllkmod > 0

and exists (select lock_b.kgllkhdl from x$kgllk lock_b

where kgllkses = '위에서 찾은 saddr' /* blocked session */

and lock_a.kgllkhdl = lock_b.kgllkhdl

and kgllkreq > 0);

 

메타링크 원문


공통 상황들 

  • 테이블이 진행중인 변경(ALTER TABLE)에 의해 사용중이라면 이 테이블에 DML작업은 행이 걸리게 됩니다. 테이블의 크기나 변경이 어떤 작업(예를 들어 (수천 건의 레코드를 가지고 있는 테이블에 ALTER TABLE x MODIFY (col1 CHAR(200))) )이냐에 따라 아주 오래 락이 걸리기도 합니다.

    이런 경우, v$lock은 이 테이블 오브젝트에 DML 인큐 락(ID1이 테이블의 OBJECT_ID LMODE=6, TYPE=TM)을 가지고 'ALTER TABLE' 을 수행하고 있는 세션을 보여줄 것입니다. 이 기다리고 있는 세션은 v$lock에서 보이지 않는데 동시 접속 세션들이 많은 환경에서는 V$LOCK 정보를 이용하여 작업을 방해하고 있는 문제의 세션을 확인하기에 부족할 것입니다.
  • 어떤 사용자가 패키지에서 정의하고 있는  프로시져나 펑션을 수행중이라면 이 패키지 컴파일은 라이브러리 캐시 락 과 라이브러리 캐시 핀을 기다리게 될 것이다.

방법 1: Systemstate 분석

Systemstate 이벤트는 모든 오라클 프로세스들의 상세한 정보를 담고 있는 트레이스 파일을 생성해 줍니다. 이 정보에는 특정 프로세스에 의해 사용중이거나 요청중인 모든 자원들을 포함하고 있습니다.

어떤 작업이 행 상태에 있는 동안 새로운 세션을 열고 다음의 명령을 발행합니다:
Oracle 9.2.0.1
또는 그 이후 :

 

$sqlplus '/ as sysdba'
oradebug setmypid
oradebug unlimit
oradebug dump systemstate 266


더 오래 전 버젼은 상위 버젼에서도 수행 가능한 다음의 구문을 이용할 수 있습니다. 이벤트 level 266 9.2.0.6 이전에서는 사용할 수 없습니다.

alter session set max_dump_file_size=unlimited;
alter session set events 'immediate trace name systemstate level 10'



오라클은 USER_DUMP_DEST 디렉토리에 systemstate 트레이스 파일을 생성합니다.

행 상태에 있는 세션의 PID를 얻기 위해 :

select pid from v$process where addr=
(select paddr from v$session where sid= <sid_of_hanging_session> );

Systemstate 덤프는 각각의 프로세스별로 구분되는 정보를 담고 있습니다.
트레이스 화일을 열고 "PROCESS <위에서 확인한 PID>"를 찾습니다.
이 프로세스 부분에서 'waitinf for' 를 검색하여 지연 이벤트가 무엇인지 확인합니다.


 
PROCESS 20: 
---------------------------------------- 
SO: 0x7d2bd820, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=20, calls cur/top: 0x7d3d62d0/0x7d3d85dc, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6 
(latch info) wait_event=0 bits=0 
Process Group: DEFAULT, pseudo proc: 0x7d2ed5dc 
O/S info: user: oracle, term: pts/7, ospid: 19759 
OSD pid info: Unix process pid: 19759, image: goblin.forgotten.realms (TNS V1-V3) 

<cut> 

(session) sid: 141 trans: (nil), creator: 0x7d2bd820, flag: (41) USR/- BSY/-/-/-/-/- 
DID: 0001-0014-00000668, short-term DID: 0000-0000-00000000 
txn branch: (nil) 
oct: 6, prv: 0, sql: 0x62d01c34, psql: 0x7c20f24c, user: 542/SCOTT 
service name: SYS$USERS 
O/S info: user: oracle, term: pts/7, ospid: 19758, machine: goblin.forgotten.realms 
program: sqlplus@goblin.forgotten.realms (TNS V1-V3) 
application name: SQL*Plus, hash value=3669949024 
waiting for 'library cache lock' blocking sess=0x(nil) seq=36 wait_time=0 seconds since wait started=11 
handle address=62d064dc, lock address=79f88a68, 100*mode+namespace=c9 

  • U락이 잡힌 오브젝트의 정보를 찾기 위해 핸들 주소를 사용합니다:

 

SO: 0x79f88a68, type: 53, owner: 0x7d3d62d0, flag: INIT/-/-/0x00
LIBRARY OBJECT LOCK: lock=79f88a68 handle=62d064dc request=S
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000
htl=0x79f88ab4[0x79e71e60,0x79e71e60] htb=0x79e71e60 ssga=0x79e716fc
user=7d3a13b8 session=7d3a13b8 count=0 flags=[0000] savepoint=0xce
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0
name=SCOTT.EMPLOYEES

 

라이브러리 오브젝트 락이 공유 모드(request=S)에서 요청되었으며 그 이름이 SCOTT.EMPLOYEE임을 알 수 있습니다.

  • 같은 트레이스 파일에서 이 'handle address' 주소로 검색하여 자원에 락을 잡고 있는 프로세스가 무엇인지 찾습니다. 

PROCESS 18: 
---------------------------------------- 
SO: 0x7d2bcca8, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=18, calls cur/top: 0x79f3ab84/0x7d3d5fc8, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6 

<cut> 

SO: 0x75fe8f7c, type: 53, owner: 0x7b751914, flag: INIT/-/-/0x00 
LIBRARY OBJECT LOCK: lock=75fe8f7c handle=62d064dc mode=X 
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000 
htl=0x75fe8fc8[0x79f81790,0x79fc3ef8] htb=0x79f81790 ssga=0x79f8102c 
user=7d3988d0 session=7d3988d0 count=1 flags=[0000] savepoint=0x146e 
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0 
name=SCOTT.EMPLOYEES

 

위 결과에서 우리는 Process 18(pid)가 우리가 사용하고자 하는 오브젝트에 배타 락(mode=X)을 걸고 있는 것을 볼 수 있습니다. V$PROCESS V$SESSION을 이용하여 이 프로세스의 sid, 사용자, 터미널, 프로그램, 등을 조회해 볼 수 있습니다.

이 세션이 실행했던 실제 문장도 이 트레이스 화일에서 확인 할 수 있습니다(문장들과 다른 라이브러리 오브젝트들은 "name=" 다음에 위치합니다).

방법 2: X$KGLLK 테이블에서 조사

X$KGLLK 테이블(SYS/INTERNAL로 조회 가능)은 모든 세션들이 잡고 있거나 요청중인 모든 라이브러리 케시 오브젝트들 담고 있으며 비록 의미를 알기 어려운 열이름들이 사용되지만 V$LOCK 뷰보다 더욱 완벽한 정보를 제공합니다.

여러분은 V$SESSION에 있는 세션 주소(SADDR) 을 찾아 보고 아래의 조회를 해 봄으로써 대기중인 세션에 의해 요청된 락들을 조사할 수 있습니다:

select sid,saddr from v$session where event= 'library cache lock';

SID SADDR
---------- --------
16 572ed244


select kgllkhdl Handle,kgllkreq Request, kglnaobj Object
from x$kgllk where kgllkses = '572ed244'
and kgllkreq > 0;

HANDLE   REQUEST   OBJECT
-------- ---------- ------------------------------------------------------------
62d064dc          2 EMPLOYEES

 

이 결과는 라이브러리 캐시 락을 요청하고 있는 세션(KGLLKREQ > 0) 과 함께 락을 잡고자 하는 오브젝트의 이름중 첫 80자리를 KGLNAOBJ로 보여주고 있습니다. KGLLKHDL 의 값은 앞에서 봤던 방법 1 Systemstate 분석절차에서의 오브젝트에 대한 '핸들 주소' 에 해당됩니다.

만일 이 KGLLKHDL X$KGLLK 의 다른 세션의 핸들과 일치한다면 블로킹 세션의 주소를 알수가 있게 됩니다. 이 락을 작고 있는 세션은 락을 잡고 있기 때문에 KGLLKMOD > 0 상태를 가지고 있을 것입니다.

 

select kgllkses saddr,kgllkhdl handle,kgllkmod mod,kglnaobj object
from x$kgllk lock_a
where kgllkmod > 0
and exists (select lock_b.kgllkhdl from x$kgllk lock_b
where kgllkses = '572ed244' /* blocked session */
and lock_a.kgllkhdl = lock_b.kgllkhdl
and kgllkreq > 0);

SADDR     HANDLE   MOD
--------  -------- ----------
OBJECT
------------------------------------------------------------
572eac94  62d064dc          3
EMPLOYEES



조금 더 살펴보면, v$session 에서 KGLLKSES 과 일치하는 SADDR 를 찾아 블러킹 세션에 대한 추가적인 정보를 확인할 수 있습니다:

select sid,username,terminal,program from v$session where saddr = '572eac94'

SID        USERNAME                  TERMINAL
---------- ------------------------------ ------------------------------
PROGRAM
------------------------------------------------
12          SCOTT                          pts/20
sqlplus@goblin.forgotten.realms (TNS V1-V3)


같은 방법으로, 모든 대기 세션들을 찾을 수 있습니다

select sid,username,terminal,program from v$session
where saddr in 
(select kgllkses from x$kgllk lock_a 
 where kgllkreq > 0
 and exists (select lock_b.kgllkhdl from x$kgllk lock_b
             where kgllkses = '572eac94' /* blocking session */
             and lock_a.kgllkhdl = lock_b.kgllkhdl
             and kgllkreq = 0)
);

SID        USERNAME                       TERMINAL
---------- ------------------------------ ------------------------------
PROGRAM
------------------------------------------------
13         SCOTT                           pts/22
sqlplus@goblin.forgotten.realms (TNS V1-V3)

16         SCOTT                           pts/7
sqlplus@goblin.forgotten.realms (TNS V1-V3)

 

 

일반적인 Lock 관련 대기 이벤트

TX Lock 에 의한 대기 현상

Row cache lock

Row cache lock에 의한 경합

Buffer busy waits, read by other session

Buffer lock에 의하 경합

Library cache lock

Library cache lock에 의한 경합

Library cache pin

Library cache pin 에 의한 경합

DFS Lock handle

Global lock인 경우에 관찰

 

           V$session_wait , v$session 을 이용하여 lock 에 대한 경합을 확인 가능

 


반응형
반응형

Table 단위로 이관 요청이 있어서 쉽게 진행을 하였다.


PUMP 를 애용하는 편이라..(Enterprise 가 아니면 pump를 이용 못하거나, 주로 export를 많이 이용하라는데..쩝..)


expdp system/oracle directory=dp dumpfile=user_151120.dmp logfile=user_log.log tables=user.table1, user.tabl2....


이렇게 진행 하였다.


ftp 로 파일을 옮긴 후 IMPDP 진행


요청 받은 table 들은 truncate 로 삭제 진행

impdp system/oracle directory=dp dumpfile=user_151120.dmp logfile=user_log_imp.log content=data_only


어엇!!!에러가 발생했다.

ORA-31693: Table data object "유저명"."테이블명" failed to load/unload and is being skipped due to error:

ORA-29913: error in executing ODCIEXTTABLEOPEN callout

ORA-29400: data cartridge error

ORA-39786: Number of columns does not match between export and import database



이유

The errors occur when the ACCESS_METHOD is EXTERNAL_TABLE. This method is chosen if at least one of these conditions is met:


There is an active trigger

The table is partitioned

FGAC (Fine Grained Accesses Control) in insert mode

Referential integrity constraint exists

Unique index exists

Enabled constraint is present on pre-existing table

If any of these conditions apply, then you need to do import using DIRECT_PATH access method to solve the problem.


흠..뭐가 테이블끼리 맞지 않는 부분이 있는 듯 하다


해결방안


Follow either of the below workarounds to solve the issue:


o  Either drop the constraints/unique indexes on table before impdp is started and add access_method=direct_path to command line


- OR -


o  Rename the table before impdp, do the import and transfer the data per INSERT/SELECT to renamed table. Finally drop the imported table and rename table to old name. 


In 10g, DataPump chooses external tables for the access method to import data into a table with an unique index. On the other hand, in 11g the DataPump chooses the direct path access method even in this case. 


This issue specified in the Bug 4383811 Which has been closed as is not feasible to fix in 10g.

The ORA-39786 error is introduced (in 10.2.0.3.0) to avoid an ORA-600 error when importing data into the pre-existing table using the external tables access method.


결국은 기존 table Drop 후에 진행 하였으며, 정상적으로 해결 하였다.


기존 Table에 Trigger 가 있었으며, constraint 와 unique 를 삭제하고 재 진행할꺼면, 해당 테이블 통으로 Drop 하는 것이 편할 듯 싶었다.

버그인 부분도 있는 듯 하다.

 



반응형
반응형

아래와 같이 튜닝을 하려고 포인트를 Merge join 에 맞춰서 group by 시 해당 부분을 튜닝하려다가 

찾게 된 자료를 공유해 본다

내 자료는 아래와 같다.

서브 쿼리로 쪼개서 그 중에 하나이다.


공유 자료다.

1억건 정도의 데이터를 가진 2~3개의 테이블을 조인하여 자료를 이행하고자 하면 심각한 수행속도의 저하에 부딪히게 된다.

 

1. Join Method 의 선택 

 

대용량의 데이터라면 당연히 Hash Join 을 이용해야 한다.

해쉬조인은 해슁함수 기법을 활용하여 조인을 수행하는 방식으로 Nested Loop 조인이 가진 랜덤 액세스의 단점과 Sort Merge 조인이 가진 정렬의 부담을 해결할 수 있는 대안이다.

 

랜덤의 부담은 최악의 경우 하나의 로우를 액세스하기 위해 한 블록씩 액세스를 해야 하고, 그 블록이 아직 디스크에 위치하고 있을 수도 있다는 점이다. 정렬의 부담은 정렬처리 그 자체의 부담이라기 보다는 메모리 내에 지정한 정렬영역보다 정렬할 크기가 지나치게 큰 경우에 발생하는 기하급수적인 부담을 말한다.

 

해쉬조인의 가장 큰 장점은 조인의 연결고리의 인덱스 존재유무에 영향을 받지 않는다는 점이다.

따라서 인라인뷰를 이용한 중간집합을 만들어 가면서 집합의 연산을 통해 결과 집합을 생성해 가다보면 중간에 생성되는 집합들은 일종의 임시 테이블이라고 할 수 있으므로 당연히 인덱스를 가질 수 없다. 이러한 처리에서 해쉬조인의 가치는 크게 부각될 수 밖에 없다.

 

 

2. Hash 조인의 튜닝 포인트

 

1) Build Table 과 Probe Table 의 선택

 

해쉬 조인을 위해 먼저 액세스하여 필요한 준비를 해두는 처리를 빌드입력(Build Input) 이라 하며, 나중에 액세스하면서 조인을 수행하는 처리를 검증 혹은 검색입력(Probe Input)이라고 한다.

 

결론부터 언급하면 적은 처리 대상 집합을 가지는 Table 이 Build Table 로 선정되어야 한다.

 

처리대상 집합이 적다는 것은 테이블 사이즈가 작다는 것을 의미하지는 않는다. 테이블이 아무리 크더라도 인덱스 스캔을 통해 테이블의 3~5% 미만을 액세스한다면 이 경우는 처리 대상 집합이 적은 것이다.

 

빌드입력이 해쉬영역에 모두 위치할 수 있는 경우는 인_메모리(In_memory) 해쉬조인을 수행하게 되고, 그렇지 못한 경우에는 유예 해쉬조인을 수행하게 된다.

 

유예 해쉬조인이 수행되는 경우 해쉬 테이블은 Temp 테이블스페이스에 생성된다. Temp 테이블스페이스에 있는 해쉬 테이블이 필요시 해당 부분에 대해서 Block 단위로 액세스하게 된다.

 

참고) 해쉬조인으로 유도하기 위해서는 USE_HASH(B A) 힌트를 사용한다. 여기서 테이블 B 는 빌드 테이블이며 테이블 A 는 검증테이블을 의미한다.

 

2) Temp Tablespace 를 이용한 성능 향상

 

일반적으로 해쉬영역의 크기를 크게 할수록 Temp 테이블스페이스를 적게 사용하지만 무한정 해쉬영역을 확장할 수 없기 때문에 초대용량 데이터를 이행할 때는 해쉬 테이블이 Temp 테이블스페이스에 생성된다.

 

PGA 의 해쉬 테이블과 Temp 테이블스페이스는 Build 테이블의 처리 대상 집합의 크기에 따라 계속적인 통신을 하게 된다. 아래는 Temp 테이블스페이스의 사용을 확인하는 SQL이다.

 

SQL> SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

         FROM V$TEMPSEG_USAGE;

 

SEGTYPE : 해쉬조인을 수행할 경우 HASH 라고 표시된다.

                 SORT 라고 표현되면 SQL에서 Order by, Group by 등에 의해 Sort 를 수행하거나

                 인덱스를 생성하는 부분이다.

EXTENTS : 할당된 익스텐트의 갯수이다.

 

SQL> SELECT A.USERNAME

                     ,A.TABLESPACE

                     ,A.CONTENTS

                     ,A.SEGTYPE

                     ,A.EXTENTS                         AS USED_EXTENTS

                     ,TO_CHAR(ROUND(A.EXTENTS / B.TOTAL_EXTENTS * 100,2),'999.00') || '%'

                                                                AS USED_PCT

                    ,B.FREE_EXTENTS                 AS FREE_EXTENTS

                 ,TO_CHAR(ROUND(B.FREE_EXTENTS / B.TOTAL_EXTENTS * 100,2),'999.00') || '%'

                                                                AS FREE_PCT

                   ,B.TOTAL_EXTENTS

        FROM (SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

                   FROM V$TEMPSEG_USAGE) A

                 ,(SELECT TABLESPACE_NAME, EXTENT_SIZE, TOTAL_EXTENTS

                               ,TOTAL_BLOCKS, USED_EXTENTS, FREE_EXTENTS

                   FROM V$SORT_SEGMENT) B

        WHERE A.TABLESPACE = B.TABLESPACE_NAME

        ;

 

3) Parallel Processing 을 이용한 성능 향상

 

해쉬조인 만을 이용하는 것보다는 Parallel Processing 을 이용한 해쉬 조인은 대용량 데이터를 처리하기 위한 최적의 솔루션을 제공하고 있다.

 

/*+ USE_HASH(B A) PARALLEL(A 8) PARALLEL(B 8) */

 

4) Parameter 조정을 통한 성능 향상

 

오라클 9i 이상

 

SQL> alter system set pga_aggregate_target = 10737418240;

SQL> alter session set workarea_size_policy = auto;

SQL> alter session set hash_multiblock_io_count = 256;

 

오라클 9i 부터는 자동실행 메모리 기능을 제공하므로 PGA 공간의 크기를 각 세션별로 지정하지 않고 전체 세션이 사용하는 총 크기를 지정하기 때문에 한 세션이 PGA 크기를 전부 독차지 할 수도 있다.

 

그러나 자동실행 메모리 기능을 실제 사용해보면 오라클 9i 는 제대로 동작하지 않을 때가 많다. 즉, pga_aggregate_target 을 크게 잡아주어도 해쉬영역으로 메모리를 사용하지 못하고 Temp 테이블스페이스를 사용한다. 이는 자동실행 메모리 기능이 9i 에서 새로 추가되었기 때문에 기능이 완벽하지 못하다고 사료된다. 오라클 10g에서는 제대로 동작한다.

 

db_file_multiblock_read_count : Table Full Scan 시 해당 파라미터를 증가시킴으로써 한 번 디스크 IO에 더 많은 블록을 액세스할 수 있으므로 디스크 IO 횟수를 줄일 수 있다.

이 파라미터는 세션 레벨에서 변경 가능하다.

 

오라클 9i 이전

 

SQL> alter session set workarea_size_policy = manual;

SQL> alter session set sort_area_retained_size = 20480000;

SQL> alter session set sort_area_size = 20480000;

SQL> alter session set hash_area_size = 20480000;

SQL> alter session set hash_multiblock_io_count = 256;

SQL> alter session set db_file_multiblock_read_count = 256;

 

Hash Area Size

 

해쉬영역(Hash Area)이란 해쉬 조인을 수행하기 위해 메모리(PGA) 내에 만들어진 영역을 말한다. 이 해쉬영역이 부족하면 디스크(Temp Tablespace)를 사용하게 되어 수행속도에 지대한 영향을 미치게 된다.

 

해쉬영역은 세션별로 지정할 수 있으며 최대 PGA의 크기만큼 설정할 수 있다. 아래는 해쉬영역의 크기를 1G 로 설정한다.

 

SQL> alter session set hash_area_size = 1073741824;

 

 

3. Hash 조인으로 유도

 

1) 힌트(Hint) 사용

 

/*+ ORDERED USE_HASH(A B C) PARALLEL(A 8) PARALLEL(B 8) */

 

USE_HASH 힌트를 사용하여도 옵타마이져가 원하는 실행계획을 만들어 내지 않으면 ORDERED 힌트를 사용하여 실행계획을 고정시킬 필요가 있다. ORDERED 힌트는 쿼리 내 FROM 절의 순서대로 조인을 수행한다.

 

 

4. Hash 조인의 모니터링

 

1) V$PROCESS

 

SELECT ADDR, PID, PGA_USED_MEM

FROM V$PROCESS

;

 

해쉬 조인이 사용하는 메모리 용량을 모니터링 할 수 있다.

 

2) V$SESSION_LONGOPS

 

SELECT SID, START_TIME, TIME_REMAINING, ELAPSED_SECONDS, MESSAGE

FROM V$SESSION_LONGOPS

WHERE SID = XXX

;

 

V$SESSION_LONGOPS 는 6초 이상 수행되는 OPERATION 의 진행상황을 모니터링 할 수 있는 동적성능 뷰이다.

 

3) V$TEMPSEG_USAGE

 

SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

FROM V$TEMPSEG_USAGE

;

 

해쉬조인이 사용하는 Temp 테이블스페이스의 사용량을 모니터링할 수 있다.


원본 출처 : http://blog.daum.net/servant2342/5417565

반응형

'Oracle > DBA' 카테고리의 다른 글

[ORACLE] ASM 에 Datafile 추가  (1) 2015.11.25
[Oracle] OWI Latch & Lock 정리  (0) 2015.11.24
[Oracle] Merge 구문 1  (0) 2015.11.12
[펌] [ORACLE] SYS_CONTEXT 및 USERENV 정리  (0) 2015.09.03
특정 컬럼만 Masking  (0) 2015.09.03
반응형


Windows 서버에서 Opatch 를 진행 시


OPatch failed with error code = 74


위와 같은 에러가 발생하며 opatch 가 안되는 현상이 발생


물론 서비스도 확인 해서 이미 중지된 상태이면 아래와 같이 서비스를 확인해 볼 필요가 있다.




Distributed Transaction Coordinator


서비스를 중지한 후 다시 Opatch 진행해 보자.


Oracle Engine 와 연관이 되어 있는 듯 한데 이 부분은 좀 더 찾아 봐야 될 듯 싶다.


반응형
반응형

DB에 접속이 안되는 현상이 있다고 연락을 받아 확인하다가,

Merge 구문이 inactive 상태에서 다른 Session 을 block 하고 있는 상태를 확인하게 되었다.


Merge 구문이 실행 된 후 완료 되고 Inactive 상태로 빠지는데,

이 때 다른 Merge 구문을 block을 함으로써 lock 상태가 되었다. 그러면서 자원을 획득하지 못한

Blocked 는 inactive 상태가 되고..이렇게 트리 형태로 증가되는 부분을 확인 하였다.


이것이 왜 그런지는 조금 더 찾아 봐야겠지만 내가 본 현상과 예측은 이와 같다.


그러면 찾아보기 전에 Merge 구문에 대해서 정리부터 해본다.


너무나도 쉽다고 생각할 수 있지만 어차피 언젠가는 merge 구문 사용이 필요할 때를 대비해서 정리해 본다.

쉽게 말해서 있으면 update / 없으면 insert 를 하는 구문이다.


간단한 테스트로 진행 (타 블로그 참조 하였음)


2개의 테이블 생성


create table emp_t (no number(3), name varchar2(10), deptno number(3));

create table emps_s ( no number(3), name varchar2(10), deptno number(3));


테이터 생성


SQL> insert into emps_s values(100, 'AA', 600);

SQL> insert into emps_s values(200, 'B', 20);

SQL> insert into emps_s values(300, 'C', 30);

SQL> insert into emps_s values(210, 'D', 40);

SQL> insert into emps_s values(400,'F',50);

SQL> insert into emp_t values(100,'A',10);

SQL> insert into emp_t values(200,'B',20);

SQL> insert into emp_t values(300,'C',30);


확인


merge 구문실행


SQL> merge into emp_t t using emps_s s on (t.no=s.no)

when matched then 

update set t.name = s.name, t.deptno=s.deptno

when not matched then

insert values(s.no, s.name, s.deptno);


5 rows merged.



두 테이블의 데이터가 동일한 것을 확인 가능

commit 은 필수!!!


단, 조건절 내의 동일한 값이 있을 경우 ORA-30926 가 발생



SQL> merge into emp_t t using emps_s s on (t.no=s.no)

when matched then

update set t.name = s.name, t.deptno=s.deptno

where deptno=777   <-원하는 조건을 추가하여 가능

when not matched then

insert values(s.no, s.name, s.deptno);


플랜을 한번 확인해 보니 아래와 같이 확인이 가능하다



Hash Join 으로 풀리고, 테이블에 대해서 index 가 없으니 당연히 full scan ..

이 부분도 고려하여 index 설계를 잘 하면, merge 구문도 성능 향상을 볼 수 있을 듯 싶다.


아래는 테스트 하다가, index 타는 merge 구문을 캡쳐하여 추가한 것이다.

Index 를 이용하여 merge 구문이 실행 된 것을 확인할 수 있다.



참조 블로그

http://majesty76.tistory.com/37

반응형
반응형

업체에서 점검 중에 아래와 같은 에러 메시지를 Alert Log 에서 학인함


ORA-01652: unable to extend temp segment by 128 in tablespace TEMP



Detail

This error is fairly self explanatory - we cannot get enough space for a temporary segment. 

The size reported in the error message is the number of contiguous free Oracle blocks that cannot be found in the listed tablespace.


NOTE:

A "temp segment" is not necessarily a SORT segment in a temporary tablespace. It is also used for temporary situations while creating or dropping objects like tables and indexes in permanent tablespaces.

eg: When you perform a CREATE INDEX a TEMP segment is created to hold what will be the final permanent index data. This TEMP segment is converted to a real INDEX segment in the dictionary at the end of the CREATE INDEX operation. It remains a temp segment for the duration of the CREATE INDEX operation and so failures to extend it report ORA-1652 rather than an INDEX related space error.


그렇다면 Temp 를 사용하는 경우다..

내가 가장 많이 알고 있는게 Sort 할 경우인데, 그 외에도 아래와 같다.

(Create , Drop 할때도 생길 수 있음)


A SORT

Used for a SELECT or for DML/DDL

CREATE INDEX

The index create performs a SORT in the users default TEMP tablespace and ALSO uses a TEMP segment to build the final index in the INDEX  tablespace. Once the index build is complete the segment type is changed.

 CREATE PK CONSTRAINT

 

ENABLE CONSTRAINT

 

CREATE TABLE

New tables start out as TEMPORARY segments.
   Eg: If MINEXTENTS is > 1 or you issue CREATE table as SELECT.

Accessing a GLOBAL TEMPORARY TABLE

When you access a global temporary table a TEMP segment is instantiated to hold the temporary data.


Sort Segment 확인

-- Used_block 과 Total_block 이 같으면 temp 가 부족한 것을 확인 가능

select TABLESPACE_NAME,TOTAL_BLOCKS,USED_BLOCKS,FREE_BLOCKS from v$sort_segment; 


아래의 명령어로 현재 temp 를 누가 사용하는지 확인 가능

SELECT a.username, a.sid, a.serial#, a.osuser, b.tablespace, b.blocks, c.sql_text

FROM v$session a, v$tempseg_usage b, v$sqlarea c

WHERE a.saddr = b.session_addr

AND c.address= a.sql_address

AND c.hash_value = a.sql_hash_value

ORDER BY b.tablespace, b.blocks;



TEMP 확이

SELECT * FROM DBA_TEMP_FILES;


Trace 확인 했을 때에는 GATHER_TABLE_STATS 를 확인 하였다...

흠...테이블 단위 통계 정보 수집이면...이때도 Temp 를 쓰는가 보다..

When gathering GLOBAL statistics a large amount of TEMP space is needed in order to collect the necessary information.


해결방법


Gather the statististics at the partition level rather than the table level and derive the table level statistics from the partitions.

To do this gather using granularity => 'PARTITION'.

exec dbms_stats.gather_table_stats(ownname => '<schema name>', tabname => '<table name>', granularity => 'PARTITION');


참고로 10g 이라서 아래도 참조할 부분이다.


This new value exists in 10.2.0.5 and for 10.2.0.4 after Patch 6526370 applied (see more in Note 6526370.8 Bug 6526370 - New GRANULARITY option for DBMS_STATS statistics on the table).


해결방법


1. tempfiles을 추가, 현재 파일 사이즈를 증가하거나 혹은 auto extend를 활성화

2. 쿼리/구문을 튜닝하여 sort 작업들이 디스크가 아니라 메모리에서 수행(가장중요)


1. Temp 를 하나 더 추가 

ALTER TABLESPACE TEMP ADD TEMPFILE '/ORADATA/TEMP02.DBF' SIZE 1000M AUTOEXTEND ON;


2.기본 Temp resize 

ALTER DATABASE TEMPFILE ''/ORADATA/TEMP01.DBF'' RESIZE 2000M; 


참조oracle 문서

How Do You Find Who And What SQL Is Using Temp Segments (문서 ID 317441.1)

ORA-1652 에러에 대한 문제 해결 방안 (문서 ID 1908925.1)

RAC 환경은,  Note 280578.1


참조 사이트

http://jun3.tistory.com/26

반응형

+ Recent posts