Index란?
MySQL에 Index란 DB에 성능을 향상시키기 위한 데이터 구조 입니다.
Index는 DB 테이블 내의 특정 열(컬럼, 필드)에 대한 검색과 정렬을 빠르게 수행하기 위한 자료구조 입니다.
Index는 데이터 검색 속도 향상, 정렬, 중복 제거 등의 용도로 사용되며 기본키 인덱스, 유니크 인덱스, 인덱스, 외래 키 인덱스 등의 종류가 있습니다.
저는 테이블의 특정 열에 대한 일반적인 Index를 적용해보려 합니다.
Index는 데이터의 종류가 많은 열에 사용하면 더욱 큰 성능 향상 효과를 볼 수 있습니다.
Index 사용하기
MySQL에서 Index를 적용하여 조회 성능 향상시켜 보겠습니다.
성능 측정은 Spring Boot에서 진행했고 JPA를 활용했습니다.
저의 프로젝트 구성은 다음과 같습니다.
Spring Boot : 2.7.14
MySQL : 8.0.30
JPA : 2.2.3
Hibernate : 5.1.2
Index 설정
Index를 설정하는 방법은 Query와 JPA 설정 2가지 방법이 있습니다.
Query
Index 설정
CREATE INDEX 이름 ON 테이블명 (필드명); -- 형식
CREATE INDEX idx_tier ON users (tier); -- 예시
Index 설정 확인
SHOW INDEX FROM 테이블명; -- 양식
SHOW INDEX FROM users; -- 예시
Index 삭제
DROP INDEX 이름 ON 테이블명; -- 양식
DROP INDEX idx_tier ON users; -- 예시
HeidiSQL을 통한 인덱스 설정 확인
위의 명령어를 사용하면 Index 설정과 Index가 잘 설정되었는지 확인할 수 있습니다.
원한다면 DROP 명령어를 통해서 설정한 인덱스를 삭제할 수 있습니다.
JPA
@Index 어노테이션을 필드에 걸어 Index 설정을 할 수 있습니다.
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.UUID;
import org.hibernate.annotations.Index;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "users")
public class User {
@Id
@Builder.Default
private String id = UUID.randomUUID().toString();
@Column(name = "login_id")
@Index(name = "idx_login_id")
private String loginId;
private String password;
}
여기서 주의해야 할 점은 @Index 어노테이션은 hibernate에서 제공하는 거라 자동 완성이 좀 이상하게 됩니다.
깔끔한 코드를 위해 `import org.hibernate.annotations.Index;` 를 직접 입력했습니다.
JPA로 설정하면 프로젝트가 빌드될 때 마다 알아서 Index를 설정하기에 개발할 때 편했습니다.
성능 측정
저는 loginId 필드에 Index를 설정했습니다.
이유는 loginId는 값의 중복을 허용하지 않아 데이터 종류가 굉장히 많기 때문에 인덱스 설정 효과가 뛰어날거라 생각했기 때문입니다.
저는 User 데이터를 10만건으로 하여 성능 측정을 하였습니다.
측정을 위한 로직은 loginId로 조회하는 로직입니다.
SELECT * FROM users WHERE login_id = "dummyid1000";
Index 적용 전
2023-08-27 16:06:28.905 INFO 15704 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-08-27 16:06:28.906 INFO 15704 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2023-08-27 16:06:28.907 INFO 15704 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2023-08-27 16:06:29.668 INFO 15704 --- [nio-8080-exec-2] com.dotd.user.aop.LoggingAspect : 위치 : UserController.login(..) / 걸린 시간 : 215 ms
인덱스 적용하기 전은 215ms가 걸렸습니다.
Index 적용 후
2023-08-27 16:11:04.939 INFO 15704 --- [nio-8080-exec-5] com.dotd.user.aop.LoggingAspect : 위치 : UserController.login(..) / 걸린 시간 : 7 ms
인덱스 적용한 후에는 7ms가 걸렸습니다.
인덱스가 적용된 후 조회 성능이 엄청나게 향샹한 것을 확인할 수 있었습니다.
이처럼 인덱스는 빠른 데이터 검색을 가능하게 해주어 조회가 자주 일어나며 데이터 종류가 다양한 필드에 설정하면 엄청난 성능 향상을 기대할 수 있습니다.
하지만 인덱스는 추가적인 저장 공간을 사용하며 데이터를 삽입, 수정, 삭제하는 작업에는 성능 저하를 미칠 수 있습니다.
그러므로, 인덱스를 설정할 때는 이 필드에 어떤 작업이 많이 일어나는지 상황을 고려하여 적용하는게 좋습니다.
마치며
프로젝트를 진행하면서 여러 가지 성능 개선 방법을 공부하고 적용하고 있습니다.
이번에는 Index를 공부하여 적용했고 실제로 10만건에 데이터를 대상으로 확인해본 결과 뛰어난 성능 향상을 확인할 수 있었습니다.
이외에도 성능향상을 위해서 쿼리 튜닝, 캐싱 등 다양한 방법이 있습니다. 이 기법들을 학습하여 프로젝트에 필요한 부분에 적용하고 그 결과를 정리해서 올려보도록 하겠습니다.
감사합니다.