반응형

대용량 테이블이고 DML(INSERT, UPDATE, DELETE 등)가 계속 일어나는 테이블에 신규 인덱스 생성을 하려면

Lock이 걸려서 서비스가 원활하지 않을 수 있습니다.

그럴 경우에 아래와 같이 ONLINE, NOLOGGING 옵션을 사용하면 좋습니다.

ONLINE은 서비스 중에 Lock이 걸리지 않고 인덱스 생성하는 옵션입니다.

NOLOGGING은 UNDO, REDO를 최소하면서 인덱스 생성할 수 있게 도와주는 옵션입니다.

1. 테이블 EMPLOYEE 에 기 생성된 인덱스 확인

SELECT IDX.OWNER, IDX.INDEX_NAME, IDX.TABLE_OWNER,
IDX.TABLE_NAME, IDX.TABLESPACE_NAME, IDX_COL.COLUMN_NAME
FROM DBA_INDEXES IDX, DBA_IND_COLUMNS IDX_COL
WHRE IDX.TABLE_NAME = 'EMPLOYEE'
AND IDX.INDEX_NAME=IDX_COL.INDEX_NAME
ORDER BY INDEX_NAME;

2. 아래의 구문을 사용한 인덱스 생성

CREATE INDEX EMP.IX_EMPLOYEE01 ON EMP.IX_EMPLOYEE(IDX01, IDX02, IDX03, IDX04)
NOLOGGING TABLESPACE TS_IDX_EMP LOCAL ONLINE;

3. 생성된 인덱스 10% 샘플링 통계수집

BEGIN
  SYS.DBMS_STATS.GATHER_INDEX_STATS (
     OwnName           => 'EMP'
    ,IndName           => 'IX_EMPLOYEE01'
    ,Estimate_Percent  => 10
    ,Degree            => 4
    ,No_Invalidate  => FALSE);
END;
/

감사합니다.

반응형

인덱스 확인

개발 및 관리/Oracle 9i, 10g, 11g, 12c, 19c 2014. 9. 23. 21:24 posted by HighLighter
반응형

SELECT IDX.OWNER, IDX.INDEX_NAME, IDX.TABLE_OWNER,
IDX.TABLE_NAME, IDX.TABLESPACE_NAME, IDX_COL.COLUMN_NAME
FROM DBA_INDEXES IDX, DBA_IND_COLUMNS IDX_COL
WHRE IDX.TABLE_NAME = 'EMP'
AND IDX.INDEX_NAME=IDX_COL.INDEX_NAME
ORDER BY INDEX_NAME;

 

SQL> desc dba_indexes;
 Name Null? Type
 ----------------------------------------- -------- ----------------------------
 OWNER NOT NULL VARCHAR2(30)
 INDEX_NAME NOT NULL VARCHAR2(30)
 INDEX_TYPE VARCHAR2(27)
 TABLE_OWNER NOT NULL VARCHAR2(30)
 TABLE_NAME NOT NULL VARCHAR2(30)
 TABLE_TYPE VARCHAR2(11)
 UNIQUENESS VARCHAR2(9)
 COMPRESSION VARCHAR2(8)
 PREFIX_LENGTH NUMBER
 TABLESPACE_NAME VARCHAR2(30)
 INI_TRANS NUMBER
 MAX_TRANS NUMBER
 INITIAL_EXTENT NUMBER
 NEXT_EXTENT NUMBER
 MIN_EXTENTS NUMBER
 MAX_EXTENTS NUMBER
 PCT_INCREASE NUMBER
 PCT_THRESHOLD NUMBER
 INCLUDE_COLUMN NUMBER
 FREELISTS NUMBER
 FREELIST_GROUPS NUMBER
 PCT_FREE NUMBER
 LOGGING VARCHAR2(3)
 BLEVEL NUMBER
 LEAF_BLOCKS NUMBER
 DISTINCT_KEYS NUMBER
 AVG_LEAF_BLOCKS_PER_KEY NUMBER
 AVG_DATA_BLOCKS_PER_KEY NUMBER
 CLUSTERING_FACTOR NUMBER
 STATUS VARCHAR2(8)
 NUM_ROWS NUMBER
 SAMPLE_SIZE NUMBER
 LAST_ANALYZED DATE
 DEGREE VARCHAR2(40)
 INSTANCES VARCHAR2(40)
 PARTITIONED VARCHAR2(3)
 TEMPORARY VARCHAR2(1)
 GENERATED VARCHAR2(1)
 SECONDARY VARCHAR2(1)
 BUFFER_POOL VARCHAR2(7)
 USER_STATS VARCHAR2(3)
 DURATION VARCHAR2(15)
 PCT_DIRECT_ACCESS NUMBER
 ITYP_OWNER VARCHAR2(30)
 ITYP_NAME VARCHAR2(30)
 PARAMETERS VARCHAR2(1000)
 GLOBAL_STATS VARCHAR2(3)
 DOMIDX_STATUS VARCHAR2(12)
 DOMIDX_OPSTATUS VARCHAR2(6)
 FUNCIDX_STATUS VARCHAR2(8)
 JOIN_INDEX VARCHAR2(3)

 SQL> desc dba_ind_columns;
 Name Null? Type
 ----------------------------------------- -------- ----------------------------
 INDEX_OWNER NOT NULL VARCHAR2(30)
 INDEX_NAME NOT NULL VARCHAR2(30)
 TABLE_OWNER NOT NULL VARCHAR2(30)
 TABLE_NAME NOT NULL VARCHAR2(30)
 COLUMN_NAME VARCHAR2(4000)
 COLUMN_POSITION NOT NULL NUMBER
 COLUMN_LENGTH NOT NULL NUMBER
 CHAR_LENGTH NUMBER
 DESCEND VARCHAR2(4)

 SQL> desc v$object_usage;
 Name Null? Type
 ----------------------------------------- -------- ----------------------------
 INDEX_NAME NOT NULL VARCHAR2(30)
 TABLE_NAME NOT NULL VARCHAR2(30)
 MONITORING VARCHAR2(3)
 USED VARCHAR2(3)
 START_MONITORING VARCHAR2(19)
 END_MONITORING VARCHAR2(19)

 SQL> spool off

토드 사용시 OWNER.TABLE_NAME 에 커서를 위치시키고 F4 를 누르면 별도의 Description을 확인할 수 있습닏.

 

반응형
반응형

*I/O 튜닝의 핵심 원리

 하나, Random 액세스 발생량을 줄인다.

 둘, Sequential 액세스에 의한 선택 비중을 높인다.

 

1. 테이블 Random 액세스 최소화 튜닝 - SQL전문가 가이드 p.628~p.630

(하나, Random 액세스 발생량을 줄인다.)

1) 인덱스 칼럼 추가
2) Covered Index
3) Include Index
4) IOT, 클러스터형 인덱스, 클러스터 테이블 활용
5) 수동으로 클러스터링 팩터 높이기

 

2. 인덱스 스캔범위 최소화 - SQL전문가 가이드 p.631~p.637

(둘, Sequential 액세스에 의한 선택 비중을 높인다.)

1) 인덱스 선행 칼럼이 범위조건일 때의 비효율

    - 인덱스 선행 칼럼이 조건절에 누락되거나 between, 부등호, like 같은 범위검색 조건이 사용되면 인덱스를

스캔하는 단계에서 비효율이 발생한다.


2) 범위조건을 In-List로 전환

   - 인덱스 선두 칼럼의 between 조건을 IN-List 조건으로 바꿀 때 IN-List 개수가 적어야 한다. IN-List 개수가 많을 때는, between 조건 때문에 리프 블록을 추가로 스캔하는 비효율보다 IN-List 조건 때문에 브랜치 블록을 반복 탐색하는 비효율이 더 클 수 있고, 인덱스 높이(height)가 높을 때 특히 그렇다.

   - Oracle이라면 범위조건에서 Index Skip Scan이 유용할 수 있다. Index Skip Scan은 인덱스 선두 칼럼이 누락됐을 때뿐만 아니라 부등호, between, like 같은 범위검색 조건일 때도 사용될 수 있다. 

 

 (가) 1차 단계 - BETWEEN

 SELECT 해당층, 평당가, 입력일, 해당동, 매물구분, 연사용일수, 중개업소코드

 FROM 매물아파트매매

 WHERE 아파트시세코드 = 'A0100'

 AND 평형 = '59'

 AND 평형타입 = 'A'

 AND 인터넷매물 BETWEEN '1' AND '2'

 ORDER BY 입력일 DESC

 ;

 

 (나) 2차 단계 - IN

SELECT 해당층, 평당가, 입력일, 해당동, 매물구분, 연사용일수, 중개업소코드

FROM 매물아파트매매

WHERE 아파트시세코드 = 'A0100'

AND 평형 = '59'

AND 평형타입 = 'A'

AND 인터넷매물 IN ('1',  '2')

ORDER BY 입력일 DESC

;


 3) 조건을 2개 이상 사용할 때의 비효율
 - 인덱스 구성 [회사+지역+상품명]일 때, 아래와 같이 범위검색 조건을 2개 이상 사용하면 첫 번째가 인덱스 스캔 범위를 거의 결정되고, 두 번째는 필터 조건 역할만 하기 때문에 성능상 불리해질 수 있다.

 

(가) 1차 단계

SELECT 고객ID, 상품명, 지역, ...

FROM 가입상품

WHERE 회사 = :com

AND 지역 LIKE :reg || '%'

AND 상품명 LIKE :prod || '%'

;

 

(나) 2차 단계

  A) CASE 1 - 만약 지역 칼럼에 대한 검색조건이 입력되지 않을 수도 있어 LIKE 연산자를 사용할 것이라면 SQL을 아래와 같이 만들어 사용하는 것이 좋다.

    <SQL1>

    SELECT 고객ID, 상품명, 지역, ...

    FROM 가입상품

    WHERE 회사 = :com

    AND 상품명 LIKE :prod || '%'

    ;

   <SQL2>

   SELECT 고객ID, 상품명, 지역, ...

   FROM 가입상품

   WHERE 회사 = :com

   AND 지역 = :reg

   AND 상품명 LIKE :prod || '%'

   ;

 

 B) CASE 2 - UNION ALL을 사용하는 방법도 있다.

 - 기존의 인덱스 구성 하에서, UNION ALL 상단 쿼리는 기존과 동일한 비효율을 안은 채 수행되겠지만 하단 쿼리만큼은 최상으로 수행될 수 있다. 만약 UNION ALL 상단 쿼리까지 최적화하려면 [회사+상품명] 순으로 구성된 인덱스를 하나 더 추가해야 한다.

 - 인덱스를 새로 추가하는데 부담이 있으면 기존 인덱스 순서를 [회사+상품명+지역] 순으로 변경하는 것을 고려할 수 있는데, 그럴 경우(UNION ALL) 하단 쿼리를 처리할 때 불리해진다. 따라서 이는 상품명 조건에 입력되는 값의 선택도에 따라 결정할 사항이다.                   

 

SELECT 고객ID, 상품명, 지역, ...

FROM 가입상품

WHERE :reg IS NULL 

AND 회사 = :com

AND 상품명 LIKE :prod || '%'

UNION ALL

SELECT 고객ID, 상품명, 지역, ...

FROM 가입상품

WHERE :reg IS NOT NULL

AND 회사 = :com

AND 지역 = :reg

AND 상품명 LIKE :prod || '%'

;

반응형
반응형

 

1. 비트맵 인덱스는 Lock에 의한 DML 부하가 심하다.

   - 레코드 하나만 변경되더라도 해당 비트맵 범위에 속한 모든 레코드에 Lock이 걸린다.

   - OLTP성 환경에 비트맵 인덱스를 쓸수 없다.

   - 읽기 위주의 대용량 DW(특히, OLAP) 환경에 아주 적합하다.

  

2. Oracle B*Tree 인덱스와 달리 비트맵 인덱스는 NULL도 저장

  

       SELECT * FROM 상품

WHERE 색상 IS NULL

;

 

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

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

 

 칼럼의 Distinct Value 개수가 적을 때 비트맵 인덱스를 사용하면 저장효율이 매우 좋다. B*Tree 인덱스보다 훨씬 적은 용량을 차지하므로 인덱스가 여러 개 필요한 대용량 테이블에 유용하다. 다양한 분석관점(Dimension)을 가진 팩트성 테이블이 주로 여기에 속한다. 반대로 Distinct Value가 아주 많은 칼럼이면 오히려 B*Tree 인덱스보다

많은 공간을 차지한다.

 

 Distinct Value 개수가 적은 칼럼일 때 저장효율이 좋지만 테이블 Random 액세스 발생 측면에서는 B*Tree 인덱스와 똑같기 때문에 그런 칼럼을 비트맵 인덱스로 검색하면 그다지 좋은 성능을 기대하기 어렵다. 스캔할 인덱스 블록이 줄어도는 정도의 성능 이점만 얻을 수 있고, 따라서 하나의 비트맵 인덱스 단독으로는 쓰임새가 별로 없다. 그 대신, 여러 비트맵 인덱스를 동시에 사용할 수 있는 특징 때문에 대용량 데이터 검색 성능을 향상시키는 데에 효과가 있다.

 

 비트맵 인덱스는 여러 인덱스를 동시에 활용할 수 있다는 장점 때문에 다양한 조건이 사용되는, 특히 정형화되지 않은 임의 질의(ad-hoc query)가 많은 환경에 적합하다.

 

SELECT 지역, SUM(판매량), SUM(판매금액)

FROM 연도별지역별상품매출

WHERE (크기 = 'SMALL' OR 크기 IS NULL)

AND 색상 = 'GREEN'

AND 출시연도 = '2012'

GROUP BY 지역

;

 

 

반응형
반응형

*인덱스를 재생성하는 데 걸리는 시간과 부하를 무시할 수 없다. 따라서 인덱스의 주기적인 재생성 작업은 아래와 같이 예상효과가 확실할 때만 시행하는 것이 바람직하다.

 

 1. 인덱스 분할에 의한 경합이 현저히 높을 때

 2. 자주 사용되는 인덱스 스캔 효율을 높이고자 할 때, 특히 NL Join에서 반복 액세스되는 인덱스 높이(height)가 증가했을 때

 3. 대량의 delete 작업을 수행한 이후 다시 레코드가 입력되기까지 오랜 기간이 소요될 때

 4. 총 레코드 수가 일정한데도 인덱스가 계속 커질 때

 

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

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

 

 Fragmentation 때문에 인덱스 크기가 계속 증가하고 스캔 효율이 나빠지면 인덱스를 재생성하거나 DBMS가 제공하는 명령어를 이용해 빈 공간을 제거하는 것이 유용할 수 있다. 하지만 일반적으로 인덱스 블록에는 어느 정도 공간을 남겨두는 것이 좋다. 왜냐하면, 빈 공간을 제거해 인덱스 구조를 슬림(slim)화하면 저장 효율이나 스캔효율에 좋겠지만 인덱스 분할이 자주 발생해 DML 성능이 나빠질 수 있기 때문이다.

 

 인덱스 분할에 의한 경합을 줄일 목적으로, 초기부터 빈 공간을 남기도록 옵션을 주고 인덱스를 재생성할 수도 있다. 하지만 효과는 일시적이다. 언젠가 빈 공간이 다시 채워지기 때문이며, 결국 적당한 시점마다 재생성 작업을 반복하지 않는 한 근본적인 해결책이 되지는 못 한다.

 

 

반응형