PORTFOLIO/TROUBLESHOOTING

[CodeChef - 트러블 슈팅] 인덱싱: 데이터 속도 전쟁에서 살아남기!

jki09871 2025. 1. 6. 16:02

[문제 인식]

게시글 검색을 위해 풀 테이블 스캔을 하는건 너무 비효율적이고 성능 소비가 심하다.

대량의 데이터가 생길수록 응답 속도는 더 큰 차이를 보인다. 그래서 풀 테이블 스캔이 아니라, 인덱스를 생성하여 데이터 조회 속도를 높이고, 리소스 사용을 최적화 한다.

인덱스

책의 색인처럼 특정 데이터를 빠르게 찾을 수 있도록 하는 특별한 데이터 구조이다.

  • B-Tree 인덱스: 범위 검색, 정렬된 데이터 조회에 적합하여 대부분의 데이터베이스에서 기본적으로 사용된다.
  • Hash 인덱스: 특정 값과 일치하는 데이터를 찾는 데 빠르며, 범위 검색에는 적합하지 않다.

[선택 이유]

  • 검색 속도를 높인다: 인덱스가 있으면 특정 데이터 위치를 바로 찾아가니까 전체 테이블을 검색할 필요 없이 빠르게 결과를 얻는다.
  • 응답 시간을 줄인다: 쿼리 실행 시 필요한 데이터만 추려내기 때문에, 응답 시간이 짧아져 사용자에게 빠르게 결과를 보여준다.
  • 데이터베이스 성능을 개선한다: 인덱스를 사용하면 데이터베이스가 더 적은 자원으로 원하는 데이터를 찾아내 성능이 전반적으로 향상된다.
  • 처리 부담을 낮춘다: 전체 테이블 스캔을 하면 데이터가 많아질수록 부담이 커지지만, 인덱스는 필요한 데이터만 조회하기 때문에 부담이 훨씬 덜하다.
  • 쿼리 최적화를 돕는다: 인덱스가 적절하게 설정되어 있으면 복잡한 쿼리에서도 최적의 검색 경로를 찾을 수 있어 쿼리가 효율적으로 실행된다

[해결 방안]

Board 엔티티에 @Index 어노테이션을 설정하여, 기본 인덱스를 설정하였다.

하지만 애플리케이션 실행 중, 오류가 발생하였는데, MYSQL의 InnoDB는 인덱스의 최대 크기를 3072byte로 제한을 한다.

Board 엔티티의 title과 contents를 중심으로 검색하려고 하면, 4 * 2200 즉 8800바이트가 발생한다.

그래서 우리는 기본 인덱스를 사용하지 않고, 이를 해결해줄 수 있는 부분 인덱스를 사용하기로 한다.

애플리케이션을 실행할 때 Local에서 CREATE INDEX boards_title_contents_partial_index ON boards (title(50), contents(200))”; 쿼리를 실행한다.

이는 title의 길이 50, contents의 길이 200까지만 인덱스를 설정한다는 뜻이다.

그래서 인덱스를 부분으로 걸어 인덱스의 크기를 줄이고 저장 공간을 절약한다.

인덱싱이 정상적으로 등록됐다.

10만개의 더미 데이터를 넣고 조회를 100번 하여 성능 비교를 했는데 놀랍게도 차이가 없다.

확인 해보니 LIKE문에서 인덱스을 걸려면 CONCAT문과 함께 사용해야 한다.

코드를 이렇게 수정하면 인덱스가 적용 된다.

type = range로 boardSearch 쿼리 인덱싱 적용 완료 확인

 

[해결 완료]

처리 방식 평균 응답시간 처리량 표준 편차 최소 응답시간 최대 응답시간

인덱스 38 25.9/sec 2.83 37 65
DB 54 18.4/sec 1.17 53 62

인덱싱을 적용한 쿼리가 이전 쿼리에 비해 약 30%의 빠른 평균 응답 속도와 처리량을 보인다.