ORACLE/Modelling2009. 2. 24. 10:09
반응형

성능 데이터 모델링의 핵심 비법

 

이춘식 | 프로젝트의 데이터베이스, 데이터 모델링, 데이터베이스 집필, 강의, 세미나, 기고

 

서울에서 부산까지 2시간 40분, 서울에서 목포까지 2시간 58분. 2004년 3월 KTX 개통으로 인해 서울에서 부산, 서울에서 목포까지 이동하는 시간이다. 시속 300km 이상의 속도를 내는 최첨단 열차인 KTX도 기존 선로를 이용할 경우 선로의 굴곡과 내구성의 특성으로 인해 시속 130km 밖에 속도를 내지 못한다. 대구에서 부산까지는 아직 KTX를 위한 선로가 완성되지 않아 기존 선로에서 운행하다보니 시간이 더 걸리고 있다. 즉, KTX는 속도를 빠르게 하는 기본 환경이 되어있어야만 시속 300km 이상의 빠른 속도를 낼 수 있다. 기존 선로에서 KTX의 성능만 향상 시켜봐야 무용지물일 뿐이다.

 

최근 많은 프로젝트에서는 데이터베이스에 대한 설계는 대충하고 구축 이후 튜닝만 하면 성능이 잘 나올 것이라는 환상을 가지고 있는 경우가 많다. 특히 SQL 구문의 실행 계획을 분석하여 실행 계획을 요리조리 바꾸어 튜닝을 하면 웬만큼 성능이 나오는 특성으로 인해 SQL 문장 튜닝으로 모든 것을 다하려고 한다.

 

데이터/트래픽 양이 많지 않고 업무가 복잡하지 않을 때는 이런 경우가 가능하겠지만 트래픽이 집중되고 데이터 양이 많으며 업무가 복잡할수록 이런 식의 튜닝으로는 성능을 향상시킬 수 없다. 개발자가 적절하게 설계되지 않은 데이터베이스에 아무리 훌륭하게 SQL 구문을 작성한다 해도 성능이 나오지 않는 것이다. 어떤 프로젝트든 개발한 프로그램에서 성능이 저하되어 문제가 발생하면 마치 죄인처럼 개발자를 바라보는 경우를 많이 본다. 그러나 근본적으로 데이터 모델이 잘못되어 개발자가 그렇게 밖에 개발할 수밖에 없어 성능이 저하되는 경우가 비일비재하다. 데이터 모델링은 수행하는 사람은 성능 저하가 나타나지 않도록 최적화된 데이터 모델을 만들어야 할 의무가 있다.

 

흔히 데이터베이스 성능을 이야기하면 SQL 문장에 대한 성능을 이야기하거나 데이터베이스 관리자(DBA)의 경우 데이터베이스 파라미터 정도로 여기는 경우가 많이 있다. 그러나 데이터베이스 설계 단계 즉, 데이터 모델링 단계에서부터 성능을 고려한 모델링을 적용하지 않는다면 구조적인 성능 문제를 가지고 있게 되어 성능개선의 한계에 부딪히는 경우가 많다. 성능 데이터 모델링이란 데이터베이스 성능 향상을 목적으로 설계 단계의 데이터 모델링 때부터 정규화, 반정규화, 테이블 통합, 테이블 분할, 조인구조, PK, FK 등 성능과 관련된 사항이 데이터 모델링에 반영될 수 있도록 하는 것으로 정의할 수 있다.

 

성능 데이터 모델링은 논리적 데이터 모델링이나 물리적 데이터 모델링과 같이 프로젝트 진행 단계에서 어떤 단계별 진행 프로세스에 포함되지는 않는다. 단, 모델링의 전체과정에서 성능과 관련된 주요한 내용이 반영되도록 해야 한다. 이번 컬럼은 필자가 국내 유수의 프로젝트를 수행하거나 진단하면서 성능과 관련된 내용만을 13개 항목으로 정리한 것이다.

 

성능에 영향을 주는 데이터 모델링의 3단락 13항목

 

데이터 모델링과 관련되어 성능에 영향을 미치는 요소는 크게 데이터 모델의 구조에 따라 성능, 대용량 데이터 특성을 고려한 성능, 인덱스 특성을 고려한 성능 향상 등이다. 여기서는 지면 관계상 13개 항목 중 중요한 6개 항목을 선정하여 살펴본다.

 

1. 데이터 모델 구조에 의한 성능 향상
- 정규화를 통한 성능 향상
- 반정규화를 통한 성능 향상
- 복잡한 데이터 모델 단순화를 통한 성능 향상

 

2. 대용량 데이터 특성을 고려한 성능 향상
- 이력 모델의 구분과 기능성 컬럼 이용으로 성능 향상
- 트랜잭션 특성에 의한 슈퍼타입/서브타입 구분에 의한 성능 향상
- 컬럼 수가 많은 테이블을 1:1 분리를 통한 성능 향상
- 대용량의 테이블은 파티셔닝을 적용한 성능 향상

 

3. 인덱스 특성을 고려한 성능 향상
- CHAR 형식에서 개발 오류 제거를 통한 성능 향상
- 일관성 있는 데이터 타입과 길이로 성능 향상
- 분산 환경 구성을 통한 성능 향상
- 효율적인 채번 방법 사용을 통한 성능 향상
- PK 순서 조정을 통한 성능 향상
- FK 인덱스 생성을 통한 성능 향상

 

정규화를 통한 성능 향상

 

일반적으로는 정규화가 잘 되어 있으면 입력, 수정, 삭제의 성능이 향상되고 반정규화를 많이 할수록 조회의 성능이 향상된다. 그러나 데이터 모델링할 때 반정규화만이 조회 성능을 향상시킨다는 고정관념은 탈피되어야 한다. 정규화를 해야만 성능을 향상시키는 경우도 빈번하기 때문이다. 정규화가 된다는 의미는 원칙적으로 데이터 간의 함수 종속성이 높다는 의미이고 데이터를 처리할 때 정규화된 속성의 집합단위로 처리될 확률도 많아진다. 또한 정규화 된 테이블을 조인하면 반드시 성능이 저하되는 것은 아니다.

 

두 개의 엔티티 타입이 통합되어 반정규화되어 성능이 저하된 경우
다음 데이터 모델의 경우를 살펴보자. 매각시간과 매각장소는 매각일자에 종속적인 2차 정규화가 안 된 데이터 모델이다. 경매에 대한 간단한 사례로 매각물건이 있으면 해당 매각물건은 특정한 날짜에 지정된 여러 장소에서 매각을 하고 매각된 내용에 대해 통계 데이터를 관리하는 데이터 모델이다. 이 업무에서는 매각일자에 따라 매각시간과 매각장소가 결정되는 중요한 속성이다. 매각일자는 대략적으로 5000건이 있고 일자별매각물건은 100만 건으로 가정하자.

 

<그림 2>의 모델에서 만약 매각장소가 ‘서울 7호’에서 매각된 총매각금액, 총유찰금액을 산출하는 조회용 SQL 문장을 작성하면 다음과 같이 작성된다.

 

 

<그림 1> 성능 데이터 모델

 

<그림 2> 성능이 저하된 반정규화 사례 - 엔티티 타입 반정규화

 

<그림 3> 성능이 저하된 반정규화 사례 - 정규화를 통한 성능 향상

 

즉 대량으로 존재하는 데이터에서 조인조건이 되는 대상을 찾기 위해 인라인뷰를 사용함으로써 성능이 저하되는 사례이다. 복합식별자 중에서 일반속성이 주식별자 속성 중 일부에만 종속 관계를 가지고 있으므로 2차 정규화의 대상이 된다. 2차 정규화를 적용하면 <그림 3>과 같은 모델이 된다.

 

2차 정규화를 적용하여 매각일자가 PK가 되고 매각시간과 매각장소가 일반속성이 되었다. 정규화를 적용함으로써 매각일자를 PK로 사용하는 매각일자별매각내역과도 관계가 연결될 수 있어 업무흐름에 따른 정확한 데이터 모델링 표기도 가능하게 되었고 드라이빙이 된 테이블이 5000건의 매각기일 테이블이 되므로 성능도 향상되었음을 알 수 있다. <그림 3>의 모델에서 만약 매각장소가 ‘서울 7호’에서 매각된 총매각금액, 총유찰금액을 산출하는 조회용 SQL문장을 작성하면 다음과 같다.

 

매각기일 테이블이 정규화가 되었고 따라서 드라이빙이 되는 대상 테이블의 데이터가 5000건이므로 빠른 조회의 성능이 나온다.

 

<그림 4> 성능이 저하된 반정규화 사례 - 속성이 중복된 경우1

 

<그림 5> 성능이 저하된 반정규화 사례 - 속성이 중복된 경우 2

 

두 개의 속성을 나열하여 반정규화하여 성능이 저하된 경우
계층형 데이터베이스를 많이 사용했던 과거 데이터 모델링의 습관에 따라 관계형 데이터베이스에서도 이와 같이 데이터 모델링을 한 경우가 많이 나타난다. 다음 사례에서 보면 모델이라고 하는 테이블에는 업무적으로 필요한 8개의 인덱스가 이미 생성되어 있는 상태이다. 데이터는 30만 건이고 온라인 환경의 데이터베이스라고 가정하자. 유형기능분류코드에 따라 데이터를 조회하는 경우가 많이 나타나 인덱스를 생성하려고 하니 유형기능분류코드 각각에 대해 인덱스를 생성해야 하므로 무려 9개나 되는 인덱스를 추가 생성해야 한다.

 

한 테이블에 인덱스가 많아지면 조회 성능은 향상되지만 데이터 입력, 수정, 삭제에 대한 성능은 저하된다. 그래서 일반 업무처리(온라인성 업무)에서는 인덱스 수를 가급적 7~8개가 넘지 않도록 하는 것이 좋다고 할 수 있다. 그런데 <그림 4>의 모델은 다른 필요한 인덱스 이외에 유형기능분류코드 속성에 해당하는 인덱스를 9개나 추가로 생성해야 하므로 실전 프로젝트에서는 어쩔 수 없이 인덱스를 생성하지 않거나 A유형기능분류코드1 하나만 인덱스를 생성하는 경우가 발생된다. 이에 따라 A유형기능분류코드1, A유형기능분류코드2, A유형기능분류코드3...을 이용하는 SQL의 성능이 저하되어 나타나는 경우가 많다. 만약 각 유형코드별로 조건을 부여하여 모델코드와 모델명을 조회하는 SQL 문장을 작성한다면 다음과 같이 작성된다.

 

 

각 유형별로 모두 인덱스가 걸려 있어야 인덱스에 의해 데이터를 찾을 수 있다. 앞의 모델은 다음과 같이 정규화를 적용해야 한다. 중복속성에 대한 분리가 1차 정규화의 정의임을 고려하면 모델 테이블은 1차정규화의 대상이 된다. 로우 단위의 대상도 1차 정규화의 대상이 되지만 컬럼 단위로 중복이 되는 경우도 1차 정규화의 대상이 된다. 따라서 모델에 대해 1차 정규화를 적용하면 다음과 같이 분리될 수 있다.

 

하나의 테이블에 9개가 반복적으로 나열되어 있을 때는 인덱스 생성이 어려웠지만 정규화되어 분리한 이후에는 인덱스 추가 생성이 0개가 되었고 또한 분리된 테이블 모델기능분류코드에서 PK인덱스를 생성하여 이용함으로 성능이 향상될 수 있다. 만약 각 유형코드별로 조건을 부여하여 모델코드와 모델명을 조회하는 SQL 문장을 작성한다면 다음과 같다.

 

 

이 SQL 구문은 유형코드+기능분류코드+모델코드에 인덱스가 걸려 있으므로 인덱스를 통해 데이터를 조회하여 성능이 향상된다. 실전 프로젝트에서도 많은 데이터 모델이 컬럼 단위에서 중복된 경우가 발견된다. 아무런 파급효과 계산 없이 무조건 컬럼 단위로 COL1, COL2, COL3... 이런 식으로 데이터 모델링을 하다가는 모델을 이용하여 개발하는 개발자에게 원성을 많이 들을 준비를 해야 한다.

 

그러므로 데이터 모델링을 전개할 때 기본적으로 정규화를 적용하도록 해야 한다. 일단 정규화를 적용한 데이터 모델을 만들고 난 이후에 업무적으로 발생시키는 트랜잭션의 성격, 분산 환경 등의 조건에 따라 반정규화를 적용하도록 해야 한다.

 

반정규화를 통한 성능 향상

 

반정규화의 목적은 당연히 조회 성능 향상이다. 정규화 규칙 1차, 2차, 3차, BCNF, 4차 정규화를 체계적으로 적용했는데 물리적인 데이터 모델을 설계할 때 적절하게 반정규화를 않으면 성능저하 현상이 나타난다. 전혀 반정규화를 적용하지 않으므로 인해 복잡한 SQL 구문이 작성되어 가독성이 떨어지며 SQL 구문의 성능이 저하되는 경우가 많이 나타난다. 따라서 실전 프로젝트에서 반정규화는 반드시 수행되어야 하는 필요한 데이터 모델링의 태스크(task)임에는 분명하나 무분별한 반정규화는 데이터 무결성을 깨뜨리는 요인이 되므로 ‘반드시 성능상 필요한 경우’에만 반정규화를 적용하도록 한다.

 

정규화가 잘 정의된 데이터 모델에서 성능이 저하된 경우 1
<그림 6>은 공급자라고 하는 엔티티 타입이 마스터이고 전화번호와 메일주소 위치가 각각 변경되는 내용이 이력형태로 관리되는 데이터 모델이다. 이 모델에서 공급자정보를 가져오는 경우를 가정해보자.

 

<그림 6> 반정규화를 통한 성능 향상 사례 1

 

<그림 7> 반정규화를 통한 성능 향상 사례 2

 

공급자와 전화번호, 메일주소, 위치는 1:M 관계이므로 한 명의 공급자당 여러 개의 전화번호, 메일주소, 위치가 존재한다. 따라서 가장 최근에 변경된 값을 가져오기 위해서는 조금 복잡한 조인이 발생될 수밖에 없다. 다음 SQL은 이와 같은 조건을 만족하는 SQL 구문이 된다.

 

 

<그림 8> 반정규화를 통한 성능 향상 사례 - 다른 서버 간 1

 

<그림 9> 반정규화를 통한 성능 향상 사례 - 다른 서버 간 2

 

꼼꼼한 독자는 이 SQL 구문을 다 이해하려고 하겠지만 대다수는 SQL 구문이 워낙 길기에 귀찮아서 이해하려 하지 않았을 것이다. 정규화된 모델이 적절하게 반정규화되지 않으면 이와 같은 복잡한 SQL 구문은 쉽게 나올 수 있다. 이른바 A4 용지 5장으로 작성된 SQL이 쉽지 않게 발견될 수 있는 것이다.

 

<그림 6>의 모델을 적절하게 반정규화를 적용하면 즉, 가장 최근에 변경된 값을 마스터에 위치시키면 다음과 같이 아주 간단한 SQL 구문이 작성된다. 앞에서 복잡하게 작성된 SQL 문장이 반정규화를 적용하므로 인해 다음과 같이 간단하게 작성이 되어 가독성도 높아지고 성능도 향상되어 나타났다.

 

결과만 보면 너무 당연하고 쉬운 것 같지만 기억해야 할 사실은 이런 내용들은 모두 실전에서 발견된 내용이라는 데 있다. 앞의 데이터 모델은 최근 값을 나타내는 기능성 컬럼을 추가하여 성능을 향상시킬 수도 있다.

 

정규화가 잘 정의된 데이터 모델에서 성능이 저하된 경우 2
업무의 영역이 커지고 다른 업무와 인터페이스가 많아짐에 따라 데이터베이스 서버가 여러 대인 경우가 있다. <그림 8>은 데이터베이스 서버가 분리되어 분산 데이터베이스가 구성되어 있을 때 반정규화를 통해 성능을 향상시킬 수 있는 경우이다.

 

서버 A에 부서와 접수 테이블이 있고 서버 B에 연계라는 테이블이 있는데 서버 B에서 데이터를 조회할 때 빈번하게 조회되는 부서번호가 서버 A에 존재하기 때문에 연계, 접수, 부서 테이블이 모두 조인이 걸리게 된다. 게다가 분산데이터베이스 환경이기 때문에 다른 서버 간에도 조인이 걸리게 되어 성능이 저하되는 것이다. 이 모델을 통해 서버 B의 연계테이블에서 부서명에 따른 연계상태코드를 가져오는 SQL 구문은 다음과 같이 작성된다.

 

 

오라클의 경우 DB LINK 조인이 발생하여 일반조인보다 성능이 저하될 것이다. 앞의 분산 환경에 따른 데이터 모델을 다음과 같이 서버 A에 있는 부서테이블의 부서명을 서버 B의 연계테이블에 부서명으로 속성 반정규화를 함으로써 조회 성능을 향상시킬 수 있다. <그림 9>의 모델에 대한 SQL 구문은 다음과 같이 작성된다.

 

 

SQL 구문도 간단해지고 분산되어 있는 서버 간에도 DB LINK 조인이 발생하지 않아 성능이 개선되었다. 데이터 모델링에서 반정규화는 속성의 반정규화만 있는 것이 아니라 테이블에 대한 반정규화(통합, 분리), 속성의 반정규화(파생 컬럼 추가, 중복 컬럼 추가, 기능성 컬럼 추가), 관계의 반정규화(중복 관계 생성)가 있다. 3가지 반정규화를 데이터 모델에 반영하여 성능을 향상시킬 수 있는 방법이 있다. 많은 사람들은 중복 속성의 반정규화만을 많이 사용하고 있으나 관계의 반정규화나 테이블의 반정규화 등을 적용하여 실전 프로젝트에서 성능 향상을 시킬 수 있음을 기억해야 한다.

 

컬럼수 많은 테이블에서 1:1 분리를 통한 성능 향상

 

프로젝트에 가보면 때론 하나의 테이블에 300개 이상의 컬럼을 가지고 있는 경우가 있다. 컴퓨터 화면 하나에는 볼 수가 없어서 스크롤을 하면서 하나의 테이블에 있는 컬럼을 구경해야 할 정도이다. 이렇게 많은 컬럼은 로우 체이닝(ROW CHAINING)과 로우 마이그레이션(ROW MIGRATION)이 많아지게 되어 성능이 저하된다.

 

로우 길이가 너무 길어서 데이터 블럭 하나에 데이터가 모두 저장되지 않고 두 개 이상의 블럭에 걸쳐 하나의 로우가 저장되어 있는 형태가 로우 체이닝 현상이다. 또한 로우 마이그레이션은 데이터 블럭에서 수정이 발생하면 수정된 데이터를 해당 데이터 블럭에서 저장하지 못하고 다른 블럭의 빈 공간을 찾아 저장하는 방식이다. 로우 체이닝과 로우 마이그레이션이 발생하여 많은 블럭에 데이터가 저장되면 데이터베이스 메모리에서 디스크와 I/O(입력/출력)가 발생할 때 불필요하게 I/O가 많이 발생하여 성능이 저하된다.

 

컬럼 수가 많음으로 인해 성능 저하
다음 모델은 도서정보라고 하는데 테이블의 컬럼 수가 아주 많이 있다. 생략된 컬럼까지 합하면 대략 200개라고 가정한다. 만약 하나의 로우의 길이가 10KB라고 하고 블럭은 2K 단위로 쪼개어 있다고 가정한다. 또한 블럭에 데이터는 모두 채워진다고 가정하면 대략 하나의 로우는 5블럭에 걸쳐 데이터가 저장될 것이다. 이 때 컬럼의 앞쪽에 위치한 발행기관명, 수량, 중간에 위치한 공고일, 발행일에 대한 정보를 가져오려면 물리적으로 컬럼의 값이 블럭에 넓게 산재되어 있어 디스크 I/O가 많이 일어나게 된다.

 

200개의 컬럼을 동시에 조회하여 화면에 보여주는 경우는 드문 사례가 될 것이다. 만약 200개의 컬럼이 가지고 있는 값을 모두 한 화면에 보여주기 위해서는 화면을 몇 번 스크롤하면서 보여야 한다. 즉 이렇게 많은 컬럼을 가지고 있는 테이블에 대해서는 트랜잭션이 발생될 때 어떤 컬럼에 대해 집중적으로 발생하는지 분석하여 테이블을 쪼개어 주면 디스크 I/O가 감소하게 되어 성능이 개선되게 된다.

 

<그림 10> 컬럼 수가 많은 테이블

 

<그림 11>의 데이터 모델을 살펴보자. 도서정보 테이블에는 전자출판 유형에 대한 트랜잭션이 독립적으로 발생되는 경우가 많이 있고 대체 제품에 대한 유형의 트랜잭션이 독립적으로 발생되는 경우가 많이 있어 1:1 관계로 분리했다. 분리된 테이블은 디스크에 적어진 컬럼이 저장되므로 로우 마이그레이션과 로우 체이닝이 많이 줄어들 수 있다. 따라서 다음과 같이 발행기관명, 수량, 중간에 위치한 공고일, 발행일을 가져오는 동일한 SQL 구문에 대해서도 디스크 I/O가 줄어들어 성능이 개선되게 된다.

 

<그림 11> 컬럼 수가 많은 테이블 1:1로 분리한 경우 1

 

많은 수의 컬럼을 가지는 데이터 모델 형식도 실전 프로젝트에서 흔히 나타나는 현상이다. 트랜잭션을 분석하여 적절하게 1:1 관계로 분리함으로써 성능을 향상할 수 있도록 해야 할 것이다.

 

일관성 있는 데이터 타입과 길이로 성능 향상

 

동일 컬럼에 데이터 타입의 길이가 맞지 않을 경우 컬럼의 형 변환이 발생하여 인덱스를 사용하지 못하는 경우가 발생하므로 반드시 일관성 있는 데이터 타입과 길이를 유지하도록 한다. 일관성 있는 데이터 타입과 길이를 지정하기 위해서는 데이터 모델링 단계에서 반드시 도메인 정의서와 용어사전을 활용하여 데이터 모델링을 전개해야 한다.

 

데이터 타입과 길이가 달라지므로 인한 성능 저하
<그림 13>의 예를 보면 장비에 대한 기본정보를 관리하는 엔티티 타입의 장비번호는 VARCHAR2(10)로 되어 있지만 이 속성을 이용하는 생산정보에서는 장비번호가 NUMBER(10)으로 되어 있다. 이 모델에서 만약 장비도입일자가 2004년 12월 1일인 장비에 대해 라인번호 당 생산건수를 산출하는 SQL구문을 만든다면 다음과 같이 작성된다.

 

 

두 속성의 데이터 타입과 길이가 다르므로 인해 원하는 결과가 나오지 않는다. 따라서 조인이 발생한 A.장비번호 = B.장비번호를 A.장비번호 = RTRIM(B.장비번호)으로 해야 결과를 도출할 수 있고 이에 따라 생산정보의 장비번호 컬럼에 인덱스가 걸려 있다고 해도 인덱스를 이용하지 못하는 현상이 발생되어 FULL TABLE SCAN이 된다.

 

<그림 14>는 SQL 구문에 RTRIM을 이용하여 실행했을 때 실행 계획이다. 인덱스 컬럼이 변형되었기 때문에 생산정보 테이블에 장비번호가 인덱스가 걸려 있어도 FULL TABLE SCAN이 발생되었다. 혹시 독자에 따라서는 ‘이렇게 간단한 오류를 누가 범하겠는가?’하고 의문을 가질 수 있다. 분명한 사실은 이렇게 데이터 타입과 길이에 대한 일관성이 유지되지 않는 경우가 실전 프로젝트에서는 아주 빈번하다는 것이다.

<그림 12> 컬럼 수가 많은 테이블 1:1로 분리한 경우 2

데이터 모델링할 때 그냥 각 속성에 데이터 타입과 길이를 직접 지정하면 앞에서와 같이 컬럼의 일관성이 결여되는 경우가 많으므로 가급적이면 도메인을 정의하여 각 속성에는 도메인을 할당하는 형식으로 데이터 모델링을 진행하는 것이 데이터 모델에 대한 일관성뿐만 아니라 데이터베이스 성능 저하도 예방하는 좋은 방법이 된다.

 

분산 환경 구성을 통한 성능 향상

 

중요 데이터 처리에 부하를 주는 배치처리/통계성업무/인터넷서비스 등은 데이터베이스 분산 환경 구성(데이터베이스 서버)을 통해 메인업무 데이터베이스 서버에 부하를 최소화하도록 배치한다.

 

인터넷 환경에서 분산 환경 구성을 통한 성능 향상
C 프로젝트에서는 네트워크 용량도 아주 우수하고 시스템의 사용도 아주 좋은 사양으로 시스템을 구성하였다. 데이터베이스 서버는 내부에서 처리하는 업무처리를 하기도 하였으며 외부 인터넷에 있는 네티즌이 데이터를 조회할 수 있도록 서비스도 오픈되어 있는 시스템이었다. 개발 프로젝트가 끝나고 한 달 정도는 아주 순조롭게 잘 사용하고 있었는데 어느 날 갑자기 KBS, MBC 등 방송국과 신문에 우리나라에 아주 편리하고 좋은 인터넷 시스템이 있다고 홍보성 기사가 나가게 되었다. 그 다음날 이전까지 아주 서비스를 잘하고 있었던 훌륭한 시스템은 바로 다운되어 버렸다. 시스템이 다운되면서 내부에서 처리하고 있는 중요한 업무까지 마비되어 비상이 된 사례가 있다.

 

<그림 13> 데이터 타입과 길이의 불일치로 인한 성능 저하 1

 

<그림 14> 데이터 타입과 길이의 불일치로 인한 성능 저하 2

 

<그림 15>는 이러한 환경을 보여주는 것이다. 인터넷 환경에서는 불특정 다수의 사람이 어느 시점에 한꺼번에 시스템에 들어와 데이터를 조회할 수 있다. 이러한 이유로 인해 업무처리 중에 자원이 부족하여 성능저하 현상이 나타날 수도 있고 중요한 업무처리 데이터와 외부에서 처리해야 하는 데이터가 공존하다 보면 데이터베이스 서버가 다운될 수 있는 위험이 너무 많이 잠재된다는 것이다.

 

인터넷에서 불특정 다수의 이용자가 서버에 접근하여 처리될 때 데이터의 수를 줄여주고 또한 인터넷 사용자에 의해 데이터베이스 서버가 다운되더라도 업무 서비스는 정상적으로 처리할 수 있도록 하기 위해 <그림 16>과 같이 데이터베이스 서버를 분리하여 구성한다.

 

인터넷 환경에 있는 사용자가 업무처리용 데이터베이스 서버에 들어오지 않으므로 안정적으로 업무처리를 할 수 있을 뿐만 아니라 자원도 모두 이용할 있어 성능도 향상될 수 있다. 이와 같은 분산구조는 계획 단계 때 결정되거나 늦어도 업무분석 단계 결정이 되어야 시스템에 적합한 하드웨어 소프트웨어를 구매하여 적용할 수 있다.

 

<그림 15> 업무 데이텁이스의 불특정 다수 트랜잭션 발생

 

<그림 16> 업무 데이터베이스의 성능 향상

 

LDAP 서버에서 사용자와 권한 관리에 따른 업무 DB에 사용자 관리 정의
LDAP은 시스템의 권한 관리를 빠르고 효율적으로 할 수 있도록 디렉토리 구조 형식으로 데이터를 가지고 있으면서 서비스하는 하나의 패키지 소프트웨어이다. 인터넷 환경에서 한 번에 로그인을 처리하는 SSO(Single Sign On)와 같은 구성을 할 때 많이 사용하는데 다른 업무 시스템과 LDAP이 구성된 시스템 간 데이터 통신이 많이 발생된다.

 

LDAP 서버에서는 보통 사용자 인증 관리인 SSO와 기타 사용자 및 조직에 대한 기본정보를 관리하고 다른 업무 데이터베이스에서 LDAP에 있는 사용자나 조직정보를 이용할 때 FROM 절에 조인이 될 수 없고 바로 건 단위로 조회를 하게 되어 성능 저하 현상이 나타 나는 경우가 많이 있다. 이와 같은 이유로 인해 가급적 사용자 정보는 업무 데이터베이스 영역에 데이터를 복제(REPLICATION)하도록 하고 그에 따라 데이터를 동기화하여 사용해야 한다.

 

<그림 17>과 비슷한 분산구성 방식인 공통코드, 기준정보, 사용자 정보와 같은 내용은 적절하게 배치를 통하거나 실시간으로 복제분산을 적용하여 성능을 향상시켜야 하는 경우에 해당된다. 이 경우도 결과만 보면 아주 당연한 데이터 아키텍처 도출같지만, 실전 프로젝트에서는 왼쪽과 같은 구성으로 성능이 저하되는 경우가 아주 많이 발견되었다.

 

<그림 17> LDAP에서 업무 DB로 사용자 정보 복제

<그림 18> PK 순서에 대한 인덱싱 생성 2

 

PK 순서조정을 통한 성능 향상

 

데이터 모델의 PK 순서가 아무런 의미가 없는 것 같지만 실전 프로젝트에서 의미 없는 PK 순서를 설계하여 성능이 저하되는 경우가 아주 빈번하다. 성능저하 현상의 많은 부분이 PK가 여러 개의 속성으로 구성된 복합식별자일 때 PK 순서에 대해 별로 고려하지 않고 데이터 모델링을 한 경우에 해당된다.

 

특히 물리적인 데이터 모델링 단계에서는 스스로 생성된 PK 순서 이외에 다른 엔티티 타입으로부터 상속받아 발생되는 PK 순서까지 항상 주의하여 표시하도록 해야 한다. PK는 해당 테이블의 데이터를 접근할 때 가장 빈번하게 사용되는 유일한 인덱스(UNIQUE INDEX)를 모두 자동 생성한다. PK 순서를 결정하는 기준은 인덱스 정렬구조를 이해한 상태에서 인덱스를 효율적으로 이용할 수 있도록 PK 순서를 지정해야 한다. 즉 인덱스의 특징은 여러 개의 속성이 하나의 인덱스로 구성되어 있을 때 앞쪽에 위치한 속성의 값이 비교자로 있어야 인덱스가 좋은 효율을 나타낼 수 있다.

 

앞쪽에 위치한 속성 값이 가급적 ‘=’ 아니면 최소한 범위 ‘BET WEEN’, ‘< >’가 들어와야 인덱스를 이용할 수 있는 것이다. 어떤 값이 들어오는지 예상을 해야 하는 특성으로 인해 데이터베이스에 발생시키는 트랜잭션의 성격을 이해하지 못하면 원활한 PK 순서를 지정할 수 없게 된다. 즉, 데이터 모델링에 참여한 사람이 정확한 프로세스의 특징을 이해하지 못한다면 PK 순서를 정확하게 지정할 수 없다는 의미이다.

 

데이터 모델링할 때 결정한 PK 순서와는 다르게 DDL 문장을 날려 PK 순서를 다르게 생성할 수도 있다. 그러나 대부분의 프로젝트에서는 데이터 모델의 PK 순서에 따라 그대로 PK를 생성한다. 만약 다르게 생성한다고 하더라도 데이터 모델과 데이터베이스 테이블의 구조가 다른 것처럼 보여 유지보수에 어려움이 많을 것이다.

 

PK 순서를 잘못 지정하여 성능이 저하된 경우(간단한 오류)
입시마스터라는 테이블의 PK는 수험번호+년도+학기로 구성되어 있고 전형과목실적 테이블은 입시마스터 테이블에서 상속받은 수험번호+년도+학기에 전형과목코드로 PK가 구성되어 있는 복합식별자 구조의 테이블이다. 입시마스터에는 200만 건의 데이터가 있고 학사는 4학기로 구성되어 있고 데이터는 5년 동안 보관되어 있다. 그러므로 한 학기당 평균 2만 건의 데이터가 있다고 가정하자. 이 테이블 구조에서 다음과 같은 SQL 구문이 실행되면 입시마스터 테이블에 있는 인덱스 입시마스터_I01을 이용할 수 있을까?

 

 

입시마스터_I01 인덱스가 수험번호+년도+학기 중 수험번호에 대한 값이 WHERE 절에 들어오지 않으므로 인해 FULL TABLE SCAN이 발생하여 즉 200만 건의 데이터를 모두 읽게 되어 성능이 저하되었다. 입시마스터 테이블에 데이터를 조회할 때 년도와 학기에 대한 내용이 빈번하게 들어오므로 <그림 18>과 같이 PK 순서를 변경함으로써 인덱스를 이용 가능하도록 할 수 있다. 그러면 생성된 인덱스가 정상적으로 이용되어 평균 2만 건의 데이터를 처리함으로써 성능이 개선된다.

 

PK 순서를 잘못 지정하여 성능이 저하된 경우(복잡한 오류)
현금출급기실적의 PK는 거래일자+사무소코드+출급기번호+명세표번호로 되어 있는데 대부분의 SQL 문장에서는 조회할 때 사무소코드가 ‘=’로 들어오고 거래일자에 대해서는 ‘BETWEEN’ 조회를 하고 있다. 이 때 SQL은 정상적으로 인덱스를 이용할 수 있지만 인덱스 효율이 떨어져 성능이 저하되는 경우에 해당된다. 해당 테이블에 발생하는 SQL은 다음과 같다.

 

 

실행 계획을 분석해 보면 인덱스가 정상적으로 이용되었기 때문에 SQL 문장은 잘 튜닝이 된 것으로 착각할 수 있다. 문제는 인덱스를 이용하기는 하는데 얼마나 효율적으로 이용하는지 검증이 필요하다. <그림 19>는 거래일자+사무소코드 순서로 인덱스를 구성한 경우와 사무소코드+거래일자 순서로 인덱스를 구성한 경우 데이터를 처리하는 범위의 차이를 보여주는 것이다. 거래일자+사무소코드로 구성된 그림을 보면 BETWEEN 비교를 한 거래일자 ‘20040701’이 인덱스의 앞에 위치하기 때문에 범위가 넓어졌고 사무소코드+거래일자로 구성된 인덱스의 경우 ‘=’비교를 한 사무소코드 ‘000368’가 인덱스 앞에 위치하여 범위가 좁아졌다.

 

그러므로 이 경우 인덱스 순서를 고려하여 데이터 모델의 PK 순서를 거래일자+사무소코드+출급기번호+명세표번호에서 사무소코드+거래일자+출급기번호+명세표번호로 수정하여 성능을 개선할 수 있다. 물론 테이블의 PK 구조를 그대로 둔 상태에서 인덱스만 하나 더 만들어도 성능은 개선될 수 있다. 이 때 이미 만들어진 PK 인덱스가 전혀 사용되지 않는다면 입력, 수정, 삭제시 불필요한 인덱스로 인해 더 성능이 저하되어 좋지 않다. 최적화된 인덱스 생성을 위해 PK 순서변경을 통한 인덱스 생성이 바람직하다.

 

<그림 19> PK 순서에 대한 인덱싱 생성4

 

PK 순서가 잘못되어 SQL 문장의 성능이 저하되는 경우가 크게 두 가지가 있는데 첫 번째는 위의 첫 번째 단순한 사례와 같이 인덱스를 이용하지 못하고 FULL TABLE SCAN하면서 성능이 저하되는 경우와 두 번째 사례와 같이 인덱스는 이용하는데 범위가 넓어져 성능이 저하되는 경우다. 보통 첫 번째 사례는 SQL의 실행 계획을 보고 쉽게 튜닝을 하는데 비해 두 번째 경우는 UNIQUE 인덱스를 이용하는데 성능이저하되는 이유로 인해 쉽게 튜닝을 하지 못하는 경우가 빈번하다. 인덱스의 정렬(SORT) 구조를 이해한 상태에서 트랜잭션의 특성에 따른 PK 구성을 하여 인덱스 범위를 최소화하는 방향으로 데이터 모델에 반영해야 한다.

 

최적의 성능을 보장하는 데이터 모델 만들기

 

성능 데이터 모델링을 요약하여 정리하면 1단계는 기본적으로 정규화를 적용하고 필요한 경우 반정규화를 테이블, 속성, 관계에 대해 적용하고 불필요한 테이블을 통합하고 전체 데이터 모델에 관계가 누락되지 않도록 해야 한다. 2단계는 대량의 데이터를 처리하는 이력 모델에는 기능성 컬럼을 추가하고, 논리적 데이터 모델의 슈퍼타입/서브타입 모델은 트랜잭션 특성에 의한 물리적 테이블로 설계하고 컬럼 수가 많은 테이블은 트랜잭션이 어떤 속성에 집중적으로 발생되는지 분석하여 1:1 분리하고 대용량의 테이블은 파티셔닝을 적용한다. 3단계는 일관성 있는 데이터 타입과 길이를 사용하며 특히 분산 환경 구성에서 적절한 데이터 분산 전략을 적용하고 일련번호 형식을 사용하는 PK 채번 방법을 LOCK을 최소화하는 구조로 선택하고 PK/FK의 순서를 적절하게 조정하도록 한다. 이 세 가지 단계를 적용하면 데이터 모델이 잘못되어 성능을 저하시킬 수 있는 요인이 거의 없다. 반드시 앞의 사상이 반영된 성능에 관해서도 최적의 데이터 모델을 만들어 기업의 핵심가치를 창출하는 데이터 아키텍트가 되기를 바란다.

 

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


반응형

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

Varchar2(8) VS Date 어느 것이 우월한가?  (0) 2009.11.03
Posted by [PineTree]
ORACLE/SQL2009. 2. 23. 20:11
반응형
A table 과  b table 를 조인하여 A table의 특정필드에 b table의 특정 필드의 값을
Update 할경우
.

update  /*+ bypass_ujvc */

  (
    SELECT
          a.colnm ra
         ,b.colnm rb   
      FROM a
         , b
     WHERE a.key= b.key
) set ra = rb;
반응형
Posted by [PineTree]
ORACLE/DataGuard2009. 2. 23. 13:08
반응형

출처 : Oracle Technology Network

 

Oracle9i Dataguard 구성 방법
2006년 1월 22일
민연홍(Oracle OCM), DBA LG카드 중형서버운영파트


미 국의 911테러 이후 전세계 IT시스템의 화두는, 자연재해 또는 테러로 인해 서비스 손실을 입게 될 경우에도 이를 복구할 수 있는 Standby 시스템을 구축하는 것이 되었다. 서버뿐만 아니라 디스크 및 백업장비까지 손실되었을 경우에도 다른 지역에서 서비스를 기동할 수 있는 시스템 구성이 각광받게 된 것이다. 이러한 Standby시스템에서 오라클의 dataguard는 데이터 무손실을 구현할 수 있는 방법으로, 한국에서는 여러 금융기관에서도 사용하고 있다. 여기서는 dataguard에 대한 간단한 소개와 그 구성방법에 대해서 알아본다.

Part 1. dataguard 개요 및 아키텍처

  1) dataguard 란 무엇인가?
  2) switchover and failover
  3) standby DB의 종류
  4) dataguard의 서비스 종류
  5) protection mode
  6) dataguard의 시스템 구성(2가지 종류)

Part 2. standby DB 기동방법

Part 3. 시스템 구축 (실습)
  1) 리스너 설정 및 기동
  2) tnsnames.ora 설정
  3) 오라클 초기화 파라미터 설정
  4) primary DB를 online backup으로 standby DB 위치로 restore
  5) primary DB에서 standby control file을 생성해서 standby DB로 전송
  6) standby DB에서 사용할 control file을 배치
  7) standby DB 기동
  8) standby DB에 standby redo log file 생성
  9) primary DB에 standby redo log file 생성
  10) standby DB를 recovery managed mode로 기동
  11) log switch 적용
  12) primary DB 점검
  13) standby DB 점검
  14) primary DB 테이블스페이스 생성 및 데이터 입력
  15) standby DB예 데이터 입력 여부 확인
  16) takeover 하기
  17) 서비스 원복(takeover)
  18) failover 하기

PartⅠ. dataguard 개요 및 아키텍처

 1) dataguard 란 무엇인가?

   - primary DB와 standby DB를 동기화시켜, primary DB가 하드웨어 장애 등의 문제가 생겼을 경우 standby DB로 failover 또는
     switchover 시킬 수 있는 시스템 구성을 말한다.
   - Oracle Net을 통해서 primary DB의 변경정보를 standby DB로 적용시켜 운영된다.

      

 2) switchover and failover

   ① 자동실행이 아니라 DBA가 action을 취해야 한다.

   ② switchover
     - OS 작업 또는 서버 PM작업 시 사용(primary -> standby , standby -> primary)

   ③ failover
     - 디스크 fail 등 긴급상황에서 사용, dataguard 재구성 필요

 3) standby DB의 종류

   ① Physical standby database
     - block 대 block 기반으로 primary DB의 redo log를 적용시켜 standby DB를 동기화

   ② Logical standby database
     - 같은 schema 정의로 공유
     - primary DB의 sql 문장을 standby DB에 적용

 4) dataguard의 서비스 종류

   ① Log transport Services
     - primary DB에서 standby DB로 redo log 정보를 자동으로 전송

   ② Log Apply Services
     - redo log를 standby DB에 적용

   ③ Role Management Service
     - 데이터베이스는 primary/standby로 두 가지의 상대적으로 배타적인 role을 가진다.
       Role Management Service는 log transport service와 log apply service를 failover 또는 switchover의 상황에 동적으로
       변경할 수 있다.

 5) protection mode

   ① Maximum Protection - primary    DB와 standby DB의 redo log를 동기화 시킨다.
      standby DB가 네트워크 이상 등의 이유로 standby로의 전송이 안될 경우 primary DB를 halt시킨다.
      데이터는 서로 동기화되어 primary DB에서 commit을 하게 되면 standby DB에서 commit이 완료될 때까지 primary DB에서 commit 완료를 하지 않는다.
      성능에는 문제를 줄 소지가 있으나 failover 상황이 오더라도 데이터 손실은 없다. physical standby DB에만 가능하다.

   ② Maximum availability - Maximum Protection과 마찬가지로 primary DB와 standby DB를 동기화시킨다.
      단, standby DB가 네트워크 문제 등의 이유로 전송이 안될지라도 halt되지는 않는다.
      데이터는 maximum protection과 마찬가지로 primary DB에서 commit을 하게 되면 standby DB에서 commit이 완료될 때까지
      primary DB에서 commit 완료를 하지 않는다. 만약 standby DB가 unavailable상태일 경우 임시로 불일치 시킨다.
      또 다시 standby DB가 available하면 자동으로 동기화 시킨다. 성능에는 문제를 줄 소지가 있으나 failover 상황이 오더라도
      데이터 손실은 거의없다. physical standby, logical standby DB 모두 가능하다.

   ③ Maximum Performance - default protection mode이다. primary data에 대한 protection이 가장 낮다.
      primary database에 transaction이 수행되면 이것을 asynchronous 하게 standby DB에 적용한다.
      즉, maximum protection, maximum availability의 경우에는 standby DB에 적용(commit) 될 때까지 primary db의 transaction 이 적용(commit)되지 않았으나,
      Maximum Performance 모드에서는 비 동기화 시키므로 primary DB에서 standby DB가 transaction 적용이 끝날 때까지
      기다리지 않는다. 즉 standby db의 문제로 인해서 primary DB에 성능영향이 가지 않는다.
      단, failover시에는 약간의 데이터 손실을 가져올 수 있다.

 6) dataguard의 시스템 구성(2가지 종류)

   ① physical standby database 구성 (LGWR process를 사용한 Physical standby DB)
      Archiving to a Physical standby Destination Using the Logwriter Proces


      


     - primary db의 LGWR 프로세스가 standby DB로 redo log를 보내고, standby DB의 RFS 프로세스가 redo log를 standby redo
      log에 적용시킨다. archiving되면 archived redo logs가 되고 이것을 MRP process가 standby DB에 적용시킨다.

   ② logical standby DB 구성
      Archiving to a Logical standby Destination Using the Logwriter Process

      

     - logical standby DB는 primary DB에서 수행된 SQL문장을 LGWR프로세스가 standby DB로 보내고 RFS 프로세스가 받아서
      Archived redo logs에 쓴다. LSP (Logical standby process)가 standby DB에 적용시킨다.

     - primary DB에서 log switch가 일어나게 되면 standby DB의 RFS 프로세스에 이를 알려주어 log switch가 되도록 한다.

TOP
PartⅡ. standby DB 기동방법

  - 주의 standby db의 startup 방식을 보면 아래와 같다. 아래 그림을 기억해두면 편하다.
    

   ① standby DB를 read only mode에서 managed recovery mode로 변경
     - 그대로 명령 또는 shutdown immediate 이후 재기동

     - 첫번째 방법

      SQL> alter database open read only;
      SQL> recover managed standby database disconnect; 

     - 두번째 방법

      SQL> shutdown immediate 
      SQL> startup nomount
      SQL> alter database mount standby database;
      SQL> recover managed standby database disconnect;

   ② shutdown 에서 managed recovery mode 로 변경

      SQL> startup nomount
      SQL> alter database mount standby database;
      SQL> recover managed standby database disconnect;

   ③ managed recovery mode 에서 read only mode 로 변경

      SQL> recover managed standby database cancel;
      SQL> alter database open read only;

   ④ read only standby DB 에서 managed recovery mode로 변경
      (먼저 standby DB에 연결된 모든 세션을 종료)

      SQL> recover managed standby database disconnect;

     - 만약 유저의 세션 때문에 실패할 경우

      SQL> shutdown immediate
      SQL> startup nomount
      SQL> alter database mount standby database;
      SQL> recover managed standby database disconnect;

TOP
PartⅢ. 시스템 구축 (실습)

  - 실습에서 사용 할 primary DB 이름은 MIN 이고, standby DB 이름은 STBY 이다.
  - 여기서는 하나의 서버에서 2개 DB를 구성하는 방법으로 수행한다.
  - 서로 다른 두 대의 서버에서도 같은 방법으로 구성 할 수 있다.
  - primary DB는 /data1/oradata/MIN에 구성되어 있다.
  - standby DB는 /data1/oradata/STBY에 구성되어 있다.

 1) 리스너 설정 및 기동

  아래와 같은 네트워크 설정을 해준다. 각 서버마다 설정해준다.
    - MIN DB에서 설정(primary DB)

vi $ORACLE_HOME/network/admin/listener.ora
smsvr1_MIN =
   (ADDRESS_LIST =
         (ADDRESS= (PROTOCOL= TCP)(Host= smsvr1)(Port=2001))
   )
SID_LIST_smsvr1_MIN =
 (SID_LIST =
   (SID_DESC =
     (ORACLE_HOME= /u/pkg/oracle/product/9.2.0)
     (SID_NAME = MIN)
   )
 )



  -STBY DB 에서 설정(physical standby DB)

vi $ORACLE_HOME/network/admin/listener.ora
smsvr1_STBY =
   (ADDRESS_LIST =
         (ADDRESS= (PROTOCOL= TCP)(Host= smsvr1)(Port=2002))
   )
SID_LIST_smsvr1_STBY =
   (SID_LIST =
    (SID_DESC =
     (ORACLE_HOME= /u/pkg/oracle/product/9.2.0)
    (SID_NAME= STBY)
   )
  )

 2) tnsnames.ora 설정

  tnsnames.ora 파일을 설정한다. 서로 네트워크가 가능하도록 하는데 이름을 재대로 써야 한다.
  초기화 파라미터에서 log_archvie_dest_2='service=STBY LGWR SYNC AFFIRM' 일 경우
  STBY는 tnsnames.ora 에서의 접속이름을 말한다.

- MIN DB 설정 primary DB에서 설정 ( standby DB로 가는 네트워크 구성)

vi $ORACLE_HOME/network/admin/tnsnames.ora
STBY =
  (DESCRIPTION =
     (ADDRESS = (PROTOCOL= TCP)(Host= smsvr1)(Port= 2002))
     (CONNECT_DATA = (SID = STBY))
  )



- STBY DB 설정, standby DB에서 설정 (primary DB로 가는 네트워크 구성)

vi $ORACLE_HOME/network/admin/tnsnames.ora
MIN=
  (DESCRIPTION =
     (ADDRESS = (PROTOCOL= TCP)(Host= smsvr1)(Port= 2001))
     (CONNECT_DATA = (SID = MIN))
  )

 3) 오라클 초기화 파라미터 설정

- MIN DB (primary DB)

vi $ORACLE_HOME/dbs/initMIN.ora

db_name=MIN
compatible=9.2.0
control_files=('/data1/oradata/MIN/control01.ctl','/data1/oradata/MIN/control02.ctl')
shared_pool_size=64M
db_cache_size=16M
undo_management=auto
background_dump_dest=/data1/oradata/MIN/bdump
user_dump_dest=/data1/oradata/MIN/udump
core_dump_dest=/data1/oradata/MIN/cdump
log_archive_start=true
log_archive_dest_1="location=/data1/oradata/MIN/archive1"
log_archive_format=%t_%s.arc

#### 데이터가드를 위해서 변경하지 말 것
remote_archive_enable=true
dg_broker_start=true
log_archive_dest_state_1=enable
log_archive_max_processes=3
standby_file_management=auto
db_file_name_convert='/data1/oradata/STBY','/data1/oradata/MIN'
log_file_name_convert='/data1/oradata/STBY','/data1/oradata/MIN'
standby_archive_dest='/data1/oradata/MIN/archive2'

##### standby DB이면 열고, primary DB이면 닫는다.
#fal_server=STBY
#fal_client=MIN
#lock_name_space=STBY

## primary DB이면 열고, standby DB이면 닫는다.
log_archive_dest_2='SERVICE=STBY LGWR SYNC'



- STBY DB (standby DB) -주의할 것은 DB이름은 MIN 이며 instance 이름과 SID는 STBY 이다.
즉, 기동을 할 때에도 ORACLE_SID=STBY 로 설정하여 기동한다.

vi $ORACLE_HOME/dbs/initSTBY.ora

db_name=MIN
compatible=9.2.0
control_files=('/data1/oradata/STBY/control01.ctl','/data1/oradata/STBY/control02.ctl')
shared_pool_size=64M
db_cache_size=16M
undo_management=auto
background_dump_dest=/data1/oradata/STBY/bdump
user_dump_dest=/data1/oradata/STBY/udump
core_dump_dest=/data1/oradata/STBY/cdump
log_archive_start=true
log_archive_dest_1="location=/data1/oradata/STBY/archive1"
log_archive_format=%t_%s.arc

### 데이터가드를 위해서 변경하지 말 것
remote_archive_enable=true
dg_broker_start=true
log_archive_dest_state_1=enable
log_archive_max_processes=3
standby_file_management=auto
db_file_name_convert='/data1/oradata/MIN','/data1/oradata/STBY'
log_file_name_convert='/data1/oradata/MIN','/data1/oradata/STBY'
standby_archive_dest='/data1/oradata/STBY/archive2'

## standby DB일 경우 아래를 열기, primary DB일 경우 닫기
fal_server=MIN
fal_client=STBY
lock_name_space=STBY

##primary DB이면 열고, standby DB이면 닫는다.
#log_archive_dest_2='SERVICE=MIN LGWR SYNC'

-초기화 파라미터 설정에서 주의해야 할 것을 먼저 보면,
standby_file_management=auto 로 되어 있어야 primary DB에서 물리적인 테이블스페이스 및 데이터파일 추가할 경우 standby DB에 자동으로 생성된다.

standby_file_management=auto로 되어 있을 경우
db_file_name_convert='/data1/oradata/STBY','/data1/oradata/MIN'

log_file_name_convert='/data1/oradata/STBY','/data1/oradata/MIN'
의 파라미터에서 ' A 부분','B 부분'에서 B부분이 자신의 primary DB의 경로를 말하고 A부분이 변환할 standby DB의 경로를 말한다. 파라미터를 확인해보자.

fal_server, fal_client 는 standby DB에서만 사용한다. fal_server는 primary DB를 설정하고 fal_client는 standby DB를 설정해둔다. 이것을 설정할 경우 primary DB와 standby DB에 redo log의 gap이 발생했을 경우 자동으로 맞추어주는 역할을 한다.
fal_server=MIN
fal_client=STBY
lock_name_space는 한 대의 서버에서 primary, standby DB를 운영할 경우 사 용한다. 앞에서 말한 바와 같이 primary , standby DB
db_name은 같으며 instance_name(SID)만 다를 뿐이다. 같은 DB이름을 가진 instance를 한 대의 서버에서 기동하기 위해서는
lock_name_space를 지정해 주어야 한다. 만약 두 대의 서버에서 구성한다면 lock_name_space파라미터는 지정할 필요가 없다.
이것은 standby DB에서만 지정한다.
lock_name_space=STBY

 4) primary DB를 online backup으로 standby DB 위치로 restore

   
<MIN DB primary DB>

- primary DB를 24시간 서비스 이므로 shutdown이 불가능한 것을 가정하에 구성한다.
- primary DB를 online backup으로 복사한다.
- online backup을 하는 것이므로 primary DB의 redo log는 standby DB로 전송하지 않는다. standby DB구성 시 자동으로
standby DB에서 redo log가 생성된다.
SQL> select tablespace_name, file_name, bytes/1024/1024 mega from dba_data_files; 
TABLESPACE_NAME FILE_NAME MEGA
------------------------------------------------------------------------------------------------------------
SYSTEM /data1/oradata/MIN/system01.dbf 250
UNDOTBS /data1/oradata/MIN/undotbs.dbf 100
USERS /data1/oradata/MIN/users01.dbf 100
SQL> select name , bytes/1024/1024 mega from v$tempfile; 
NAME MEGA
------------------------------------------------------------
/data1/oradata/MIN/temp01.dbf 100

- 여기서는 cp 명령이 standby DB로 전송하는 것을 뜻한다. ftp로 primary db의 백업을 전송한다.
   SQL> alter tablespace system begin backup;
   SQL> !cp /data1/oradata/MIN/system01.dbf /data1/oradata/STBY/system01.dbf
   SQL> alter tablespace system end backup;
   SQL> alter tablespace undotbs begin backup;
   SQL> !cp /data1/oradata/MIN/undotbs.dbf /data1/oradata/STBY/undotbs.dbf
   SQL> alter tablespace undotbs end backup;
   SQL> alter tablespace users begin backup;
   SQL> !cp /data1/oradata/MIN/users01.dbf /data1/oradata/STBY/users01.dbf
   SQL> alter tablespace users end backup;

- tempfile은 그대로 복사를 한다. begin backup, end backup 이 필요 없다. 단 tempfile 이어야 한다.
   SQL> !cp /data1/oradata/MIN/temp01.dbf /data1/oradata/STBY/temp01.dbf

 5) primary DB에서 standby control file을 생성해서 standby DB로 전송

    <MIN DB primary DB>

- primary DB에서 standby control file을 생성해서 standby DB로 전송한다
   SQL> alter database create standby controlfile as '/data1/oradata/STBY/stbyctl.ctl';

 6) standby DB에서 사용할 control file을 배치

    <STBY DB standby DB의 control file>

- standby DB에서 사용할 control file을, standby DB의 초기화 퍼라미터(initSTBY.ora)파일에 있는 control file 위치에 배치한다.
SQL> !cp /data1/oradata/STBY/stbyctl.ctl /data1/oradata/STBY/control01.ctl
SQL> !cp /data1/oradata/STBY/stbyctl.ctl /data1/oradata/STBY/control02.ctl

 7) standby DB 기동

    <STBY DB standby DB 에서 수행>

- standby DB를 기동시킨다. startup mount standby database 라는 명령은 없다. nomount까지 기동한 후 standby DB로 mount를 한다.

   SQL> startup nomount
   SQL> alter database mount standby database;

 8) standby DB에 standby redo log file 생성

    <STBY DB standby DB에서 수행>

우리는 처음으로 standby DB를 구성하였으므로 standby redo log를 추가해 주어야 한다.
여기서 중요한 것은 primary redo log와 standby redo log가 같은 크기를 가지고 있어야 한다.
만약 다를 경우에는 차후에 ORA-16139 media recovery required
에러가 발생하면서 takeover나 failover가 정상적으로 수행되지 않을 수 있다.

SQL> select * from v$logfile;

GROUP#

STATUS TYPE

MEMBER

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

1

ONLINE

/data1/oradata/STBY/log01a.log

2

ONLINE

/data1/oradata/STBY/log02a.log

3

 

/data1/oradata/STBY/log03a.log

SQL> alter database add standby logfile
           '/data1/oradata/STBY/stbylog01a.log' size 10M;
SQL> alter database add standby logfile
           '/data1/oradata/STBY/stbylog02a.log' size 10M;
SQL> alter database add standby logfile
           '/data1/oradata/STBY/stbylog03a.log' size 10M;
SQL> select * from v$logfile;

 

GROUP#STATUS

TYPE

MEMBER

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

1

ONLINE

/data1/oradata/STBY/log01a.log

2

ONLINE

/data1/oradata/STBY/log02a.log

3

ONLINE

/data1/oradata/STBY/log03a.log

4

STANDBY

/data1/oradata/STBY/stbylog01a.log

5

STANDBY

/data1/oradata/STBY/stbylog02a.log

6

STANDBY

/data1/oradata/STBY/stbylog03a.log



 9) primary DB에 standby redo log file 생성

    <MIN DB primary DB 에서 수행>

서버문제가 발생했을 경우 takeover를 해야 하므로 primary DB도 standby DB가 될 수 있기 때문에
미리 standby redo log를 만든다.

SQL> select * from v$logfile;

 

GROUP#>

STATUS TYPE

MEMBER

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

1

ONLINE

/data1/oradata/MIN/log01a.log

2

ONLINE

/data1/oradata/MIN/log02a.log

3

ONLINE

/data1/oradata/MIN/log03a.log


SQL> alter database add standby logfile
          '/data1/oradata/MIN/stbylog01a.log' size 10M;
SQL> alter database add standby logfile
          '/data1/oradata/MIN/stbylog02a.log' size 10M;
SQL> alter database add standby logfile
          '/data1/oradata/MIN/stbylog03a.log' size 10M;

SQL> select * from v$logfile;

GROUP#

STATUS TYPE

MEMBER

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

1

ONLINE

/data1/oradata/MIN/log01a.log

2

ONLINE

/data1/oradata/MIN/log02a.log

3

ONLINE

/data1/oradata/MIN/log03a.log

4

STANDBY

/data1/oradata/MIN/stbylog01a.log

5

STANDBY

/data1/oradata/MIN/stbylog02a.log

6

STANDBY

/data1/oradata/MIN/stbylog03a.log

 10) standby DB를 recovery managed mode로 기동

    <STBY DB standby DB 에서 수행>

standby DB를 recovery managed mode로 변경한다.
standby DB서버에서 MRP 프로세스가 생긴다.

   SQL> recover managed standby database disconnect;

 11) log switch 적용

    <MIN DB primary DB 에서 수행>

standby DB를 구성하는 동안 primary DB와 gap이 생겼을 것이다.
current redo log를 적용시킨다.

   SQL> alter system archive log current;

 12) primary DB 점검

            PROCESS STATUS
           ------------- ---------------
           ARCH       CLOSING
           ARCH       CLOSING
           LGWR       WRITING SQL> select dest_id "ID",destination,status,target, schedule,process,mountid mid from v$archive_dest order by dest_id;
=> destination 2번에 우리는 service=STBY로 설정하였다. STBY는 tnsnames.ora에 나오는 접속이름이었다. STATUS=VALID 상태이고 STANDBY 이어야 한다.


=> 아무런 에러도 나와서는 안된다. 여기에서 에러가 났다면 primary DB를 먼저 기동하고 standby DB를 기동했을 경우 발생할 수도 있으나, standby로 전송이 안된 것일 수도 있으므로 다른 것도 확인을 해보아야 한다. 만약 standby DB를 먼저 기동하고 recovery managed mode에서 MRP 프로세스를 띄우고 그리고 나서야 primary DB를 기동시켰다면 아래에서는 아무런 메세지도 나와서는 안된다. 예제에서는 primary DB를 먼저 기동했으므로 메세지가 발생했을 것이다.

        MESSAGE         TIMESTAMP
        --------------------------
        --------------------------- SQL> select dest_id id,database_mode db_mode,recovery_mode, protection_mode,standby_logfile_count "SRLs", standby_logfile_active ACTIVE, archived_seq# from v$archive_dest_status;
==> db_mode가 MOUNTED_STANDBY 이어야 한다. recovery_mode 가 managed가 되어 있어야 primary DB에서 전송된 redo log정보를 standby DB에 적용시킬 수 있다.

        ID DB_MODE         RECOVER PROTECTION_MODE      SRLs ACTIVE ARCHIVED_SEQ#
        --- --------------- ------- -------------------- ---- ------ -------------
       1 OPEN            IDLE    MAXIMUM PERFORMANCE     0      0        45
       2 MOUNTED-STANDBY MANAGED MAXIMUM AVAILABILITY    2      0        45
       3 OPEN            IDLE    MAXIMUM PERFORMANCE     0      0         0

13) standby DB 점검
14) primary DB 테이블스페이스 생성 및 데이터 입력
        <MIN DB primary DB>
test 테이블스페이스를 만들고 테이블을 만들고 데이터를 넣어본다. 주의할 것은 db_file_name_convert 에서 나오는 것처럼 /data1/oradata/MIN 안에만 생성을 해야 한다. 그래야 standby DB에 데이터파일이 자동으로 생기게 된다.
또한 파라미터에서 standby_file_management=auto로 되어 있어야 standby DB에 테이블스페이스의 데이터파일이 생긴다.
SQL> create tablespace test datafile '/data1/oradata/MIN/test01.dbf' size 10M; SQL> select tablespace_name, file_name, bytes/1024/1024 mega from dba_data_files;

            

15) standby DB예 데이터 입력 여부 확인 <STBY DB standby DB>
- primary DB에서 만든 테이블스페이스가 있는지 데이터는 들어갔는지 확인한다.
recovery managed mode를 해제하고 read only로 open한다.
SQL> recover managed standby database cancel; SQL> alter database open read only;
==> 정상적으로 primary DB에서 만든 테이블스페이스가 적용되었으며, test 라는 테이블에 데이터 insert가 정상적으로 된 것을 확인할 수 있다.


- 다시 recovery managed mode로 만들어서 primary 에서 전송된 redo log 정보가 standby DB에 적용되도록 한다. fal_server, fal_client 파라미터가 설정되어 있으므로 자동으로 gap이 생긴 부분을 맞추어 준다.
DB를 open 상태에서도 recovery managed mode로 변경이 가능하다.
SQL> recover managed standby database disconnect;
16) takeover
시스템 문제가 발생하였다. takeover를 수행한다.
①<MIN DB primary DB>
가 장 먼저 primary DB를 standby로 변경을 한 후 standby DB를 primary DB로 변경 해야한다. standby DB를 primary로 먼저 변경하면 primary DB가 standby DB로될 때까지 기다리게 된다.
이제 primary DB를 standby DB로 변경한 후 기존의 primary DB를shutdown 한다.
SQL> alter database commit to switchover to physical standby with session shutdown wait; SQL> shutdown immediate
② <STBY DB standby DB>
standby DB를 primary DB로 바꾸고 shutdown 한다. 유저접속은 없으므로 with session shutdown 절은 안 들어가도 된다.
SQL> alter database commit to switchover to primary; SQL> shutdown immediate
③ 파라미터를 변경한다. # 을 붙인 것을 빼거나 추가해서 설정해준다.
<MIN DB primary DB>

vi $ORACLE_HOME/dbs/initMIN.ora
<
변경전
>
#####standby DB
이면 열고, primary DB이면 닫는다
.
#fal_server=STBY
#fal_client=MIN
#lock_name_space=STBY


##primary DB
이면 열고, standby DB이면 닫는다.
log_archive_dest_2='SERVICE=STBY LGWR SYNC'

<변경후>
#####standby DB
이면 열고, primary DB이면 닫는다
.
fal_server=STBY
fal_client=MIN
lock_name_space=STBY

##primary DB이면 열고, standby DB이면 닫는다.
#log_archive_dest_2='SERVICE=STBY LGWR SYNC'


<STBY DB standby DB>
>vi $ORACLE_HOME/dbs/initSTBY.ora <변경전> ##standby 이면 열고, primary DB이면 닫는다. fal_server=MIN fal_client=STBY lock_name_space=STBY
##primary DB
이면 열고, standby DB이면 닫는다. #log_archive_dest_2='SERVICE=MIN LGWR SYNC'

<변경후>
##standby
이면 열고, primary DB이면 닫는다. #fal_server=MIN #fal_client=STBY #lock_name_space=STBY

##primary DB이면 열고, standby DB이면 닫는다. #log_archive_dest_2='SERVICE=MIN LGWR SYNC'



④ <MIN DB , new standby DB> - 새롭게 standby DB가 된 MIN DB를 recovery managed mode로 변경한다. SQL> startup nomount SQL> alter database mount standby database; SQL> recover managed standby database disconnect; SQL> select process, status from v$managed_standby; ==> MRP 프로세스 기동 확인

        PROCESS STATUS
        ---------------- ------------
        ARCH    CONNECTED
        ARCH    CONNECTED
       MRP0    WAIT_FOR_LOG
     RFS     WRITING
     RFS     ATTACHED

⑤ <STBY DB, new primary DB> - new primary DB를 기동한다. SQL> startup
- 확인하기 SQL> select i.instance_name, i.status instance_status, d.name dbname, d.database_role db_role, d.switchover_status switchover_status , d.protection_mode from v$database d, v$instance i;
=> 중요한 점검포인트 이다. TO_STANDBY 인지 확인한다.

   

(17) 서비스 원복(takeover) 다시 원복을 시킨다. STBY DB를 standby DB로 변경한 후 MIN DB를primary DB로 변경한다.

<STBY DB, new primary DB> - primary DB를 standby DB로 만들고 나서 standby DB를 primary DB로 만든다.
순서를 잊지 말자.
SQL> alter database commit to switchover to physical standby with session shutdown wait; SQL> shutdown immediate
<MIN DB new standby DB> - MIN DB를 primary DB로 변경한다. SQL> alter database commit to switchover to primary ; SQL> shutdown immediate
<MIN DB primary DB> - 초기화 파라미터를 변경한다.

vi $ORACLE_HOME/dbs/initMIN.ora
<원복시킨다>
#####standby DB이면 열고, primary DB이면 닫는다.
#fal_server=STBY
#fal_client=MIN
#lock_name_space=STBY

##primary DB이면 열고, standby DB이면 닫는다.
log_archive_dest_2='SERVICE=STBY LGWR SYNC'


<STBY DB standby DB>
vi $ORACLE_HOME/dbs/initSTBY.ora <원복시킨다> ##standby 이면 열고, primary DB이면 닫는다. fal_server=MIN fal_client=STBY lock_name_space=STBY
##primary DB
이면 열고, standby DB이면 닫는
.
#log_archive_dest_2='SERVICE=MIN LGWR SYNC'




18) failover

- primary DB가 있는 건물이 무너지고 디스크 이상으로 인해서 DB 데이터파일이 손상되었다.
standby DB를 긴급하게 기동시켜야 한다. MIN DB를 shutdown abort로 Down시키고(디스크 fail 장애),
standby DB를 primary DB로 기동시킨다.

- failover을 한 후에 시스템을 복구해서 MIN DB를 primary DB, STBY DB를 standby DB로 원래대로 구성하려면 Dataguard를 재구성 해야 한다.

즉, failover을 했다면 failover이후에 new primary DB인 STBY DB를 통해서 MIN DB를 standby DB로 구성하고
takeover 시키면 된다.

<MIN DB primary DB>
- 디스크장애상황
SQL> shutdown abort

<STBY DB standby DB>
- recovery managed mode를 해제(cancel)가 아닌 끝내도록(finish) 한다. primary DB로 변경한다.
SQL> recover managed standby database finish;
SQL> alter database commit to switchover to primary;
$ORACLE_HOME/dbs/initSTBY.ora 파일에서 primary DB로 파라미터를 설정하고 기동한다.
SQL> startup

<주의> 만약 standby DB인 STBY DB를 primary DB로 failover하던 도중 ORA-16139 media recovery required
에러가 나면서 recovery 하라고 나온다면?

이럴 경우엔 아래와 같은 명령을 사용하도록 한다.
Log stream을 standby DB에 적용하지 못한 경우에 발생할 수 있다.
이러한 사항은 여러 문제로 인해서 발생할 수 있으므로 발생했다면 오라클에 공식적으로 문의 해야한다.
아래와 같이 skip하면 skip하는 만큼의 gap을 DB에 적용하지 못할 수 있으니 주의해야 한다.
SQL> alter database recover managed standby database finish skip wait;
SQL> alter database commit to switchover to primary;
$ORACLE_HOME/dbs/initSTBY.ora 파일에서 primary DB로 파라미터를설정하고 기동한다.
SQL> startup 

 

반응형

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

DataGuard  (0) 2008.12.13
Posted by [PineTree]
ORACLE/INSTALL2009. 2. 23. 11:36
반응형

Oracle 9i 데이터베이스를 설치하기 위하여 다음 사항을 확인해야 한다.

 

1. CentOS 5.2 설치 전이라면, swap 공간을 물리 메모리의 4배로 잡아준다. 

    이미 설치하였다면 Oracle 인스턴스가 시작되기 전에 미리 할당 작업을 완료한다.

2. CentOS 5.2 가 기본적으로 X-window로 설치되어 있어야 한다. (Server-GUI 선택하면 될 듯)

3. Oracle 9i 설치를 위해 하드디스크의 사용 가능한 용량이 4GB 이상이어야 한다.

 

< 사용자 생성 및 그룹 생성 >

groupadd dba

groupadd oinstall

useradd -g oinstall -G dba oracle

passwd oracle

 

< 디렉토리 생성 >

mkdir -p /opt/oracle/product/9.2.0.4

mkdir -p /opt/oracle/oradata

chown -R oracle:oinstall /opt/oracle

chmod 755 /opt/oracle/oradata

 

< Oracle 파일 다운로드 >

http://www.oracle.com/technology/software/products/oracle9i/htdocs/linuxsoft.html

위 사이트에서 파일을 다운로드 받는다. (32bit CPU 기준이다.)

 

< 다운로드 받은 압축 파일 압축 해제 >

사이트에 명시된되로 "gunzip 파일명" 으로 압축을 해제하고,

"cpio -idmv < 파일명" 으로 최종 압축을 해제해서 "Disk1~3" 디렉토리가 생성된 것을 확인한다.

 

< 요구되는 패키지를 검사 >

rpm -q compat-db

              compat-gcc-34

              compat-gcc-34-c++

              compat-libgcc-296

              compat-libstdc++-296

              compat-libstdc++-33

              gcc

              gcc-c++

              glibc

              glibc-common

              glibc-devel

              glibc-headers

              libgcc

              make

              libXp

 

< root 계정 로그 아웃 >

이제 root 계정의 접속은 끊고, 위에서 생성한 oracle 계정으로 접속한다. (su - oracle)

참고로 oracle 인스톨 중에 root 계정이 필요하니, 필히 su - 명령어의 사용 그룹에 oracle 계정 추가!!

 

< 환경 설정 >

# vi ~oracle/.bash_profile

 

ORACLE_BASE=/opt/oracle

ORACLE_HOME=$ORACLE_BASE/920

ORACLE_SID=ORCL

LD_LIBRARY_PATH=$ORACLE_HOME/lib

PATH=$PATH$ORACLE_HOME/bin

 

export ORACLE_BASE ORACLE_HOME ORACLE_SID LD_LIBRARY_PATH

 

# source ~oracle/.bash_profile

 

< 나머지 설정_1 >

su -

# cd /usr/lib

# ln -s libstdc++-3-libc6.2-2-2.10.0.so libstdc++-libc6.1-1.so.2

 

< 패키지 다운로드 및 인스톨 >

http://oss.oracle.com/projects/compat-oracle/dist/files/RedHat/compat-libcwait-2.1-1.i386.rpm

http://oss.oracle.com/projects/compat-oracle/dist/files/RedHat/compat-oracle-rhel4-1.0-5.i386.rpm

 

rpm -ivh compat-libcwait-2.1-1.i386.rpm

rpm -ivh compat-oracle-rhel4-1.0-5.i386.rpm --nodeps

 

< 나머지 설정_2 >

su -

# cd /usr/bin

# ln -s gcc34 gcc32

 

< 나머지 설정_3 >

su -

# cd /usr/lib

# ln -s libgdbm.so.2.0.0 libdb.so.2

 

< 나머지 설정_3에서 NETCA/DBCA 실패할 경우 >

cd $ORACLE_HOME

rm JRE

ln -s $ORACLE_BASE/jre/1.3.1 JRE

cd JRE/bin

ln -s java jre

cd i386/native_threads/

ln -s java jre

9.2.0.8 패치 이전에 적용한다.

 

< oracle 설치 >

# cd /opt/oracle/Disk1

# export LANG=en

# ./runinstaller

 

1) Welcome : Next

2) Inventory Location : /oracle/oraInventoryss
3) UNIX Group Name : oinstall 
4) 루트권한으로 : /tmp/orainstRoot.sh 실행 !!
(새로운 터미널을 열고, su - 명령으로 root권한 획득 후 실행)
5) 위 명령어 실행후 : Continue
6) File Locations : 대부분 기본값 => Next
7) Available Products : Oracle9i Database 9.2.0.4.0 => Next
8) Installation Types : Enterprise Edition (2.84GB) => Next
9) Database Configuration : General Purpose => Next
10) Database Identification : ORCL(대표DB명) => Next
11) Database File Location : 대부분 기본 값 => Next
12) Database Character Set :
Choose one of the common character sets :
Korean KO16KSC5601 <== 이거선택(EUC-KR) => Next
13) Summary => Next
14) Setup Privileges
루트권한으로 : /opt/oracle/product/920/root.sh
Enter the full pathname of the local bin directory: [/usr/local/bin]: <엔터키입력>

15) 위 명령어 실행후 : OK

16) Database Configuration Assistant
SYS Password:
Confirm SYS Passwork :
SYSTEM Password :
Confirm SYSTEM Password :
위 항목 비밀번호 입력

17) Agent Configuration Assistant 가 에러가 나서 취소된다. 무시한다.

18) 완료되면 => Next
19) End of Installation => EXIT

이렇게되면. 오라클 설치가 끝나고.
에이전트 및 웹서버 시작이 된다.
기본 DB 및 리스너도 시작이 되어 있다.


반응형
Posted by [PineTree]
ORACLE/RAC2009. 2. 23. 11:22
반응형
출처 : http://kr.blog.yahoo.com/dbacool/1157

RAC(OPS) 환경하에서 양쪽 Node의 archived log file을 RMAN을 사용하여 동시에 BACKUP 받는 방법
======================================================================================

ORACLE 9i 이전 버전
-------------------

Oracle 8i까지는 다음과 같은 Script를 통하여 Backup을 받을 수 있었습니다.

1) Script Name: arch_backup.rcv

run{
allocate channel node_1 type disk connect 'system/manager@v92hp1';
allocate channel node_2 type disk connect 'system/manager@v92hp2';

backup filesperset 1
(archivelog until time 'SYSDATE' thread 1 channel node_1)
(archivelog until time 'SYSDATE' thread 2 channel node_2);

release channel node_1;
release channel node_2;

}

2) 수행 방법

$ rman target=system/manager catalog=rman_user/rmanpw cmdfile='arch_backup.rcv' log='arch_backup.log'



ORACLE 9i 이후 버전
-------------------

그러나 Oracle9i 이상부터는 Archived file backup전에 다음과 같은 설정을 먼저
해 주셔야만 합니다.

1) Configuration 설정

$ rman target=system/manager catalog=rman_user/rmanpw
RMAN> Show all;
RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 2;
RMAN> configure default device type to disk;
RMAN> configure channel 1 device type disk connect 'system/manager@v92hp1';
RMAN> configure channel 2 device type disk connect 'system/manager@v92hp2';

위 설정은 backup을 Disk에 받는 경우로 가정하고 device type을 모두 disk로 설정하였습니다.
만일 backup solution을 사용하여 tape에 받는다면 device type을 'sbt_tape'으로 변경해 주시면 됩니다

몇개의 Channel을 설정할 것인가에 따라 PARALLELISM의 값을 반드시맞춰 주어야 합니다.
이것을 맞춰주지 않으면 다음과 같은 형태의 Error가 발생하면서 다른 Node의 archive file들을 인식하지
못하게 됩니다.(실제로 Archived file들은 정상적으로 존재합니다)

RMAN-06059: expected archived log not found, lost of archived log compromises recoverability
ORA-19625: error identifying file /u01/64bit/app/oracle/product/9.2.0/admin/V92HP/arch/arch1_146.dbf
ORA-27037: unable to obtain file status
HP-UX Error: 2: No such file or directory
Additional information: 3

위 설정은 한번만 수행해 주시면 됩니다.
만일 CHANNEL을 잘못 설정하였으면 다음과 같은 명령으로 Clear 해 주시면 됩니다.

RMAN> configure channel 1 device type disk clear;


2)Archived file을 Backup 받습니다.

RMAN> run { backup
format='/u01/64bit/app/oracle/product/9.2.0/admin/V92HP/arch/%U'
archivelog all delete input;
}



ADDITIONAL INFORMATION(1)
-------------------------
RAC 환경 하에서 일부 Archived file들이 OS에서 삭제 되었을 경우 다음과 같은 명령을 통하여
validation check를 수행한 후에 backup을 수행하여 주십시요

RMAN> allocate channel for maintenance type disk connect 'system/manager@v92hp1';
RMAN> allocate channel for maintenance type disk connect 'system/manager@v92hp2';
RMAN> crosscheck archivelog all;

만약에 Configuration에서 이미 Channel을 설정해 주었다면
Channel allocation 없이 바로 crosscheck명령어를 수행해 주시면 됩니다.


ADDITIONAL INFORMATION(2)
-------------------------
Channel Configuration 설정시에 Backup FORMAT을 함께 설정하려면 다음과 같은 형태로 수행합니다.

RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 2;
RMAN> configure default device type to disk;
RMAN> configure channel 1 device type disk connect 'system/manager@v92hp1' FORMAT '/arch/bkup%t_s%s_s%p';
RMAN> configure channel 2 device type disk connect 'system/manager@v92hp2' FORMAT '/arch/bkup%t_s%s_s%p';


ADDITIONAL INFORMATION(3)
-------------------------
Tape device를 사용할 경우 device type은 'sbt_tape'을 사용합니다.

RMAN> CONFIGURE DEVICE TYPE 'SBT_TAPE' PARALLELISM 2;
RMAN> configure default device type to 'sbt_tape';
RMAN> configure channel 1 device type 'sbt_tape' connect 'system/manager@v92hp1' FORMAT 'bkup%t_s%s_s%p';
RMAN> configure channel 2 device type 'sbt_tape' connect 'system/manager@v92hp2' FORMAT 'bkup%t_s%s_s%p';
반응형
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 12. 15:45
반응형
emca
emca -config dbcontrol db -repos recreate -SID ora11g -PORT 1525 -ORACLE_HOME /u0/app/ora11g/product/11gr2/db_1 -DBCONTROL_HTTP_PORT 9999


반응형

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

유용한 DICTIONARY 뷰 ..  (0) 2009.03.06
PCTFREE, PCTUSED  (0) 2009.02.25
INSERT /*+ APPEND */ VS CTAS  (0) 2009.02.06
Query Rewrite와 MView Refresh.  (0) 2009.02.05
MView의 생성  (0) 2009.02.05
Posted by [PineTree]
OS/LINUX2009. 2. 10. 16:06
반응형
1.yum 패키지 설치

다음은 RHEL4에 yum을 설치할때 필요한 패키지들이고, 순서대로 설치하면 된다.
   1. libsqlite-3.2.1-1.i386.rpm
   2. python-elementtree-1.2.6-7.el4.rf.i386.rpm
   3. python-sqlite-0.5.0-1.2.el4.rf.i386.rpm
   4. python-urlgrabber-2.9.6-1.2.el4.rf.noarch.rpm
   5. yum-2.4.2-0.4.el4.rf.noarch.rpm

cd /etc/yum.repos.d/

vi RedHat-Base.repo

[base]
name=RedHat-$releasever - Base
baseurl=http://ftp.daum.net/centos/4.7/os/x86_64/
gpgcheck=1

#released updates
[update]
name=RedHat-$releasever - Updates
baseurl=http://ftp.daum.net/centos/4.7/updates/x86_64/
gpgcheck=1


==================================================
vi /etc/yum.conf
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
pkgpolicy=newest
distroverpkg=redhat-release
tolerant=1
exactarch=1
retries=20
obsoletes=1
gpgcheck=1

==============================================================================




안될 때

rpm --import http://ftp.daum.net/centos/RPM-GPG-KEY-CentOS-4

yum list

반응형

'OS > LINUX' 카테고리의 다른 글

LINUX SWAP파일 추가하기  (0) 2009.09.07
Linux 성능 조정 - tcp  (0) 2009.03.13
LINUX 해킹당했을 때 대처요령  (0) 2008.11.17
RPM src install  (0) 2008.06.24
rpm 아키택쳐 버젼까지 확인방법  (0) 2008.05.31
Posted by [PineTree]
ORACLE/TUNING2009. 2. 9. 23:01
반응형

DUAL에 통계정보가 일반적으로 없는 8i와 9i에서 DUAL 테이블의 UNION ALL 혹은 UNION 의 실행계획에서 cardinality가 1이 아닌 것으로 계산되어 Cost가 높게 계산되는 CBO 버그에 대해서 테스트해봤다..

 

 

-- 다음과 같이 여러가지 경우의 DUAL UNION (ALL) DUAL에 대해 10053 trace를 수행함.
alter session set db_file_multiblock_read_count=32;
alter session set events '10053 trace name context forever,level 1';

 

-- 8.1.7.4는 UNION ALL과 UNION 이 동일하게 card=41임.

-- Block의 수는 1개로 인식됨.

 

Oracle8i Enterprise Edition Release 8.1.7.4.0 - 64bit Production

DB_FILE_MULTIBLOCK_READ_COUNT = 32

QUERY
SELECT /*+ all_rows */ 1 FROM DUAL UNION ALL SELECT 2 FROM DUAL


***************************************
BASE STATISTICAL INFORMATION
***********************
Table stats    Table: DUAL   Alias: DUAL
  TOTAL ::  (NOT ANALYZED)    CDN: 41  NBLKS:  1  TABLE_SCAN_CST: 1  AVG_ROW_LEN:  100
***************************************
SINGLE TABLE ACCESS PATH
  TABLE: DUAL     ORIG CDN: 41  CMPTD CDN: 41
  Access path: tsc  Resc:  1  Resp:  1
  BEST_CST: 1.00  PATH: 2  Degree:  1
***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***********************
Join order[1]: DUAL [DUAL]
Best so far: TABLE#: 0  CST:          1  CDN:         41  BYTES:          0
Final:
  CST: 1  CDN: 41  RSC: 1  RSP: 1  BYTES: 0

 


-- 9.2.0.7은 UNION ALL과 UNION, all_rows와 first_rows_1에 따라 다른 결과
-- first_rows_1/UNION ALL인 경우에만 card=1 이고 나머지 경우는 모두 4072임.

-- 4072건으로 인식되는 경우 블럭수가 100개로 인식되는 Case도 있음.
-- 특이사항) 본문에는 없지만 테스트결과
--           first_rows_10이면 card=10, first_rows_100이면 card=100, first_rows_1000이면 card=1000 임.

-- ** 9i에서 dynamic_sampling(2) 힌트를 사용하면 정상적으로 card=1 의 결과를 얻을 수 있다.

 

-- 1. all_rows/UNION ALL

Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production

DB_FILE_MULTIBLOCK_READ_COUNT = 32

QUERY
SELECT /*+ all_rows */ 1 FROM DUAL UNION ALL SELECT 2 FROM DUAL

***************************************
BASE STATISTICAL INFORMATION
***********************
Table stats    Table: DUAL   Alias: DUAL
  TOTAL ::  (NOT ANALYZED)    CDN: 4072  NBLKS:  100  AVG_ROW_LEN:  100
_OPTIMIZER_PERCENT_PARALLEL = 0
***************************************
SINGLE TABLE ACCESS PATH
  TABLE: DUAL     ORIG CDN: 4072  ROUNDED CDN: 4072  CMPTD CDN: 4072
  Access path: tsc  Resc:  8  Resp:  8
  BEST_CST: 8.00  PATH: 2  Degree:  1
***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***********************
Join order[1]:  DUAL[DUAL]#0
Best so far: TABLE#: 0  CST:          8  CDN:       4072  BYTES:          0
Final - All Rows Plan:
  JOIN ORDER: 1
  CST: 8  CDN: 4072  RSC: 8  RSP: 8  BYTES: 0
  IO-RSC: 8  IO-RSP: 8  CPU-RSC: 0  CPU-RSP: 0

 

-- 2. first_rows_1/UNION ALL

QUERY
SELECT /*+ first_rows(1) */ 4 C FROM DUAL UNION ALL SELECT /*+ first_rows(1) */ 6 C FROM DUAL

-- 2.1 case 1
***************************************
BASE STATISTICAL INFORMATION
***********************
Table stats    Table: DUAL   Alias: DUAL
  TOTAL ::  (NOT ANALYZED)    CDN: 4072  NBLKS:  100  AVG_ROW_LEN:  100
_OPTIMIZER_PERCENT_PARALLEL = 0
***************************************
SINGLE TABLE ACCESS PATH
  TABLE: DUAL     ORIG CDN: 4072  ROUNDED CDN: 4072  CMPTD CDN: 4072
  Access path: tsc  Resc:  8  Resp:  8
  BEST_CST: 8.00  PATH: 2  Degree:  1

-- 2.2 case 2
***************************************
SINGLE TABLE ACCESS PATH (First K Rows)
  TABLE: DUAL     ORIG CDN: 1  ROUNDED CDN: 1  CMPTD CDN: 1
  Access path: tsc  Resc:  2  Resp:  2
  BEST_CST: 2.00  PATH: 2  Degree:  1
***********************

-- 2.3 final Decision
***********************
Join order[1]:  DUAL[DUAL]#0
Best so far: TABLE#: 0  CST:          2  CDN:          1  BYTES:          0
Final - First K Rows Plan:
  JOIN ORDER: 1
  CST: 2  CDN: 1  RSC: 2  RSP: 2  BYTES: 0
  IO-RSC: 2  IO-RSP: 2  CPU-RSC: 0  CPU-RSP: 0
  First K Rows Plan


--3. all_rows/UNION

QUERY
SELECT /*+ all_rows */ 6 C FROM DUAL UNION  SELECT 7 C FROM DUAL

***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***********************
Join order[1]:  DUAL[DUAL]#0
Best so far: TABLE#: 0  CST:          8  CDN:       4072  BYTES:          0
    SORT resource      Sort statistics
      Sort width:            3 Area size:       43008 Max Area size:       43008   Degree: 1
      Blocks to Sort:       10 Row size:           10 Rows:       4072
      Initial runs:          1 Merge passes:        1 IO Cost / pass:         14
      Total IO sort cost: 12
      Total CPU sort cost: 0
      Total Temp space used: 0
Final - All Rows Plan:
  JOIN ORDER: 1
  CST: 20  CDN: 4072  RSC: 20  RSP: 20  BYTES: 0
  IO-RSC: 20  IO-RSP: 20  CPU-RSC: 0  CPU-RSP: 0


--4. first_rows_1/UNION

-- UNION은 SORT OPERATION이 수행되므로 이 경우 CBO는 'All Rows Plan'만 고려되었음.

QUERY
SELECT /*+ first_rows(1) */ 8 C FROM DUAL UNION SELECT /*+ first_rows(1) */ 9 C FROM DUAL

***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***********************
Join order[1]:  DUAL[DUAL]#0
Best so far: TABLE#: 0  CST:          8  CDN:       4072  BYTES:          0
    SORT resource      Sort statistics
      Sort width:            3 Area size:       43008 Max Area size:       43008   Degree: 1
      Blocks to Sort:       10 Row size:           10 Rows:       4072
      Initial runs:          1 Merge passes:        1 IO Cost / pass:         14
      Total IO sort cost: 12
      Total CPU sort cost: 0
      Total Temp space used: 0
Final - All Rows Plan:
  JOIN ORDER: 1
  CST: 20  CDN: 4072  RSC: 20  RSP: 20  BYTES: 0
  IO-RSC: 20  IO-RSP: 20  CPU-RSC: 0  CPU-RSP: 0

 

 

-- 10.2.0.3 (FAST DUAL)

-- optimizer_mode, union all 혹은 union, _optimizer_cost_model=(io,cpu) 에 관계없이 모두 card=1
-- (dual의 통계정보 존재 여부와도 상관 없음)
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production

****************
QUERY BLOCK TEXT
****************
SELECT 1 FROM DUAL
*********************
QUERY BLOCK SIGNATURE
*********************
qb name was generated
signature (optimizer): qb_name=SEL$2 nbfros=1 flg=0
  fro(0): flg=0 objn=258 hint_alias="DUAL"@"SEL$2"
*****************************
SYSTEM STATISTICS INFORMATION
*****************************
  Using WORKLOAD Stats
  CPUSPEED: 1023 millions instructions/sec
  SREADTIM: 1 milliseconds
  MREADTIM: 1 millisecons
  MBRC: 16.000000 blocks
  MAXTHR: 525863936 bytes/sec
  SLAVETHR: 3824640 bytes/sec
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
  Table: DUAL  Alias: DUAL
    #Rows: 1  #Blks:  1  AvgRowLen:  2.00
***************************************
SINGLE TABLE ACCESS PATH
  Table: DUAL  Alias: DUAL    
    Card: Original: 1  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
  Access Path: TableScan
    Cost:  2.01  Resp: 2.01  Degree: 0
      Cost_io: 2.00  Cost_cpu: 7271
      Resp_io: 2.00  Resp_cpu: 7271
  Best:: AccessPath: TableScan
         Cost: 2.01  Degree: 1  Resp: 2.01  Card: 1.00  Bytes: 0
***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***************************************
Considering cardinality-based initial join order.
Permutations for Starting Table :0
***********************
Join order[1]:  DUAL[DUAL]#0
***********************
Best so far: Table#: 0  cost: 2.0065  card: 1.0000  bytes: 0
(newjo-stop-1) k:0, spcnt:0, perm:1, maxperm:80000
*********************************
Number of join permutations tried: 1
*********************************
Final - All Rows Plan:  Best join order: 1
  Cost: 2.0065  Degree: 1  Card: 1.0000  Bytes: 0
  Resc: 2.0065  Resc_io: 2.0000  Resc_cpu: 7271
  Resp: 2.0065  Resp_io: 2.0000  Resc_cpu: 7271


반응형

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

SQL Trace와 TKPROF 유틸리티  (0) 2009.03.19
통계정보의 이해  (0) 2009.03.03
Oracle 10g에서 Index 힌트의 변화  (0) 2009.02.09
ORACLE HINT 정리  (0) 2009.02.09
DML의 INSERT 성능 향상  (0) 2009.02.09
Posted by [PineTree]
ORACLE/TUNING2009. 2. 9. 22:46
반응형
전통적으로 index 힌트를 사용하는 방법은 다음과 같다.

select /*+ index(t_index t_index_idx1) */ count(*)
from t_index
where c1 > 0 and c2 > 0;


이 방식의 한 가지 단점은 Index 이름이 변경되는 경우에는 해당 인덱스를 사용하지 못할 수도 있다는 것이다. Oracle 10g에서는 다음과 같은 새로운 Syntax가 추가되었다.

select /*+ index(t_index t_index(c1)) */ count(*)
from t_index
where c1 > 0 and c2 > 0;


즉, index 이름 대신 Index를 구성하는 컬럼명을 사용할 수 있다. 다중 컬럼 인덱스인 경우에는 /*+ index(t_index t_index(c1,c2,c3)) */ 와 같이 사용할 수 있다.

Index의 이름이 변경될 때의 피해도 줄일수 있고, 힌트도 훨씬 명확해지는 장점이 있다. 어떤 컬럼을 사용하는 인덱스인지 힌트를 보고 바로 알 수 있다.

10.2.0.3 버전에서는 아래와 같은 힌트가 추가되었다.

    * index_rs
    * index_rs_asc
    * index_rs_desc

Index range scan 전용 힌트가 추가된 셈이다. Optimizer의 일부 문제로 인해 Index 힌트를 사용하는 경우 index range scan이 효율적임에도 불구하고 index full scan(index fast full scan과 헷갈리면 안됨!!)이 선택되는 문제가 발견되었다. 그래서 이런 문제를 원천적으로 해결할 수 있도록 새로운 힌트가 추가된 것이다.

10g 사용자라면 이러한 새로운 힌트를 사용함으로써 index 힌트 사용에서 오는 일부 껄끄러운 문제를 손쉽게 해결할 수 있을 듯하다.
반응형
Posted by [PineTree]
ORACLE/TUNING2009. 2. 9. 21:36
반응형

/*+ ALL_ROWS */
explicitly chooses the cost-based approach to optimize a statement
block with a goal of best throughput (that is, minimum
total resource consumption) 

전체 RESOURCE 소비를 최소화 시키기 위한 힌트.
             Cost-Based 접근방식.


 


/*+ CHOOSE */
causes the optimizer to choose between the rule-based
approach and the cost-based approach for a SQL statement
based on the presence of statistics for the tables accessed by
the statement 
             Acess되는 테이블에 통계치 존재여부에 따라
             Optimizer로 하여금 Rule-Based Approach와 Cost-Based Approach
             중 하나를 선택할수 있게 한다.
             Data Dictionary가 해당테이블에 대해 통계정보를 가지고 있다면
             Optimizer는 Cost-Based Approach를 선택하고,
             그렇지 않다면 Rule-Based Approach를 선택한다.



/*+ FIRST_ROWS */
explicitly chooses the cost-based approach to optimize a statement
block with a goal of best response time (minimum
resource usage to return first row)
가장 좋은 응답 시간의 목표로 문 블록을 최적화하기 위해 cost-based 접근
방법을 선택합니다. (첫번째 행을 되돌려 주는 최소의 자원 사용)

/*+ RULE */
explicitly chooses rule-based optimization for a statement
block 
  Rule-Based 최적화를 사용하기위해.

/*+ AND_EQUAL(table index) */
explicitly chooses an execution plan that uses an access path
that merges the scans on several single-column indexes 

 single-column index의 merge를 이용한 access path 선택.
             적어도 두개이상의 index가 지정되어야한다.


/*+ CLUSTER(table) */
explicitly chooses a cluster scan to access the specified table 
  지정된 테이블Access에 Cluster Scan 유도.
             Cluster된 Objects에만 적용가능.


/*+ FULL(table) */
explicitly chooses a full table scan for the specified table 
해당테이블의 Full Table Scan을 유도.


/*+ HASH(table) */
explicitly chooses a hash scan to access the specified table 
지정된 테이블Access에 HASH Scan 유도


/*+ HASH_AJ(table) */
transforms a NOT IN subquery into a hash antijoin to access
the specified table 

NOT IN SubQuery 를 HASH anti-join으로 변형


/*+ HASH_SJ (table) */
transforms a NOT IN subquery into a hash anti-join to access
the specified table 

 correlated Exists SubQuery 를 HASH semi-join으로 변형



/*+ INDEX(table index) */
explicitly chooses an index scan for the specified table
그 명시된 테이블을 위하여, 색인 scan을 고르는

/*+ INDEX_ASC(table index) */
explicitly chooses an ascending-range index scan for the specified
table 

INDEX HINT와 동일 단,ASCENDING 으로 SCAN함을 확실히 하기위함.



/*+ INDEX_COMBINE(table index) */
If no indexes are given as arguments for the INDEX_COMBINE
hint, the optimizer uses whatever Boolean combination
of bitmap indexes has the best cost estimate. If particular
indexes are given as arguments, the optimizer tries to use
some Boolean combination of those particular bitmap indexes. 

 INDEX명이 주어지지 않으면 OPTIMIZER는 해당 테이블의
             best cost 로 선택된 Boolean combination index 를 사용한다.
             index 명이 주어지면 주어진 특정 bitmap index 의
             boolean combination 의 사용을 시도한다.



 



/*+ INDEX_DESC(table index) */
explicitly chooses a descending-range index scan for the specified
table 
 지정된 테이블의 지정된 index를 이용 descending으로 scan
             하고자할때 사용.


/*+ INDEX_FFS(table index) */
causes a fast full index scan to be performed rather than a full
table scan 

 full table scan보다 빠른 full index scan을 유도.


/*+ MERGE_AJ (table) */
transforms a NOT IN subquery into a merge anti-join to access
the specified table 

 not in subquery를 merge anti-join으로 변형



/*+ MERGE_SJ (table) */
transforms a correlated EXISTS subquery into a merge semi-join
to access the specified table 

correalted EXISTS subquery를 merge semi-join으로 변형



/*+ ROWID(table) */
explicitly chooses a table scan by ROWID for the specified
table 

지정된 테이블의 ROWID를 이용한 Scan 유도


/*+ USE_CONCAT */
forces combined OR conditions in the WHERE clause of a
query to be transformed into a compound query using the
UNION ALL set operator 

 조건절의 OR 를 Union ALL 형식으로 변형한다.
             일반적으로 변형은 비용측면에서 효율적일때만 일어난다.




/*+ ORDERED */
causes Oracle to join tables in the order in which they appear
in the FROM clause 

from절에 기술된 테이블 순서대로 join이 일어나도록 유도.



/*+ STAR */
forces the large table to be joined last using a nested-loops join
on the index 

 STAR QUERY PLAN이 사용가능하다면 이를 이용하기위한 HINT.
             STAR PLAN은 규모가 가장큰 테이블이 QUERY에서 JOIN ORDER상
             마지막으로 위치하게 하고 NESTED LOOP 으로 JOIN이 일어나도록
             유도한다.
             적어도 3개 테이블 이상이 조인에 참여해야하며 LARGE TABLE의
             CONCATENATED INDEX는 최소 3컬럼 이상을 INDEX에 포함해야한다.
             테이블이 ANALYZE 되어 있다면 OPTIMIZER가 가장효율적인 STAR PLAN을
             선택한다.    





/*+ DRIVING_SITE (table) */
forces query execution to be done at a different site from that
selected by Oracle 

QUERY의 실행이 ORACLE에 의해 선택된 SITE가 아닌 다른 SITE에서
             일어나도록 유도.


/*+ USE_HASH (table) */
causes Oracle to join each specified table with another row
source with a hash join 

각 테이블간 HASH JOIN이 일어나도록 유도.



/*+ USE_MERGE (table) */
causes Oracle to join each specified table with another row
source with a sort-merge join 

지정된 테이블들의 조인이 SORT-MERGE형식으로 일어나도록 유도.



/*+ USE_NL (table) */
causes Oracle to join each specified table to another row
source with a nested-loops join using the specified table as the
inner table 

테이블의 JOIN 시 테이블의 각 ROW가 INNER 테이블을 NESTED LOOP
             형식으로 JOIN 한다.

.



/*+ APPEND */ , /*+ NOAPPEND */
specifies that data is simply appended (or not) to a table; existing
free space is not used. Use these hints only following the
INSERT keyword.
데이타가 테이블로 단순히 덧붙여진다는 (or not)것 명시합니다; 무료인
현존하는 영역은 사용되지 않습니다.
단지 그 삽입 키 핵심어를 따르는 이 암시를 사용하시오.

/*+ NOPARALLEL(table) */
disables parallel scanning of a table, even if the table was created
with a PARALLEL clause
그 테이블이 PARALLEL 문절로 새로 만들어졌다면 테이블의 평행  순차 검색을
사용하지 않게 함


/*+ PARALLEL(table, instances) */
allows you to specify the desired number of concurrent slave
processes that can be used for the operation.
DELETE, INSERT, and UPDATE operations are considered for
parallelization only if the session is in a PARALLEL DML
enabled mode. (Use ALTER SESSION PARALLEL DML to
enter this mode.)
PARALLEL hint를 사용하면 query에 포함된 table의 degree를 설정할 수 있다.
예를 들어, 다음과 같이 hint를 적어 degree 4로 parallel query option을
실행하도록 할 수 있다.
이 때 parallel이란 글자와 괄호( '(' )사이에 blank를 넣지 않도록 한다.
select /*+ PARALLEL(emp, 4) */ * from emp; 
 
 

/*+ PARALLEL_INDEX
allows you to parallelize fast full index scan for partitioned
and nonpartitioned indexes that have the PARALLEL attribute
parallelize에 당신에게 빠른 가득한 색인 scan을 허락합니다. 그런데,
그것은 PARALLEL 속성을 가지고 있는 색인을 분할했고 nonpartitioned했습니다.

/*+ NOPARALLEL_INDEX */
overrides a PARALLEL attribute setting on an index
병렬이 색인을 나아가는 것을 속하게 하는 대체


/*+ CACHE */
specifies that the blocks retrieved for the table in the hint are
placed at the most recently used end of the LRU list in the
buffer cache when a full table scan is performed
그 블록이 찾아서 가져왔다는 것을 명시합니다. 그리고 그 테이블을 위해
그 암시에 놓여집니다. 그런데, 그것은 가장 요즈음 사용된 언제 그 버퍼 캐쉬,
가득한 테이블 scan에 있는 LRU 리스트의 끝입니다. 수행됩니다.

/*+ NOCACHE */
specifies that the blocks retrieved for this table are placed at
the least recently used end of the LRU list in the buffer cache
when a full table scan is performed
그 명시합니다. 그리고, 그 블록은 이 테이블을 위해 검색되면서 요즈음 사용된
언제 그 버퍼 캐쉬, 가득한 테이블 scan에 있는 LRU 리스트의 가장 작은 끝에
놓여집니다. 수행됩니다.

/*+ MERGE (table) */
causes Oracle to evaluate complex views or subqueries before
the surrounding query
오라클이 그 둘러싸는 질의 전에 복잡한 뷰나 부속 조회를 평가하게 합니다.

/*+ NO_MERGE (table) */
causes Oracle not to merge mergeable views
오라클이 mergeable 뷰를 합병하지 않게 하지 않습니다

/*+ PUSH_JOIN_PRED (table) */
causes the optimizer to evaluate, on a cost basis, whether or
not to push individual join predicates into the view
개개 접합을 미는 것이 그 뷰 안으로 단정 하든 간에 비용 방식으로 최적자가
평가하게 합니다.

/*+ NO_PUSH_JOIN_PRED (table) */
Prevents pushing of a join predicate into the view
접합 술부 중에서 그 뷰로 밀면서, 막는

/*+ PUSH_SUBQ */
causes nonmerged subqueries to be evaluated at the earliest
possible place in the execution plan
원인은 그 실행 계획에서의 가장 이른 가능한 장소에 평가되는 부속 조회를
nonmerged했습니다.

/*+ STAR_TRANSFORMATION */
makes the optimizer use the best plan in which the transformation
has been used.
최적자가 그 변형이 사용된 가장 좋은 계획을 사용하는 제작


반응형
Posted by [PineTree]