안녕하세요.

오늘은 데이터베이스 인덱스 개념에 대해 설명합니다.

인덱스란

인덱스(INDEX)DBMS의 검색 속도를 높이기 위한 기술 입니다.

DBMS는 데이터를 순차적으로 쌓으므로, 특정 데이터를 찾기 위해서는 데이터의 FULL-SCAN인 순차 탐색(O(N))이 필요합니다.

DBMS는 특정 데이터를 특별한 자료 구조로 쌓아 탐색 속도를 개선할 수 있는 기능을 제공합니다. 해당 기능을 인덱스라 부르고 쌓은 데이터들을 인덱스 테이블이라 부릅니다.

인덱스는 책의 목차와 비유할 수 있습니다. 우리가 책의 목차를 참고하여 필요한 내용으로 곧 바로 넘어가드시, DBMS인덱스 테이블에서 특정 인덱스를 찾아 필요한 행 데이터를 바로 가져옵니다.


인덱스 테이블

인덱스 테이블은 데이터를 조회할 때 사용되는 특정 컬럼의 데이터로 구성됩니다.

인덱스 테이블 에 포함된 데이터를 WHERE 문으로 조회를 하면 인덱스 테이블을 통해 ROW-ID를 빠르게 구한 뒤 단번에 행 데이터를 조회 할 수 있습니다.

인덱스 테이블 탐색

인덱스 테이블의 핵심은 빠른 조회 성능입니다. 이를 위해 인덱스 테이블은 탐색 트리 자료구조 중 하나인 B+트리 자료구조로 데이터를 저장합니다. 탐색 트리는 O(log2Nlog_2N) 성능의 빠른 조회를 할 수 있는 특징이 있습니다.

그렇기에, 데이터 FULL-SCAN[O(N)]성능에 비해, 압도적인 빠른 조회를 할 수 있는 장점 이 있습니다.

B+트리 포스팅을 참고해주세요.

인덱스 테이블 생성

TABLE을 생성 할 때, PRIMARY_KEY를 지정한 컬럼은 자동적으로 PRIMARY_KEY를 기준으로 인덱스 테이블이 생성됩니다.

만약 다른 컬럼을 인덱스 테이블을 생성하고 싶다면, 직접 생성해야 합니다.


인덱스 장점

인덱스의 장점은 곧 B+트리 자료구조의 장점과 일맥상통 합니다.

빠른 조회

인덱스 테이블은 메모리에 저장되어 있는 B+트리 자료구조 입니다.

메모리는 한정적인 자원이기 때문에 DBMS인덱스로 지정한 컬럼 데이터와 ROW-ID로 구성된 최소한의 노드로 B+트리를 구성합니다.

ROW-ID는 파일에 저장되어 있는 행 데이터를 가져올 수 있는 정보입니다.

여기에서 알 수 있는 재미있는 특징이 하나 있습니다. 데이터 FULL-SCAN이 느린이유는 순차탐색인 이유도 있지만, 빈번한 파일IO도 많은 영향을 미칩니다.

반면에 빠른 메모리 조회로 행 아이디를 찾는 인덱스 방식은 최소한의 파일IO를 사용합니다. 최소한의 파일IO는 더욱 빠른 탐색 속도를 가능하게 합니다.

데이터 정렬

만약 인덱스된 컬럼으로 정렬 명령을 내린다면 정렬 비용을 아낄 수 있습니다.

B+트리 구조상 조회된 데이터를 가져오기만 해도 정렬된 데이터를 획득할 수 있기 때문입니다.


인덱스 단점

지금까지의 설명만 보자면 인덱스 기능은 매우 훌륭한 기능 같습니다만, 그에 못지 않은 단점도 존재합니다. 대표적으로 아래와 같은 단점이 존재합니다.

  • 인덱스 테이블 유지 비용 (B+트리 유지비용)
  • 인덱스 테이블 추가 공간 비용

인덱스 테이블 유지 비용

B+트리의 중요한 특징 중 하나는 균형 이진 트리를 구성한다는 점 입니다. 노드의 삭제, 삽입시 트리 균형을 위해 트리 구조를 재구성 하는 비용이 발생합니다. 더군다나 탐색 이진 트리의 업데이트는 삭제 + 삽입 과정이 발생하므로 2배의 비용이 발생하게 됩니다.

위에서 살펴본 B+트리의 특징이 인덱스 테이블에도 똑같이 적용됩니다.

즉, O(log2Nlog_2N)으로 빠르게 조회가 가능하지만 삽입, 삭제, 업데이트 작업은 노드의 위치 탐색 비용 + 트리 재구성 비용 이 발생하게 됩니다.

DBMS는 트리 재구성 비용이라도 아끼기 위해 노드 삭제를 진행하지 않습니다. 대신 해당 노드에 사용하지 않는다는 마킹만 진행합니다. 그로인해 DBMS의 삭제, 업데이트 명령은 노드의 위치 탐색 비용만 발생하게 됩니다.

인덱스 테이블 추가 공간 비용

인덱스 테이블의 노드 삭제를 하지 않음으로써, 트리 재구성 비용을 아낀 전략은 유효해 보입니다. 하지만 이 역시도 다른 문제가 존재합니다.

그 문제는 바로, 인덱스 테이블이 거대해짐에 따라, 트리의 높이가 깊어지는 문제 입니다.

이는 테이블의 행 개수 보다 많은 개수의 저장공간을 필요로 합니다.

하지만 더욱 결정적인 문제는 트리 높이에 따른 성능으로 인해 인덱스 테이블 의 깊은 높이는 DBMS 성능을 점진적으로 내린다는 점 입니다.

결론적으로, 미 사용 노드를 트리에서 제거함으로써 높이 최적화가 필요함 을 알 수 있습니다. DBMS는 트리 높이 최적화를 수행하는 명령을 제공합니다. 해당 명령을 주기적으로 수행함으로써 전체적인 DBMS 성능을 높일 수 있습니다.


인덱스 생성 전략

위에서 살펴본 인덱스의 단점을 통해, 다음과 같은 결론을 도출 할 수 있습니다.

조회보다 삽입, 삭제, 업데이트가 더 많이 발생하는 테이블은 인덱스 기능이 오히려 단점이 될 수 있습니다.

또한 인덱스를 설정할 때는 유의할점이 몇개 존재합니다.

Cardinality 체크

인덱스를 구성할 땐, 컬럼의 Cardinality 를 고려하여 생성해야 합니다.

Cardinality 란 값의 분산도를 의미합니다. 다르게 표현하자면 값이 형태가 얼마나 다양하게 나올 수 있느냐의 척도입니다. 만약 (Y, N) 2가지 값으로만 구성된 컬럼을 인덱스로 설정하는 것은, 1700 페이지로 구성된 책에 목차가 2개만 존재하는것과 마찬가지 효과 입니다.

그렇기에 행 데이터가 최대한 많이 분류될 수 있는 컬럼으로 인덱스를 생성해야 효과적입니다.

조회 조건 빈번도 체크

당연한 얘기일 수 있겠지만, 조회 조건으로 자주 사용되는 컬럼일수록 인덱스 조건에 부합합니다.

아래의 항목은 간단한게 체크해볼 수 있는 리스트 입니다.

  • 조건절에 자주 등장하는 컬럼
  • LIKE 검색보다는 = 으로 검색하는 컬럼
  • ORDER BY 절에서 자주 사용되는 컬럼
  • JOIN으로 자주 사용되는 컬럼


지금까지 살펴본 내용을 요약하자면 다음과 같습니다.

  • 인덱스B+트리 구조를 통해 조회 성능을 올리는 기능입니다.
  • 데이터 FULL-SCAN은 빈번한 파일IO 작업을 통한 순차탐색으로 매우 느린 반면에 인덱스는 메모리에 저장된 트리 탐색을 통해 파일의 위치를 획득하여 파일IO 작업을 최소화 합니다.
  • 인덱스는 조회 성능을 높이고 삽입, 삭제, 업데이트 성능을 낮추는 트레이드 오프 기능 이므로 조회가 주된 목적인 테이블일 수록 유리합니다.
  • 인덱스는 조회가 주된 목적인 테이블일 수록 유리합니다.
  • 인덱스 테이블의 높이는 점점 깊어지므로, 주기적인 정리가 필요합니다.
  • 인덱스를 생성할 때는 Cardinality조회 조건 빈번도 체크가 필요합니다.

오늘 포스팅은 여기까지 입니다.

읽어주셔서 감사합니다.

'데이터베이스' 카테고리의 다른 글

[MySQL] 데이터베이스 원격 접속 명령어  (0) 2020.08.21
트랜잭션(Transaction)이란?  (27) 2017.02.27
Mysql 외부접근 설정하기.  (0) 2015.11.16

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts