들어가며
회사에서 약 12만건의 테스트 데이터를 삽입 후 테스트를 하다가 검색 속도 저하 이슈가 발견됐습니다.
검색 속도를 향상 시킬 방법을 생각하다가 잊고 지냈던 index가 떠올랐어요
하지만 회사 프로젝트에 적용 시키기엔 인덱스에 대한 개념을 정확하게 알고 있지 못한 상태라고 판단이 됐고

정확한 개념 파악 후 프로젝트에 적용시키기 위해 정리하게 됐습니다!
인덱스 적용 후 데이터 검색 속도가 눈에 띄게 향상 됐습니다.
정확한 수치를 기록해뒀으면 좋았을텐데 현재는 퇴사를 해서 확인 할 방법이 없네요,,^^
1. 인덱스(Index) 란 ?
인덱스란 ?
인덱스는 데이터베이스의 테이블에 대한 검색 속도를 향상시켜주는 자료구조입니다.
테이블의 특정 컬럼에 인덱스를 생성하면, 해당 컬럼의 데이터를 정렬한 후 별도의 메모리 공간에 데이터의 물리적 주소와 함께 저장됩니다.
컬럼의 값과 물리적 주소를 (key,value) 한 쌍으로 저장합니다.
인덱스는 책의 목차 혹은 색인이라고 생각하면 됩니다.
책에서 원하는 내용을 찾을 때 목차나 색인을 이용하면 훨씬 빠르게 찾을 수 있는데,
마찬가지로 테이블에서 원하는 데이터를 찾기 위해 인덱스를 이용하면 빠르게 찾을 수 있습니다.
그러므로 데이터 = 책의 내용 , 인덱스 =책의 목차 , 물리적 주소 = 책의 페이지 번호 라고 생각할 수 있습니다.

인덱스를 활용하면, 데이터를 조회하는 SELECT 외에도 UPDATE나 DELETE 성능이 함께 향상됩니다.
해당 연산을 수행하려면 해당 대상을 조회해야만 작업을 할 수 있기 때문입니다.
SELECT * FROM USER WHERE name = 'ahreum';
만약 index를 사용하지 않은 컬럼을 조회해야 하는 상황이라면 전체를 탐색하는 Full Scan을 수행해야 합니다.
Full Scan은 전체를 검색하기 때문에 테이블 내의 데이터가 많으면 많을 수록 처리 속도가 떨어지게 됩니다.
인덱스의 관리
DBMS는 index를 항상 최신의 정렬된 상태로 유지해야 원하는 값을 빠르게 탐색할 수 있습니다.
그렇기 때문에 인덱스가 적용된 컬럼에 INSERT,UPDATE,DELETE가 수행이 된다면
각각 다음과 같은 연산을 추가적으로 해줘야 하며 그에 따른 오버헤드가 발생합니다.
- INSERT : 새로운 데이터에 대한 인덱스를 추가함
- DEELTE : 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업을 진행함
- UPDATE : 기존의 인덱스를 사용하지 않음을 처리하고, 갱신된 데이터에 대해 인덱스를 추가함
인덱스의 장점과 단점
- 장점
- 테이블을 조회하는 속도와 그에 따른 성능을 향상시킬 수 있음
- 전반적인 시스템 부하를 줄일 수 있음
- 단점
- 인덱스를 관리하기 위해 DB의 약 10%에 해당하는 저장공간이 필요함
- 인덱스를 관리하기 위해 추가 작업이 필요함
- 인덱스를 잘못 사용할 경우 오히려 성능이 저하되는 역효과가 발생할 수 있음
만약 INSERT,DELETE,UPDATE가 빈번한 속성에 인덱스를 걸게 되면
인덱스의 크기가 비대해져 성능이 오히려 저하되는 역효과가 발생 할 수 있습니다.
그러한 이유 중 하나는 DELETE와 UPDATE 연산 때문입니다.
위에서 언급하였듯이, UPDATE와 DELETE는 기존의 인덱스를 삭제하지 않고 사용하지 않음 처리를 해줍니다.
만약 어떤 테이블에 UPDATE와 DELETE가 빈번하게 발생된다면 실제 데이터는 10만건 이지만, 인덱스는 100만건이 넘어가게 되어
SQL문 처리 시 비대해진 인덱스로 인해 인덱스를 사용하지 않는 상황보다 성능이 떨어지게 될 것입니다.
인덱스를 사용하면 좋은 케이스
- 규모가 작지 않은 테이블
- INSERT, UPDATE, DELETE가 자주 발생하지 않는 컬럼
- JOIN이나 WHERE 또는 ORDER BY에 자주 사용되는 컬럼
- 데이터의 중복도가 낮은 컬럼
💡 인덱스는 내부적으로 Key,Value의 트리 형태로 데이터를 저장하는데
데이터(Key)가 중복되어 여러개 존재하면 검색되는 대상이 증가하기 때문 - 기타 등등
⭐️ 인덱스를 사용하는 것 만큼이나 생성된 인덱스를 관리해주는 것도 중요합니다. 그러므로 사용되지 않는 인덱스는 바로 제거를 해주어야 합니다.!
2. 인덱스의 자료구조
인덱스는 여러 자료구조를 이용해서 구현할 수 있는데, 대표적으로 해시 테이블(Hash Table)과 B+Tree가 있습니다.
해시 테이블 (Hash Table)
해시 테이블은 key와 value를 한 쌍으로 데이터를 저장하는 자료구조 입니다.
(key,value)로 쌍을 표현하며, key 값을 이용해 대응되는 value 값을 구하는 방식입니다.
해시 충돌이라는 변수가 존재하지만 평균적으로 O(1)의 매우 빠른 시간만에 원하는 데이터를 탐색할 수 있는 구조입니다.
해시 테이블을 이용한다면 인덱스는 (key,value) = (컬럼의 값, 데이터의 위치)로 구현하는데, 해시 테이블은 실제로 인덱스에서는 잘 사용되지 않습니다.
그 이유는, 해시 테이블은 등호(=) 연산에 최적화 되어있기 때문입니다.
데이터베이스에서는 부등호(<,>) 연산이 자주 사용되는데, 해시 테이블 내의 데이터들은 정렬되어 있지 않으므로 특저어 기준보다 크거나 작은 값을 빠른 시간 내에 찾을 수 없습니다.
예를 들면 김씨 성을 가진 모든 사용자를 검색하기 위한 쿼리문은 인덱스의 혜택을 전혀 받지 못하게 됩니다.
이러한 이유로 데이터베이스의 인덱스에는 B+Tree가 일반적으로 사용됩니다.
B+Tree
기존의 B-Tree는 어느 한 데이터의 검색은 효율적이지만, 모든 데이터를 한 번 순회 하는데에는 트리의 모든 노드를 방문해야 하므로 비효율적입니다. 이러한 B-Tree 의 단점을 개선시킨 자료구조가 B+Tree입니다.
B+Tree는 오직 leaf node(자식이 없는 노드)에만 데이터를 저장하고 leaf node가 아닌 node에는 자식 포인터만 저장합니다.
그리고 leaf node 끼리는 Linked list로 연결되어있습니다.
또 B+Tree 에서는 반드시 leaf node에만 데이터가 저장되기 때문에 중간 node에서 key를 올바르게 찾아가기 위해서 key가 중복될 수 있습니다.

B+Tree 장점
1. leaf 노드를 제외하고 데이터를 저장하기 않기 때문에 메모리를 더 확보할 수 있습니다. 따라서 하나의 node에 더 많은 포인터를 가질 수 있기 때문에 트리의 높이가 더 낮아지므로 검색 속도를 높일 수 있습니다.
2. Full Scan을 하는 경우 B+Tree는 leaf node에만 데이터가 저장되어 있고, leaf node 끼리 linked list로 연결되어 있기 때문에 선형 시간이 소모됩니다. (반면, B-Tree는 모든 node를 확인해야 함)
반면, B-Tree의 경우 최상의 경우 특정 ket를 root에서 찾을 수 있지만, B+Tree의 경우 반드시 특정 key에 접근하기 위해 leaf node 까지 접근해야 하는 단점이 있습니다.
그렇다면 왜 인덱스에서 B-Tree 대신 주로 B+Tree를 사용하는 걸까요?
위에서 언급했듯이 인덱스 컬럼은 부등호를 이용한 순차 검색 연산이 자주 발생할 수 있습니다.
따라서 B+Tree의 Linked list를 이용하면 순차 검색을 효율적으로 할 수 있게 됩니다!
마치며
인덱스라는 개념을 단순히 'DB 검색 속도를 향상 시켜주는 용도' 로 생각하고 있었는데
막상 공부해보니 아무곳에나 남발하면 아주 위험한 친구였다는 생각이 듭니다,,,
인덱스의 알고리즘을 공부하면서 B+Tree에 대해 알게 되었는데 다음에는 B-Tree, B*Tree 알고리즘에 대해 공부해서 포스팅 할 예정입니다.
공부는 새로운 공부를 하게 만든다는 점이 아주 매력적이네요,, 진짜로,,
긴 글 읽어주셔서 감사합니다!
출처
https://mangkyu.tistory.com/96
#인덱스 #DB