아직까지 서비스를 출시한 경험도 없고, 너무 복잡한 데이터 베이스 구조도 설계한 적이 없어 Slow Query에 대해서 신경쓰지 않고 개발을 하곤 했다. 따라서 Slow Query를 개선하기 위해 로그를 찍거나 쿼리 최적화 및 튜닝에 대해서 고민해본 적이 없는 것 같다. 이번 포스팅을 통해 Slow Query를 개선하기 위해 DB Index이 무엇이고, 어떻게 설정하고 적용해야하는지 공부해보아야 겠다.
추가적인 쓰기 작업과 저장 공간을 활용하여 데이터 베이스 테이블의 검색 속도를 향상시키기 위한 자료구조이다. DB Index의 가장 대표적인 예는 책의 색인이다. 책에서 원하는 내용을 찾는다고 할 때, 책의 모든 페이지를 찾아보는 것 (FULL SCAN) 보다는 책의 맨 앞 혹은 책 맨 뒤에 있는 색인 페이지를 통해 빠르게 찾을 수 있다. 마찬가지로 index를 사용하지 않는 칼럼을 조회하는 상황에서는 테이블 전체를 탐색하는 Full Scan이 수행되어 처리 속도가 떨어진다. 따라서 index 설정을 통해 검색 속도 향상 및 조회 성능을 높일 수 있다.
// 인덱스 설정
CREATE INDEX si_id ON MEMBER (id); // single column index
CREATE INDEX si_name ON MEMBER (name);
CREATE INDEX mi_id_name ON MEMBER (id, name); // multi column index
CREATE INDEX mi_id_name_age ON MEMBER (id, name, age);
Index를 관리하기 위해서는 DB의 약 10%에 해당하는 저장공간이 필요하다. 또한 Index는 항상 최신의 정렬된 상태로 유지해야 원하는 값을 빠르게 탐색할 수 있는데, 만약 Index에 적용된 칼럼에 INSERT, UPDATE, DELETE가 수행된다면 Index를 관리하기 위해 추가적으로 연산을 해주어야 하며 그에 따른 오버헤드가 발생한다.
따라서, DELETE와 UPDATE가 비번하게 일어나는 칼럼에 대해서 index를 설정하면, 인덱스의 크기가 비대해져서 성능을 오히려 저하시킨다. 왜냐하면 DELETE와 UPDATE 시 기존의 인덱스를 삭제하지 않고 '사용하지 않음'처리를 해주기 때문에 인덱스의 크기가 커져, SQL문 처리시 오히려 성능이 떨어질 수 있다.
따라서, 다음과 같은 기준을 통해 INDEX를 설정할 칼럼을 선택하는 것이 바람직하며, 아무 칼럼에 무작정 INDEX를 설정하는 것은 전체적인 데이터 베이스의 성능 부하를 초래한다.
(Key, Value)로 데이터를 저장하는 자료구조로, 빠른 데이터 검색이 필요할 때 유용하다. 하지만 DB 인덱스에서 해시 테이블을 사용하는 경우는 제한적이라고 한다. 왜냐하면 해시 테이블은 등호(=) 연산에 특화된 자료구조이기 때문이다. 데이터베이스 조회시 등호 연산도 사용하지만, 부동호 연산(>, <)이 자주 일어난다. 해시 함수는 값이 1이라도 달라지면 다른 해시값을 생성할 수 있기 때문에 데이터베이스 검색을 위해서는 해시 테이블이 적합하지 않다.
DB의 인덱스를 위해 자식 노드가 2개 이상인 B-Tree를 개선시킨 자료구조이다.
데이터 베이스의 인덱스 칼럼은 부등호를 이용한 순차 검색 연산이 자주 발생한다. 따라서 BTree의 리프 노드들을 Linked List로 연결하여 순차검색을 용이하게 하는 등 BTree를 인덱스에 맞게 최적화한 것이다.
비록 B+Tree는 O(log2𝑛)의 시간복작도를 가지지만, 해시테이블보다 인덱싱에 더욱 적합한 자료구조이다.
https://mangkyu.tistory.com/96
https://velog.io/@jwpark06/효과적인-DB-index-설정하기