DELETE
, INSERT
, UPDATE
쿼리에는 해당 사항이없으며 INDEX 사용시 오히려 느려진다.Heap
이라고 한다.Heap
에서는 인덱스가 없는 테이블의 데이터를 찾을 때 전체 데이터 페이지의 처음 레코드부터 끝 페이지의 마지막 레코드까지 모두 조회하여 검색조건과 비교하게 된다.테이블 스캔(Table Scan)
또는 풀 스캔(Full Scan)
이라고 한다.SELECT
할 때 빨리 찾기 위해 사용된다.B-Tree 알고리즘 사용 이유
B+ Tree 인덱스는 컬럼의 값을 변형하지 않고(값의 앞부분만 잘라서 관리), 원래의 값을 이용해 인덱싱하는 알고리즘이다.
Hash는 컬럼의 값으로 해시 값을 계산해서 인덱싱하는 알고리즘으로 매우 빠른 검색을 지원한다.
하지만 값을 변형해서 인덱싱하므로, 특정 문자로 시작하는 값으로 검색을 하는 등 전방 일치와 같이 값의 일부만으로 검색하고자 할 때는 해시 인덱스를 사용할 수 없다. 주로 메모리 기반의 데이터베이스에서 많이 사용한다.
데이터 접근에 시간 복잡도가 O(1)인 Hash Table말고 B-Tree를 사용하는 이유는 SELECT 절의 조건에 부등호 연산(>, <)이 포함될 경우 문제가 발생한다.
HashTable은 동등 연산(=)에 특화되어있어 데이터베이스의 자료구조에 적합하지 않다.
사용자가 쿼리를 통해 Index를 사용하는 칼럼을 검색하게 되면, 이때 MYI 파일의 내용을 활용한다.
디스크 공간은 보통 테이블을 저장하는 데 필요한 디스크 공간보다 작다.
왜냐하면 보통 인덱스는 KEY-ROWID만 가지고 있고, 테이블의 세부항목들은 갖고 있지 않기 때문이다.
SELECT *
FROM EMP
WHERE empno=7902;
이 때 두 가지 경우로 나눌 수 있는데,
기존 Block에 여유가 없을 때, 새로운 Data가 입력된다.
→ 새로운 Block을 할당 받은 후, Key를 옮기는 작업을 수행한다.
→ Index split 작업 동안, 해당 Block의 Key 값에 대해서 DML이 블로킹 된다.
대기 이벤트 발생
<Table과 Index 상황 비교>
인덱스에는 크게 Clustered와 NonClustered 인덱스로 나눌 수 있다.
Clustered 인덱스는 물리적 정렬로 DB에 데이터를 입력 시 Clustered 인덱스를 기준으로 입력이 된다.
따라서 한 테이블에 오직 하나만 존재 할 수 있으며 Table을열었을 때 Order By를 사용하지 않아도 데이터가 Clustered 인덱스에 따라 정렬이 되어 있는 것을 확인 할 수있다.
물리적으로 정렬이 되어 있는 만큼 가장 빠른 처리를 한다.
NonClustered 인덱스는 clustered 인덱스와는 달리 중복된 값을 가지면 한 테이블에 여러 개를 생성 할 수 있다.
자동 정렬되지 않고, Index를 생성할 때는 Clustered가 되어있을 때, Index Scan이 유리하다.
Index를 남발하지 말아야 하는 이유
데이터베이스 서버에 성능문제가 발생하면 가장 빨리 생각하는 해결책이 인덱스 추가 생성이다.
문제가 발생할때마다 인덱스를 생성하면서 인덱스가 쌓여가는 것은 하나의 쿼리문을 빠르게는 만들 수 있지만 전체적인 데이터베이스의 성능 부하를 초래한다.
조회 성능을 극대화하려 만든 객체인데 많은 인덱스가 쌓여서 Insert, Delete, Update시에 부하가 발생해 전체적인 데이터베이스 성능을 저하한다.
그렇기에 인덱스를 생성하는것 보다는 SQL문을 좀 더 효율적으로 짜는 방향으로 나가야한다.
인덱스 생성은 마지막 수단으로 강구해야 할 문제이다.
where
절에서 자주 사용하는 컬럼에 사용한다.like '%~'
는 조심해야 한다. %는 뒤에만 사용하도록 해야한다.order by
에 항상 또는 자주 사용되는 컬럼에 사용한다.join
으로 자주 사용되는 컬럼에 사용한다.not
연산자는 긍정문으로 변경Insert
, Delete
등 데이터의 변경(DML)이 많은 컬럼은 인덱스를 걸지 않은 편이 좋다.Insert
, Update
, Delete
)를 하면 인덱스를 다시 조정해야하기 때문에 자원이 많이 소모된다. 특히나 Insert
연산CREATE INDEX [인덱스명] ON [테이블명](컬럼1, 컬럼2, 컬럼3.......);
EX> CREATE INDEX EX_INDEX ON CUSTOMERS(NAME,ADDRESS);
// UNIQUE 키워드를 붙이면 컬럼값에 중복값을 허용하지 않는다는 뜻
EX> CREATE[UNIQUE] INDEX EX_INDEX ON CUSTOMERS(NAME,ADDRESS);
ALTER TABLE 테이블명 ADD INDEX(필드명(크기));
CREATE TABLE 테이블 명 ( 필드명 데이터타입(데이터크기), INDEX(필드명(크기)) ENGINE MyISAM;
필드 중에는 데이터 형식 때문에 인덱스가 될 수 없는 필드도 있다.
여러 필드로 이루어진(다중 필드) 인덱스를 사용하면 첫 필드 값이 같은 레코드도 구분할 수 있다.
참고로 액세스에서 다중 필드 인덱스는 최대 10개의 필드를 포함할 수 있다.
DROP INDEX [인덱스 명]
SHOW INDEX FROM 테이블이름
인덱스 파일은 생성 후 Insert, Update, Delete등을 반복하다보면 성능이 저하된다.
생성된 인덱스는 트리구조를 가지는데, 삽입,수정,삭제등이 오랫동안 일어나다보면 트리의 한쪽이 무거워져 전체적으로 트리의 깊이가 깊어지기 때문이다.
이러한 현상으로 인해 인덱스의 검색속도가 떨어지므로 주기적으로 리빌딩하는 작업을 거치는것이 좋다.
SELECT I.TABLESPACE_NAME,I.TABLE_NAME,I.INDEX_NAME, I.BLEVEL,
DECODE(SIGN(NVL(I.BLEVEL,99)-3),1,DECODE(NVL(I.BLEVEL,99),99,'?','Rebuild'),'Check') CNF
FROM USER_INDEXES I
WHERE I.BLEVEL > 4
ORDER BY I.BLEVEL DESC
해당 쿼리문을 실행하여 검색되는 Index는 리빌딩을 하는것이 좋다.
ALTER INDEX [인덱스명] REBUILD;
SELECT 'ALTER INDEX '||INDEX_NAME||' REBUILD; 'FROM USER_INDEXES;