-- 1. 선택도가 높은 컬럼을 앞에 -- 2. 등호(=) 조건을 앞에, 범위 조건을 뒤에 -- 3. 자주 사용되는 컬럼 조합
CREATE INDEX idx_emp_composite ON employees( department_id, -- 등호 조건 job_id, -- 등호 조건 salary -- 범위 조건 );
-- 효율적인 사용 SELECT*FROM employees WHERE department_id =10 AND job_id ='SA_REP' AND salary >5000;
인덱스 통계 확인
-- 인덱스 목록 조회 SELECT index_name, table_name, uniqueness, status FROM user_indexes WHERE table_name ='EMPLOYEES';
-- 인덱스 컬럼 확인 SELECT index_name, column_name, column_position FROM user_ind_columns WHERE table_name ='EMPLOYEES' ORDERBY index_name, column_position;
-- 인덱스 상세 통계 SELECT index_name, blevel, -- B-Tree 레벨 leaf_blocks, -- 리프 블록 수 num_rows, -- 인덱스 행 수 distinct_keys, -- 고유 키 수 clustering_factor -- 클러스터링 팩터 FROM user_indexes WHERE table_name ='EMPLOYEES';
인덱스 사용 확인
-- 실행 계획에서 인덱스 사용 여부 확인 EXPLAIN PLAN FOR SELECT*FROM employees WHERE department_id =10;
SELECT*FROMTABLE(DBMS_XPLAN.DISPLAY);
-- 인덱스가 사용되지 않는 이유 확인 -- 1. 통계 정보 부족 -- 2. 인덱스 컬럼 변형 -- 3. 데이터 분포 문제 -- 4. Full Table Scan이 더 효율적
인덱스 재구성
-- 인덱스 재구성 (Online) ALTER INDEX idx_emp_dept REBUILD ONLINE;
-- 인덱스 재생성 DROP INDEX idx_emp_dept; CREATE INDEX idx_emp_dept ON employees(department_id);
-- 파티션 인덱스 재구성 ALTER INDEX idx_sales_date REBUILD PARTITION p_2024_q1 ONLINE;
불필요한 인덱스 찾기
-- 사용되지 않는 인덱스 모니터링 시작 ALTER INDEX idx_emp_dept MONITORING USAGE;
-- 사용 여부 확인 SELECT*FROM v$object_usage WHERE index_name ='IDX_EMP_DEPT';
-- 모니터링 중지 ALTER INDEX idx_emp_dept NOMONITORING USAGE;
인덱스 설계 가이드라인
인덱스를 생성해야 하는 경우
WHERE 절에 자주 사용되는 컬럼
JOIN 조건에 사용되는 컬럼
ORDER BY 절에 사용되는 컬럼
선택도(Selectivity)가 높은 컬럼
테이블 크기가 큰 경우
인덱스를 생성하지 말아야 하는 경우
테이블이 작은 경우 (수천 건 이하)
컬럼 값이 자주 변경되는 경우
Cardinality가 매우 낮은 컬럼 (비트맵 제외)
테이블의 대부분 행을 조회하는 경우
인덱스 성능 비교
-- Full Table Scan SELECT/*+ FULL(e) */*FROM employees e WHERE department_id =10;
-- Index Range Scan SELECT/*+ INDEX(e idx_emp_dept) */*FROM employees e WHERE department_id =10;
-- Index Fast Full Scan SELECT/*+ INDEX_FFS(e idx_emp_dept_sal) */ department_id, salary FROM employees e;