서론
DB 인덱스의 원리 / 적절한 인덱스 사용의 중요성에 대해서는 이론적으로 공부했었다.
프로젝트를 진행하며 인덱스 유무의 성능 차이를 체감한 경험이 있어 기록한다.
개요
a, b, c, d 라는 데이터 타입이 있다. 계층적 데이터 구조로 이루어져있으며, a는 b의 순열로 나타나며, b는 c의 순열로, c는 d의 순열로 나타낼 수 있다. (중복은 없다.)
즉, a > b > c > d의 관계다.
a는 여러 b순열로 표현될 수 있으며, b,c,d는 각각 하위 순열이 하나 밖에 없다.
예를 들어, a1는 (b1,b2,b3), (b1, b4, b5, b6, b3) 등 2개 이상의 순열로 표현될 수 있지만, b,c,d는 b1 = (c1,c2)와 같이 하나의 순열로만 표현된다.
a,b,c는 각 하위 요소의 순서 또한 가지고 있다.
그래서 데이터의 한 row에는
a의 경우,
a_id, a_permutation_no, b_id, a_order_no
b,c,d의 경우,
b_id, c_id, c_order_no
를 포함하고 있다.
프로젝트를 진행하며, a가 d 단위로 나타날 수 있는 모든 방법을 찾아내야 했다. (a,b,c,d의 데이터는 모두 DB에 저장되어 있다.)
처음에는 d 단위가 없었다.
Select Join 쿼리로 a,b,c의 모든 데이터를 가지고 온 다음, a,b,c 인스턴스를 List에 담고, 각 상위 데이터 id를 List<>.Select().Where(x => x.id == curId)를 통해서 가져와 하위 List에 넣어줬다.(C# .NET을 사용했다.)
이 경우, 약 10만개의 a데이터를 처리할 때, 70초 정도의 성능을 보였다.
각 상위 데이터 id를 List<>.Select().Where()로 가져오는 것을 자료 구조로 바꿔 Dictionary<key, List<Child.Id>> 저장했다. 이 경우, 데이터 응답 시간을 11초까지 줄일 수 있었다. 약 7배의 시간 성능 향상이 있었다.
자료구조를 바꿔서 시간 성능을 향상시켰으나, 그래도 10만건의 데이터를 가져올 때, 성능 문제가 분명 존재했다.
DB를 확인해보니 해당 데이터 Table에 아무런 Key나 인덱스가 존재하지 않았다. 각 데이터들의 ID는 유일성이 보장되는 데이터이기 때문에 PK로 설정해줬고, 각 테이블에 하위 데이터 Id를 FK로 설정해줬다.
인덱스 설정 후, 약 600ms 이내로 데이터를 처리할 수 있었다. 2에서 총 18배 정도의 성능향상을 할 수 있었다.
후기
기계적으로 쓰던 인덱스가 기존 사용하던 DB에 존재하지 않을 때, 성능 하락이 얼마나 되는지 알 수 있었다.
본격적으로 해당 기능에 대해 회고하고 싶지만, 일단은 프로젝트가 끝난 다음에....