데이터베이스 인덱스는 책의 색인(찾아보기)과 같은 역할이다.
데이터베이스에 있는 모든 데이터를 검색(Full Table Scan)하는 것은 오랜 시간이 걸리기 때문에, 컬럼과 해당 레코드의 주소값를 key-value로 생성해 빠른 조회를 돕는 것이다.
인덱스를 사용하면 조회 뿐만 아니라, UPDATE/DELIETE 연산 시에도 성능이 향상된다.
// 업데이트를 위해선 조건절에 레코드를 먼저 찾아야 한다.
UPDATE user SET name = 'BONSIK' WHERE name = 'KOO';
이처럼, RDBMS는 빠른 조회를 위해서 인덱스를 항상 정렬된 상태를 유지해야 된다.
반대로 데이터 저장(INSERT, DELETE, UPDATE)이 발생 한다면, 아래와 같은 추가 작업이 발생 하므로 그에 따른 오버헤드가 생긴다.
(추가로 인덱스 저장 용량과 생성 비용도 발생)
INSERT
- 저장할 레코드의 키 값과 대상 레코드의 주소 정보를 리프 노드에 저장한다.
- 리프 노드가 꽉 찰 경우 리프 노드 분리가 필요한데, 이는 상위 브랜치 노드까지 분리가 발생할 수 있다.(뒤에서 설명 추가)
- 상대적으로 DELETE, UPDATE 보다 더 많은 비용이 발생한다.
- 참고로, 스토리지 엔진에 따라 인덱스를 즉시 생성할 수도 그렇지 않을 수 있다.(단, Primary Key, Unique 인덱스 일 경우, 중복 검사가 필요하므로 즉시 생성)
DELETE
- 삭제할 데이터 리프 노드에 삭제 마크를 표시한다.
**💡 삭제 마크만 사용하는 이유**
1.성능 향상: 인덱스를 실제 삭제하면 해당 공간은 빈자로 남게 되므로, 인덱스 재구축이 작업이 필요하다. 이는 많은 오버헤드가 발생하므로 삭제 마크만 표시 한다면 성능 저하를 최소화 할 수 있다.
2.복구 가능성: 인덱스를 실제 삭제하면 데이터를 복구했을 때, 마찬가지로 인덱스 재구축 작업이 필요하므로 삭제 마크만 사용한다면 오버헤드를 피할 수 있다.
3.재사용: 추가할 인덱스가 이전에 삭제 마크 부분에 해당할 경우, 해당 인덱스 키를 재사용하고 데이터(레코드 주소값)만 교체할 수 있다.
UPDATE
- 업데이트 할 인덱스를 삭제 마크를 표시한 뒤, 새로운 키의 인덱스를 추가한다.
이와 같이, 빈번하게 데이터 저장(INSERT, DELETE, UPDATE)이 발생하는 컬럼에 인덱스를 설정하게 되면 인덱스 크기가 비대해져 오히려 역효과를 불러올 수 있다.
→ 인덱스를 실제 삭제 마크로 표시하기 때문
결과적으로 인덱스는 데이터 저장이 발생하는 성능 저하를 희생하고, 데이터 읽기 성능 향상을 택했다.