많은 사람들이 데이터베이스 인덱스의 개념을 설명할 때 책의 맨 마지막에 있는 색인(찾아보기)에 비유합니다.
예를 들어서 여러분이 깔끔한 파이썬 탄탄한 백엔드 책을 보고 있다고 가정해 봅시다. 만약에 “트렌젝션”이라는 단어가 책 어디에 나왔는지 찾아야하는 상황이라고 해봅시다.
책에 색인(찾아보기)이 없는 경우라면, 책을 첫 페이지에서부터 한장씩 남겨가며 “트렌젝션” 단어를 찾는 수밖에 없습니다. 운이 좋아서 찾는 내용이 책의 앞부분에서 “트렌젝션” 단어를 찾았다고 하더라도 책 전체에서 ‘트렌젝션'이라는 단어가 한 번만 나온다는 보장이 없으므로, 책의 마지막 장까지 계속해서 찾아봐야 합니다.
이번에는 책에 색인(찾아보기)이 있는 경우를 살펴보겠습니다. 색인(찾아보기)은 “ㄱ”, “ㄴ”, “ㄷ”, …과 같은 순서로 이미 정렬되어 있어서 “ㅌ” 부분을 찾아보면 그 중에서 쉽게 “트렌젝션" 단어를 찾을 수 있을 것입니다. 그리고 단어 옆에 적혀있는 페이지 번호로 책 내용중에 “트렌젝션" 단어가 있는 위치로 바로 찾아 들어갈 수 있습니다.
또한 색인(찾아보기)의 경우에는 하나의 단어가 몇 개의 페이지에 있다고 하더라도 그 몇 개 페이지가 모두 색인(찾아보기)에 표시되기 때문에 책 전체를 계속해서 찾을 필요가 없이 몇 번만 책을 펼치면 모든 내용을 찾을 수 있습니다.
데이터베이스의 인덱스 개념은 책의 색인(찾아보기)과 상당히 비슷한 개념입니다. 책의 마지막에 있는 색인(찾아보기)이 데이터베이스의 인덱스에 비유된다면 책의 전체 내용은 데이터 파일에 해당한다고 볼 수 있습니다. 책의 색인을 통해서 알아낼 수 있는 페이지 번호는 데이터 파일에 저장된 레코드(2차원 테이블의 행 데이터)의 주소에 비유될 수 있습니다.
책의 색인(찾아보기)는 책의 분량에 따라서 필요할 수도 있고 필요 없을 수도 있습니다. 10 페이지 이내 분량의 책이라면 색인이 없다고 하더라도 빠르게 내용을 찾을 수 있을 것입니다. 하지만 수천 페이지로 구성된 두꺼운 책이 있다면, 색인 없이는 원하는 내용을 찾는데 많은 시간을 쏟게될 것입니다.
DBMS도 마찬가지로 데이터의 양이 많아지게 되면 테이블의 모든 데이터를 검색해서 원하는 결과를 가져오려면 시간이 오래 걸립니다. 그래서 열(column) 또는 여러개의 열의 값과 해당 레코드(row)가 저장된 주소를 키와 값의 쌍(key-value)으로 삼아서 인덱스를 만들어두는 것입니다.
결국 인덱스는 데이터를 더 빠르게 찾을 수 있도록 도와주는 도구라고 정리할 수 있습니다.
현대 웹시스템에서 다루어지는 데이터의 양은 굉장히 많아지고 복잡해 졌습니다. 수 많은 데이터를 저장해두고 그 많은 데이터에서 원하는 결과를 찾아내는 상황이 빈번하게 일어납니다. 때문에 개발자는 데이터베이스의 인덱스에 대한 개념을 잘 알고 있어야 조회 성능을 개선할 수 있습니다.
DBMS는 인덱스를 생성할 때, B-Tree 자료구조에 데이터를 정렬해서 저장합니다. 정렬된 자료구조에 데이터를 저장해 놓으면 효율적인 탐색 알고리즘을 사용하여 데이터를 빠르게 찾을 수 있기 때문입니다.
이러한 인덱스의 정렬 특성 덕분에 빠르게 검색을 할 수 있게 되는데, 장점만 존재하는 것은 아닙니다. 이제부터 인덱스가 정렬된 상태를 유지하는 특성으로 인해서 얻을 수 있는 장점과 단점에 대해서 살펴보고 언제 사용하면 좋은지에 대해서 알아보도록 하겠습니다.
정리하면, 인덱스를 잘 사용하면 검색 속도가 월등히 향상되고, 시스템 성능이 좋아지는 반면에 잘 못 사용하면 오히려 사용하지 않는 것보다 더 나쁜 결과를 초래할 수 있다는 사실을 인지하고 사용하시길 바랍니다.
B트리(B-tree)는 자가 균형 이진 트리(Self-balancing tree structure)의 일종으로, 데이터베이스 시스템과 파일 시스템에서 널리 사용되는 데이터 구조입니다. B트리는 효율적인 삽입, 삭제, 검색 연산을 가능하게 하며, 디스크에 저장된 대량의 데이터를 빠르게 읽고 쓸 수 있게 해줍니다.
Clustered Index와 Non-Clustered Index는 데이터베이스에서 인덱싱을 구현하는 두 가지 주요 방법입니다. 두 인덱스 유형 모두 B트리나 그 변형을 기반으로 합니다.
지금까지 인덱스가 어떻게 생성되는지 그리고 생성된 인덱스가 어떻게 사용되는지를 알아봤으니 실제로 인덱스를 생성해보겠습니다. 실습에 필요한 데이터셋은 아래 파일에 준비되어있습니다. (총 690만 rows) 실습과 동일한 MySQL 버전은 8.0.27 입니다.
인덱스를 생성하는 문법은 아래와 같습니다.
CREATE INDEX 인덱스명 ON 테이블명 (컬럼명);
아래 명령어를 입력하면 records_username_idx
라는 이름으로 인덱스가 생성됩니다.
CREATE INDEX records_username_idx ON records (username);
데이터가 많아 인덱스를 생성하는데만 13초가 걸린 것을 확인할 수 있습니다.
인덱스 삭제하는 문법은 아래와 같습니다.
DROP INDEX 인덱스명 ON 테이블명;
DROP INDEX records_username_idx ON records;
username
컬럼에 대한 인덱스를 생성했으니 실제로 인덱스를 사용하면 속도가 빨라지는지 테스트해보겠습니다.
username
컬럼 인덱스 없이 실행한 결과
username
컬럼 인덱스를 생성한 뒤 실행한 결과
이렇게 간략히 진행한 테스트에서 약 93배 정도의 속도 차이가 나는 것을 확인할 수 있습니다.