데이터베이스 - 인덱스(Index)
Index
인덱스(Index)란?
인덱스는 각 데이터의 색인으로 데이터가 저장된 레코드의 주소이다. DBMS도 데이터베이스 테이블의 모든 데이터를 검색해서 원하는 원하는 결과를 가져오려면 시간이 오래 걸린다. 그래서 칼럼의 값과 해당 레코드가 저장된 주소를 키와 값의 쌍으로 인덱스를 만들어 둔다.
DBMS의 인덱스는 항상 정렬된 상태를 유지하기 때문에 원하는 값을 탐색하는데는 빠르지만 새로운 값을 추가, 삭제, 수정하는 경우에는 쿼리문 실행속도가 더 느려진다. 즉, 저장 성능을 희생해 읽기 속도를 높이는 것이다. 하지만 모든 컬럼(column)에 인덱스를 생성하게 되면 오히려 저장 성능이 떨어지고 인덱스의 크기가 커져서 역효과가 날 수 있다.
Index 자료구조
B+-Tree 인덱스 알고리즘
일반적으로 사용되는 인덱스 알고리즘은 B+-Tree 알고리즘이다. B-tree는 데이터가 항상 정렬된상태로 유지되어 있고 가장 상단의 노드인 ‘루트 노드(Root Node)’, 중간 노드인 ‘브랜치 노드(Branch Node)’, 가장 아래 노드인 ‘리프노드(Leaf Node)’ 로 이루어져 있다. Binary search tree와 비슷하지만, B-tree는 한 노드 당 자식 노드가 2개 이상 가능하다. key값을 이용해 찾고자 하는 데이터를 트리 구조를 이용해 찾는 것이다.
Hash 인덱스 알고리즘
칼럼의 값을 해시 값으로 계산해서 인덱싱하는 알고리즘으로 O(1)의 매우 빠른 검색을 지원한다. 하지만 값을 변형해서 인덱싱하므로 값의 일부만으로 검색하고자 할 때는 해시 인덱스를 사용할 수 없다.
왜 B-tree를 쓸까?
시간복잡도 O(1)인 hash 인덱스 알고리즘이 더 좋을거 같은데 왜 쓰지 않을까? SELECT 질의 조건에는 부등호(<>) 연산도 포함되는데 동등 연산(=)에 특화된 hash table을 사용하게 된다면 문제가 발생한다.
Index의 성능과 고려해야 할 사항
검색 쿼리의 성능을 향상시키는 INDEX는 항상 좋을까? 모든 컬럼에 INDEX를 생성해두면 더 빨라지지 않을까 생각할 수 있지만 그렇지 않다. INDEX를 생성하게 되면 INSERT, DELETE, UPDATE 쿼리문을 실행할 때 별도의 과정이 추가적으로 발생한다. INSERT의 경우 INDEX에 대한 데이터도 추가해야 하므로 그만큼 성능에 손실이 발생하고, DELETE의 경우 INDEX에 존재하는 값은 삭제하지 않고 사용하지 않는다는 표시로 남게 된다. 즉, row의 수는 그대로인 것이다.
이 작업이 반복되게 되면 실제 데이터는 1만건이고 총 데이터가 10만건인 상황이 발생할 수 있다. UPDATE의 경우는 INSERT, DELETE 문제점을 동시에 수반해 변경 전 데이터는 삭제되지 않고, INSERT로 인한 분리도 발생하게 된다. 이렇게 되면 인덱스를 쓰는 의미가 없다. 그렇다면 인덱스를 어느 컬럼에 사용하는 것이 좋을까?
인덱스는 자주 조회하고 수정 빈도가 낮으며 데이터 중복이 적은 컬럼을 선택하는 것이 좋다. 그러나 한 테이블에 인덱스가 너무 많으면 데이터를 수정할 때 시간이 너무 커지고, 나이(age)나 성별(gender)같은 데이터 중복이 높은 컬럼은 인덱스를 생성하는 것이 비효율적이다. 인덱스로 얻는 이점보다 인덱스 추가 저장공간, 데이터 수정으로 인덱스 수정에 의한 성능 저하가 더 클 수 있기 때문이다.
*틀린 부분이 있으면 언제든지 말씀해 주시면 공부해서 수정하겠습니다.