행위

"파티셔닝 인덱스"의 두 판 사이의 차이

DB CAFE

(INDEX UNUSABLE 상태를 확인하고 해결하는 방법)
 
(같은 사용자의 중간 판 30개는 보이지 않습니다)
1번째 줄: 1번째 줄:
PARTITIONED INDEX의 종류 및 INDEX UNUSABLE 상태 정리
+
== 파티셔닝 인덱스 종류 ==
 +
=== 파티션 인덱스 와 비파티션 인덱스 ===
 +
http://www.gurubee.net/wiki/download/6260332/worddav264d3fdd650c34c32cab2381bd3bfafc1.png
 +
----
  
oracle index, unusable index, 글로벌 인덱스, 파티션 인덱스
+
=== LOCAL INDEX ===
Oracle8의 새로운 기능인 partition 은 index에도 적용된다.  
+
# local index란 index를 생성한 table과 partitioned index가 equi-partition된 경우를 나타낸다.
 +
# 즉, index와 table은 같은 컬럼에 의해 partition 되며, 하나의 index partition이 table partition 하나와 대응되며, 대응되는 index partition과 table partition은 각각 같은 범위를 갖게 된다.
 +
# 결국 특정한 하나의 index에 포함된 모든 key들은 하나의 table partition 내의 data만을 가리키게 된다.
  
partitioned index는 생성되는 형태에 따라 몇 가지로 나누어지는데, 여기에서는 이 각각의
+
----
종류에 대해 좀 더 자세히 설명한다.
+
{{틀:타이틀 투명
 +
|제목= partitioned index는 prefixed 와 non-prefixed로 나누어진다.
 +
|아이콘=emoji_objects
 +
}}
  
그리고 table과 index가 partition됨에 따라 index가 unusable 상태가 되는 경우가 발생할 수 있는데 이러한 상태를
+
=== LOCAL PREFIXED INDEX ===
 
+
# prefixed index는 index에서 맨 앞에 위치한 column에 의해 partition 되는 것
유발시키는 경우와 조치 방법에 대해서도 살펴본다.
+
# non-prefixed index는 index에서 맨 앞의 컬럼을 제외한 다른 컬럼에 의해 partition 되는것
 
 
 
 
1. partitioned index의 종류
 
(1) LOCAL INDEX
 
local index란 index를 생성한 table과 partitioned index가 equi-partition된 경우를 나타낸다.
 
 
 
즉, index와 table은 같은 컬럼에 의해 partition되며, 하나의 index partition이 table partition 하나와 대응되며, 대응되는 index partition과 table partition은 각각 같은 범위를 갖게 된다. 결국 특정한 하나의 index에 포함된 모든 key들은 하나의 table partition 내의 data만을 가리키게 된다.
 
 
 
partitioned index는 다시 다음과 같이 prefixed와 non-prefixed로 나누어진다.
 
 
 
 
 
 
 
(1)-1 local prefixed index
 
prefixed index는 index에서 맨 앞에 위치한 column에 의해 partition되는 것이며, non-prefixed index는 index에서 맨 앞의 컬럼을 제외한 다른 컬럼에 의해 partition된 경우이다.
 
 
 
local prefixed index는 다음과 같이 생성할 수 있다.
 
  
 +
{{틀:타이틀 투명
 +
|제목=local prefixed index 생성 예시
 +
|아이콘=arrow_downward
 +
}}
 
<source lang=sql>
 
<source lang=sql>
 
   CREATE TABLE dept   
 
   CREATE TABLE dept   
36번째 줄: 32번째 줄:
 
   CREATE INDEX dept_idx ON dept(deptno) LOCAL;
 
   CREATE INDEX dept_idx ON dept(deptno) LOCAL;
 
</source>
 
</source>
 +
----
 +
=== LOCAL NON-PREFIEX INDEX ===
 +
# index columns들 중 맨 앞에 있는 column으로 partition되지 않은 경우는 non-prefixed index가 된다.
  
(1)-2 local non-prefixed index
+
{{틀:타이틀 투명
 
+
|제목=non-prefixed index 생성 예시
index columns들 중 맨 앞에 있는 column으로 partition되지 않은 경우는 non-prefixed index가 된다. 다음과 같이 생성할 수 있다.
+
|아이콘=arrow_downward
 
+
}}
 
 
 
<source lang=sql>
 
<source lang=sql>
   CREATE INDEX dept_locidx ON dept(loc) LOCAL;
+
   CREATE INDEX dept_locidx  
 +
            ON dept(loc)  
 +
          LOCAL;
 
</source>
 
</source>
  
이러한 non-prefixed index는 특히 historical한 data를 보관하는 table의 경우 유용하다. 즉, 날짜에 따라 table과 index의 partition은 이루어지고, 인덱스는 별도의 사원 번호나 제품 번호와 같이 key가 되는 것에 생성하는 경우이다.
+
* 이러한 non-prefixed index는 특히 historical한 data를 보관하는 table의 경우 유용하다.  
 
+
* 즉, 날짜에 따라 table과 index의 partition은 이루어지고, 인덱스는 별도의 사원 번호나 제품 번호와 같이 key가 되는 것에 생성하는 경우이다.
 
 
 
 
(2) GLOBAL INDEX
 
 
 
  
 +
=== [[파티션 테이블 로컬인덱스 생성|파티션 로컬인덱스 생성]] ===
 +
----
  
global index는 table과는 다르게 partition이 된다. 즉, table과 같은 column으로 partition되나 그 범위가 틀리거나, 혹은 다른 컬럼으로 partition이 이루어진다.
+
=== GLOBAL INDEX ===
 
+
{{틀:고지상자
하나의 index partition에 있는 모든 index는 모두 하나의 table partition에 속하게 되지 않고, 두 개 이상의 partition에 나누어 있을 수 있다. 예를 들어 EMP table의 경우 많은 수의 사원을 각 부서 별로 partition을 구성할 수 있다. 특정 부서에 속한 사원에 대한 operation의 경우 이것은 매우 도움이 될 수 있다. 그러나 대부분 회사에 부서의 종류는 아주 많은 것이 아니어서
+
|제목=글로벌 인덱스
 
+
|내용=# 하나의 index partition에 있는 모든 index는 모두 하나의 table partition에 속하게 되지 않고, 두 개 이상의 partition에 나누어 있을 수 있다.  
번호에 index를 거는 것은 드문 일이다. 그러나 사원 번호는 고유하기 때문에 primary key가 되거나 index를 생성하는 것이 일반적이다. 이 때 이 사원 번호에 부여된 index를 partitioning하게 되면, 이것이 global index가 되는 것이다.
+
# 예를 들어  
 
+
## EMP(사원) table의 경우 많은 수의 사원을 각 부서 별로 partition을 구성할 수 있다.  
global index는 prefixed global index만이 존재하며, non-prefixed global index는 생성이 불가능하다. 즉, global index는 항상 index의 맨 앞 컬럼 값만을 이용하여 partition된다.
+
## 특정 부서에 속한 사원에 대한 operation의 경우 이것은 매우 도움이 될 수 있다.
 
+
## 그러나 대부분 회사에 부서의 종류는 아주 많은 것이 아니어서 부서 번호에 index를 거는 것은 드문 일이다.  
위의 예를 이용하여 global index를 생성하면 다음과 같다.
+
## 그러나 사원 번호는 고유하기 때문에 primary key가 되거나 index를 생성하는 것이 일반적이다.  
 +
## 이 때 이 사원 번호에 부여된 index를 partitioning하게 되면, 이것이 global index가 되는 것이다.
 +
}}
 +
# global index는 table 과 다르게 partition이 된다.
 +
# table과 같은 column으로 partition되나 그 범위가 틀리거나, 혹은 다른 컬럼으로 partition이 이루어진다.
 +
# global index는 prefixed global index만이 존재하며, non-prefixed global index는 생성이 불가능하다.
  
 +
* global index 생성 예제
  
 +
{{틀:타이틀 투명
 +
|제목=TABLE 생성시
 +
|아이콘=arrow_downward
 +
}}
 
<source lang=sql>
 
<source lang=sql>
  CREATE TABLE emp
+
CREATE TABLE emp
 
+
          ( empno NUMBER NOT NULL
  (empno NUMBER NOT NULL,
+
          , ename VARCHAR2(10)
 
+
          , deptno NUMBER
  ename VARCHAR2(10),
+
          )
 
+
-- 파티션 절
  deptno NUMBER)
 
 
 
 
   PARTITION BY RANGE (deptno)
 
   PARTITION BY RANGE (deptno)
 +
            ( PARTITION part1 VALUES LESS THAN(30)
 +
            , PARTITION part2 VALUES LESS THAN (MAXVALUE)
 +
            )
 +
;
 +
</source>
  
  (PARTITION part1 VALUES LESS THAN(30),
 
 
  PARTITION part2 VALUES LESS THAN (MAXVALUE));
 
 
  CREATE UNIQUE INDEX emp_pk on emp(empno)
 
 
  GLOBAL PARTITION BY RANGE (empno)
 
 
  (PARTITION p1 VALUES LESS THAN ("1000"),
 
 
  PARTITION p2  VALUES LESS THAN ("2000"),
 
 
  PARTITION p3  VALUES LESS THAN (MAXVALUE));
 
  
 +
{{틀:타이틀 투명
 +
|제목=INDEX  생성시
 +
|아이콘=arrow_downward
 +
}}
 +
<source lang=sql>
 +
CREATE UNIQUE INDEX PK_EMP on emp(empno)
 +
-- 파티션 절
 +
GLOBAL PARTITION BY RANGE (empno)
 +
              ( PARTITION p1 VALUES LESS THAN ("1000")
 +
              , PARTITION p2 VALUES LESS THAN ("2000")
 +
              , PARTITION p3 VALUES LESS THAN (MAXVALUE)
 +
              )
 +
-- UNUSABLE 로 생성
 +
;
 +
-- UNIQUE INDEX 를 UNUSABLE로 생성 후 리빌드 (생성 성능 향상을 위해)
 +
-- ALTER INDEX PK_EMP  REBUILD PARTITION [파티션명];
 +
</source>
  
 +
==== GLOBAL INDEX 의 INDEX UNUSABLE ====
 +
# non-partitioned index 나 partitioned index의 partition은 특정한 operation에 의해 Index Unusable(IU) 상태가 될 수 있다.
 +
# 이렇게 IU 상태가 된 index나 index partition을 SELECT하거나 DML을 시도하면 오류가 발생하게 된다.
 +
# partition이 IU 상태가 되면 그 partition을 사용하기 전에 rebuild하여야 한다.
 +
# 그러나 IU partition을 제외한 다른 partition만을 읽거나 DML을 수행하는 작업은 IU partition을 access하지 않는 한 오류가 발생하지 않는다.
 +
#: 단, IU partition을 rebuild하기 전에 split이나 rename이 가능하며, IU 상태인 global index를 drop하는 것도 가능하다.
  
2. index unusable
+
{{틀:고지상자
 
+
|제목= partition을 Index Unusable 상태로 만들 수 있는 작업(6가지로 요약)
 
+
|내용=
 
 
non-partitioned index나 partitioned index의 partition은
 
특정한 operation에 의해 Index Unusable(IU) 상태가 될 수 있다.
 
이렇게 IU 상태가 된 index나 index partition을 SELECT하거나 DML을 시도하면 오류가 발생하게 된다.
 
어떤 partition이 IU 상태가 되면 그 partition을 사용하기 전에 rebuild하여야 한다.
 
그러나 IU partition을 제외한 다른 partition만을 읽거나 DML을 수행하는 작업은 IU partition을 access하지 않는 한 오류가 발생하지 않는다.
 
단, IU partition을 rebuild하기 전에 split이나 rename이 가능하며, IU 상태인 global index를 drop하는 것도 가능하다.
 
partition을 Index Unusable 상태로 만들 수 있는 작업은
 
다음과 같이 6가지로 요약할 수 있다.
 
 
 
 
(1) direct path load 시
 
(1) direct path load 시
  
 
Direct path SQL*Loader 수행 후 index가 table의 해당 data보다 이전 것이면, IU 상태가 된다.
 
Direct path SQL*Loader 수행 후 index가 table의 해당 data보다 이전 것이면, IU 상태가 된다.
(Oracle7에서는 Index가 Direct Load State가 되었다고 표현한다).
 
 
 
index가 table의 data보다 이전 상태라는 것은 data를 load 후 index를 생성 중에 space 부족 등의 원인으로 오류가 발생하였거나 SKIP_INDEX_MAINTENANCE option을 사용한 경우이다.
 
index가 table의 data보다 이전 상태라는 것은 data를 load 후 index를 생성 중에 space 부족 등의 원인으로 오류가 발생하였거나 SKIP_INDEX_MAINTENANCE option을 사용한 경우이다.
  
121번째 줄: 130번째 줄:
  
 
     global index partition을 IU 상태로 만든다.
 
     global index partition을 IU 상태로 만든다.
 
  
  
 
(4) ALTER TABLE SPLIT PARTITION은 local index의 partition definition은 변경시키지만, 자동으로 index를 새로운 definition에 맞게 rebuild하지 않기 때문에 영향 받는 local index partition을 IU 상태로 만든다. 또한 이것은 ROWID를 변경시키기 때문에 모든 global index partition을 IU 상태로 만든다.
 
(4) ALTER TABLE SPLIT PARTITION은 local index의 partition definition은 변경시키지만, 자동으로 index를 새로운 definition에 맞게 rebuild하지 않기 때문에 영향 받는 local index partition을 IU 상태로 만든다. 또한 이것은 ROWID를 변경시키기 때문에 모든 global index partition을 IU 상태로 만든다.
 
  
  
 
(5) ALTER INDEX SPLIT PARTITION은 index의 definition은 변경시키지만, 영향 받은 partition은 rebuild시키지 않는다. 이 작업은 영향받는 index partition 부분을 IU 상태로 만든다. 그러나 global index의 경우는 그대로 usable 상태로 된다.
 
(5) ALTER INDEX SPLIT PARTITION은 index의 definition은 변경시키지만, 영향 받은 partition은 rebuild시키지 않는다. 이 작업은 영향받는 index partition 부분을 IU 상태로 만든다. 그러나 global index의 경우는 그대로 usable 상태로 된다.
 +
}}
  
 +
==== INDEX UNUSABLE 상태를 확인하고 해결하는 방법 ====
 +
1) IU 상태인 파티셔닝 테이블 확인
 +
<source lang=sql>
 +
select index_owner, index_name, partition_name, status
 +
  from dba_ind_partitions
 +
where status = 'UNUSABLE' ; 
 +
</source>
  
 +
2) 인덱스 rebuild
 +
<source lang=sql>
 +
alter index pk_emp rebuild partiton p1;
 +
</source>
  
3. unusable상태를 확인하고 해결하는 방법
+
==== global partition index 인덱스는 인덱스 전체를 한번에 재생성 할수 없음. ====
 +
* 해결 방법  
  
  os> sqlplus system/manager
+
1) 글로벌 파티션 인덱스 생성시 ORA-14086 오류 발생
 +
<source lang=sql>
 +
alter index SALES_GPNK1 rebuild
 +
</source>
 +
"ORA-14086:분할영역된 인덱스는 전체를 다시 만들 수 없습니다." 와 같은 에러를 발생하게 된다.
  
  SQL>select index_owner, index_name, partition_name, status
+
2) 파티션 단위로 인덱스 REBUILD
 
+
<source lang=sql>
      from dba_ind_partitions
+
-- 인덱스 정보 조회 dba_ind_partitions 에서 파티션 확인 후
 
+
-- 파티션별로 인덱스 리빌드
      where status = "UNUSABLE" ; 
+
alter index SALES_GPNK1 rebuild partition SALES_GPI01 ;
 
+
</source>
 
+
실무에서 global partition index의 경우 non-partition index 이든 partition index 이든 파티션 테이블 관련 작업인 경우 재생성이 필수 이므로
 
+
파티션 테이블별로 global index의 rebuild 작업용 스크립트를 작성해 놓아야 당황하지 않고 빠른 시간안에 관련 인덱스를 재 생성 할 수 있다
  rebuild하는 방법은 해당 user에서
 
 
 
  SQL>alter index emp_pk rebuild partiton p1;
 
 
 
 
 
——
 
  
 +
* ORA-01502 오류 발생 시 )
  
+
ORA-01502: 인덱스 ''''인덱스명''''또는 인덱스 분할영역은 사용할 수없는 상태이다.
ORA-01502: 인덱스 ''''인덱스명''''또는 인덱스 분할영역은 사용할 수없는 상태이다.
 
  
 
원인 : 파티셔닝테이블은 파티션별로 ROWID를 다르게 갖게 됨으로 파티션의 변경이 발생하게 되면 ROWID의 변경이 발생하게 된다.
 
원인 : 파티셔닝테이블은 파티션별로 ROWID를 다르게 갖게 됨으로 파티션의 변경이 발생하게 되면 ROWID의 변경이 발생하게 된다.
  
그래서 실제 파티션 테이블의 RowID 와 변경된 파티션 로컬 인덱스와 글로벌 인덱스의  RowID와 가 일치하지 않게 되어  
+
그래서 실제 파티션 테이블의 RowID 와 변경된 파티션 로컬 인덱스와 글로벌 인덱스의  RowID와 가 일치하지 않게 되어 인덱스 사용 중지 발생  
인덱스 사용 중지 발생  
 
 
즉, IU상태(INDEX UNUSABLE)가 발생하게 되어 인덱스의 사용 불가 및 재성성에 따른 운영 및 관리 상의 부하 , 재생성에 따른 시스템의 부하가 발생.
 
즉, IU상태(INDEX UNUSABLE)가 발생하게 되어 인덱스의 사용 불가 및 재성성에 따른 운영 및 관리 상의 부하 , 재생성에 따른 시스템의 부하가 발생.
  
(쉽게 말해 테이블 파티션이 이동하거나 , 테이블 스페이스 이동 , 병합등 ...으로인해 인덱스 참조가 깨진 현상
+
(쉽게 말해 테이블 파티션이 이동하거나 , 테이블 스페이스 이동 , 병합등 ...으로인해 인덱스 참조가 깨진 현상)
 
 
 
 
Partition Index를 Unusable상태로 만들 수 있는 명령.(Oracle9i 기준).  --퍼옴--
 
 
 
{| class="wikitable"
 
|-
 
! 작업 대상 !! 작업유형 !! 인덱스!! Unusable 상태 변경
 
|-
 
| 예시 || 예시 || 예시
 
|-
 
| 예시 || 예시 || 예시
 
|-
 
| 예시 || 예시 || 예시
 
|}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
파티션 테이블
 
 
 
ADD
 
 
 
LOCAL
 
 
 
새로 생성되므로 상관없다.
 
 
 
GLOBAL
 
 
 
파티션만 추가되므로 상관없다.
 
 
 
DROP
 
 
 
LOCAL
 
 
 
같이 삭제되므로 상관없다.
 
 
 
GLOBAL
 
 
 
모든 GLOBAL INDEX가 Unusable
 
 
 
SPLIT
 
 
 
LOCAL
 
 
 
SPLIT된 파티션 인덱스 Unusable
 
 
 
GLOBAL
 
 
 
모든 GLOBAL INDEX가 Unusable
 
 
 
MERGE
 
 
 
LOCAL
 
 
 
머지되어 남는 파티션 인덱스 Unusable
 
 
 
GLOBAL
 
 
 
모든 GLOBAL INDEX가 Unusable
 
 
 
RENAME
 
 
 
LOCAL
 
 
 
실제 변경이 없으므로 상관없다.
 
 
 
GLOBAL
 
 
 
실제 변경이 없으므로 상관없다.
 
 
 
MOVE
 
 
 
LOCAL
 
 
 
MOVE된 파티션 인덱스 Unusable
 
 
 
GLOBAL
 
 
 
모든 GLOBAL INDEX가 Unusable
 
  
TRUNCATE
 
 
LOCAL
 
 
남은 로우가 없으므로 상관없다.
 
 
GLOBAL
 
 
모든 GLOBAL INDEX가 Unusable
 
 
EXCHANGE
 
 
LOCAL
 
 
EXCHANGE한 파티션 인덱스 Unusable
 
 
GLOBAL
 
 
모든 GLOBAL INDEX가 Unusable
 
 
(표를 보면 알겠지만 Unusable상태가 되는 것은 실제 파티션 테이블 데이터의 RowID를 변경시킨 경우(파티션 단위의 변경이 발생시에도 해당 파티션에 실제 로우 데이터가 있어서 RowID 변경이 발생된 경우)에 해당된다.)
 
 
 
 
해결 :
 
 
가장 간단한 방법!!!!!!!!!!!!
 
 
인덱스를 사용하지 않고 해당 파티션을 TABLE FULL SCAN 하면 에러가 발생 하지 않는다.
 
 
 
옵티마이져가 실행계획 수립시에 INDEX UNUSABLE 상태 여부를 체크하지 않으므로
 
해당 인덱스를 사용하는 실행계획이 수립되고 실제 수행시 오류가 발생하게 됨으로
 
이미 운용중인 어플리케이션이나 SQL이 정상 수행되지 않는다.
 
 
이런 경우에는 skip_unusable_indexes = TRUE 파라메터를 지정하면
 
수행시에 해당 인덱스가 UNUSABLE 이면 이를 사용하지 않고 TABLE FULL SCAN 등을 한다.
 
경우에 따라서 유용하게 사용 가능하므로 고려 해 볼 수 있다.
 
 
궁극적인 해결방법은
 
 
partition table관련 작업을 한 후에는 table에 걸려 있는 local(partitioned) index 나 global index를 반드시 rebuild해 주어야 한다.
 
 
 
왠만하면 그냥 index Rebuild로 문제를 해결할 수 있다.
 
 
global index를 rebuild하려면 non-partition index 인덱스인 경우는 단순히 Rebuild를 실행하면 되지만
 
global partition index 인덱스는 인덱스 전체를 한번에 재생성 할 수 없다.
 
<source lang=sql>
 
alter index SALES_GPNK1 rebuild
 
</source>
 
 
"ORA-14086:분할영역된 인덱스는 전체를 다시 만들 수 없습니다." 와 같은 에러를 발생하게 된다.
 
 
<source lang=sql>
 
alter index SALES_GPNK1 rebuild partition SALES_GPI01 ;
 
</source>
 
  
위와 같이 인덱스 파티션 단위로 재 생성 해주어야만 한다.
 
  
global partition index의 경우 non-partition index 이든 partition index 이든 파티션 테이블 관련 작업인 경우 재생성이 필수 이므로
+
[[Category:oracle]]
파티션 테이블별로 global index의 rebuild 작업용 스크립트를 작성해 놓아야 빠른 시간안에 관련 인덱스를 재 생성 할 수 있다
 

2024년 4월 23일 (화) 00:19 기준 최신판

thumb_up 추천메뉴 바로가기


1 파티셔닝 인덱스 종류[편집]

1.1 파티션 인덱스 와 비파티션 인덱스[편집]

worddav264d3fdd650c34c32cab2381bd3bfafc1.png


1.2 LOCAL INDEX[편집]

  1. local index란 index를 생성한 table과 partitioned index가 equi-partition된 경우를 나타낸다.
  2. 즉, index와 table은 같은 컬럼에 의해 partition 되며, 하나의 index partition이 table partition 하나와 대응되며, 대응되는 index partition과 table partition은 각각 같은 범위를 갖게 된다.
  3. 결국 특정한 하나의 index에 포함된 모든 key들은 하나의 table partition 내의 data만을 가리키게 된다.

 emoji_objects partitioned index는 prefixed 와 non-prefixed로 나누어진다.

1.3 LOCAL PREFIXED INDEX[편집]

  1. prefixed index는 index에서 맨 앞에 위치한 column에 의해 partition 되는 것
  2. non-prefixed index는 index에서 맨 앞의 컬럼을 제외한 다른 컬럼에 의해 partition 되는것

 arrow_downward local prefixed index 생성 예시

CREATE TABLE dept   
              ( deptno NUMBER NOT NULL
              , loc VARCHAR2(10))
   PARTITION BY RANGE (deptno)
   (PARTITION part1 VALUES LESS THAN(30),
   PARTITION part2 values less than (MAXVALUE));
   CREATE INDEX dept_idx ON dept(deptno) LOCAL;

1.4 LOCAL NON-PREFIEX INDEX[편집]

  1. index columns들 중 맨 앞에 있는 column으로 partition되지 않은 경우는 non-prefixed index가 된다.

 arrow_downward non-prefixed index 생성 예시

CREATE INDEX dept_locidx 
             ON dept(loc) 
          LOCAL;
  • 이러한 non-prefixed index는 특히 historical한 data를 보관하는 table의 경우 유용하다.
  • 즉, 날짜에 따라 table과 index의 partition은 이루어지고, 인덱스는 별도의 사원 번호나 제품 번호와 같이 key가 되는 것에 생성하는 경우이다.

1.5 파티션 로컬인덱스 생성[편집]


1.6 GLOBAL INDEX[편집]

  1. 하나의 index partition에 있는 모든 index는 모두 하나의 table partition에 속하게 되지 않고, 두 개 이상의 partition에 나누어 있을 수 있다.
  2. 예를 들어
    1. EMP(사원) table의 경우 많은 수의 사원을 각 부서 별로 partition을 구성할 수 있다.
    2. 특정 부서에 속한 사원에 대한 operation의 경우 이것은 매우 도움이 될 수 있다.
    3. 그러나 대부분 회사에 부서의 종류는 아주 많은 것이 아니어서 부서 번호에 index를 거는 것은 드문 일이다.
    4. 그러나 사원 번호는 고유하기 때문에 primary key가 되거나 index를 생성하는 것이 일반적이다.
    5. 이 때 이 사원 번호에 부여된 index를 partitioning하게 되면, 이것이 global index가 되는 것이다.


  1. global index는 table 과 다르게 partition이 된다.
  2. table과 같은 column으로 partition되나 그 범위가 틀리거나, 혹은 다른 컬럼으로 partition이 이루어진다.
  3. global index는 prefixed global index만이 존재하며, non-prefixed global index는 생성이 불가능하다.
  • global index 생성 예제

 arrow_downward TABLE 생성시

CREATE TABLE emp
           ( empno NUMBER NOT NULL
           , ename VARCHAR2(10)
           , deptno NUMBER
           )
-- 파티션 절 
   PARTITION BY RANGE (deptno)
             ( PARTITION part1 VALUES LESS THAN(30)
             , PARTITION part2 VALUES LESS THAN (MAXVALUE)
             )
;


 arrow_downward INDEX 생성시

CREATE UNIQUE INDEX PK_EMP on emp(empno)
-- 파티션 절 
GLOBAL PARTITION BY RANGE (empno)
               ( PARTITION p1 VALUES LESS THAN ("1000")
               , PARTITION p2 VALUES LESS THAN ("2000")
               , PARTITION p3 VALUES LESS THAN (MAXVALUE)
               )
-- UNUSABLE 로 생성 
;
-- UNIQUE INDEX 를 UNUSABLE로 생성 후 리빌드 (생성 성능 향상을 위해)
-- ALTER INDEX PK_EMP  REBUILD PARTITION [파티션명];

1.6.1 GLOBAL INDEX 의 INDEX UNUSABLE[편집]

  1. non-partitioned index 나 partitioned index의 partition은 특정한 operation에 의해 Index Unusable(IU) 상태가 될 수 있다.
  2. 이렇게 IU 상태가 된 index나 index partition을 SELECT하거나 DML을 시도하면 오류가 발생하게 된다.
  3. partition이 IU 상태가 되면 그 partition을 사용하기 전에 rebuild하여야 한다.
  4. 그러나 IU partition을 제외한 다른 partition만을 읽거나 DML을 수행하는 작업은 IU partition을 access하지 않는 한 오류가 발생하지 않는다.
    단, IU partition을 rebuild하기 전에 split이나 rename이 가능하며, IU 상태인 global index를 drop하는 것도 가능하다.


(1) direct path load 시

Direct path SQL*Loader 수행 후 index가 table의 해당 data보다 이전 것이면, IU 상태가 된다. index가 table의 data보다 이전 상태라는 것은 data를 load 후 index를 생성 중에 space 부족 등의 원인으로 오류가 발생하였거나 SKIP_INDEX_MAINTENANCE option을 사용한 경우이다.


(2) ALTER TABLE MOVE PARTITION과 같이 ROWID를 변화시키는 작업.

   영향받는 local index와 전체 global index를 IU 상태가 되게 한다.


(3) ALTER TABLE TRUNCATE PARTITION이나 DROP PARTITION과 같이 table의 row를 지우는 작업.

   global index partition을 IU 상태로 만든다.


(4) ALTER TABLE SPLIT PARTITION은 local index의 partition definition은 변경시키지만, 자동으로 index를 새로운 definition에 맞게 rebuild하지 않기 때문에 영향 받는 local index partition을 IU 상태로 만든다. 또한 이것은 ROWID를 변경시키기 때문에 모든 global index partition을 IU 상태로 만든다.


(5) ALTER INDEX SPLIT PARTITION은 index의 definition은 변경시키지만, 영향 받은 partition은 rebuild시키지 않는다. 이 작업은 영향받는 index partition 부분을 IU 상태로 만든다. 그러나 global index의 경우는 그대로 usable 상태로 된다.



1.6.2 INDEX UNUSABLE 상태를 확인하고 해결하는 방법[편집]

1) IU 상태인 파티셔닝 테이블 확인

select index_owner, index_name, partition_name, status 
  from dba_ind_partitions
 where status = 'UNUSABLE' ;

2) 인덱스 rebuild

alter index pk_emp rebuild partiton p1;

1.6.3 global partition index 인덱스는 인덱스 전체를 한번에 재생성 할수 없음.[편집]

  • 해결 방법

1) 글로벌 파티션 인덱스 생성시 ORA-14086 오류 발생

alter index SALES_GPNK1 rebuild

"ORA-14086:분할영역된 인덱스는 전체를 다시 만들 수 없습니다." 와 같은 에러를 발생하게 된다.

2) 파티션 단위로 인덱스 REBUILD

-- 인덱스 정보 조회 dba_ind_partitions 에서 파티션 확인 후 
-- 파티션별로 인덱스 리빌드 
alter index SALES_GPNK1 rebuild partition SALES_GPI01 ;

실무에서 global partition index의 경우 non-partition index 이든 partition index 이든 파티션 테이블 관련 작업인 경우 재생성이 필수 이므로 파티션 테이블별로 global index의 rebuild 작업용 스크립트를 작성해 놓아야 당황하지 않고 빠른 시간안에 관련 인덱스를 재 생성 할 수 있다

  • ORA-01502 오류 발생 시 )

ORA-01502: 인덱스 '인덱스명'또는 인덱스 분할영역은 사용할 수없는 상태이다.

원인 : 파티셔닝테이블은 파티션별로 ROWID를 다르게 갖게 됨으로 파티션의 변경이 발생하게 되면 ROWID의 변경이 발생하게 된다.

그래서 실제 파티션 테이블의 RowID 와 변경된 파티션 로컬 인덱스와 글로벌 인덱스의 RowID와 가 일치하지 않게 되어 인덱스 사용 중지 발생 즉, IU상태(INDEX UNUSABLE)가 발생하게 되어 인덱스의 사용 불가 및 재성성에 따른 운영 및 관리 상의 부하 , 재생성에 따른 시스템의 부하가 발생.

(쉽게 말해 테이블 파티션이 이동하거나 , 테이블 스페이스 이동 , 병합등 ...으로인해 인덱스 참조가 깨진 현상)