언어, 프레임워크/Spring
대용량 데이터에서의 성능 최적화
go_getter
2025. 5. 19. 02:04
DB에서의 성능 최적화
1. 인덱스 적용
- where, join, order by에 자주 사용되는 컬럼에 인덱스를 적용한다.
- 인덱스가 너무 많으면 성능이 저하된다.
- 고유한 값에 인덱스를 적용하는 것이 효율이 좋다.
> MySQL 기준 인덱스 적용하기
-- 단일 컬럼 인덱스
CREATE INDEX index_name ON table_name (column_name);
-- 다중 컬럼(복합 인덱스)
CREATE INDEX index_name ON table_name (column1, column2);
복합 인덱스의 경우 왼쪽부터 차례대로 사용되는 경우에만 활용되며 왼쪽 정렬 원칙(Left-most Prefix Rule) 이라고 부른다.
> JPA에서 인덱스 적용하기
@Entity
@Table(name = "users", indexes = {
@Index(name = "idx_user_name", columnList = "name"), // 인덱스명 생략 가능
@Index(name = "idx_user_name_age", columnList = "name, age")
})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
}
@Column(unique = true) // unique 설정한 필드는 자동 인덱스 생성
private String email;
spring.jpa.hibernate.ddl-auto=create # 또는 update
2. 정규화 ↔ 비정규화 판단
- 조회 성능이 더 중요하다면 부분 비정규화 고려
- ex. 조인 줄이기 위해 중복 데이터 허용
- 데이터 무결성이 중요하면 정규화 유지
3. CQRS + Eventual Consistency
- 쓰기 DB와 읽기 DB를 분리 → 확장성과 성능 개선
- 이벤트 기반 비동기 동기화로 최신성 유지
4. Batch Insert / Update 처리
- 대량 쓰기 작업 시, 루프보다 batch 처리로 성능 향상
5. Partitioning / Sharding
- 테이블이 너무 커질 경우, 수평 파티셔닝 또는 DB 샤딩 적용
6. 데이터 보관 주기 및 이력 분리
- 오래된 데이터는 히스토리 테이블로 분리하여 조회 성능 확보
서비스에서의 성능 최적화
1. 캐싱
- 조회 빈도 높은 데이터는 Redis 등 인메모리 캐시로
- 캐시 무효화 정책 설계 중요 (TTL, 수동 삭제 등)
2. 조회 쿼리 튜닝
- N+1 문제 방지 (JPA fetch join, DTO projection, query DSL 등)
- 페이징 처리 시 count() 최적화 고려
3. 비동기 처리 / 메시지 큐 활용
- 처리 시간이 오래 걸리는 작업은 MQ 또는 비동기 처리
- 예: Kafka, RabbitMQ
4. 서비스 로직 단순화
- 복잡한 계산 로직은 별도 비동기 처리 또는 저장된 결과 사용
5. 지속적인 모니터링과 병목 분석
- APM 도구(NewRelic, Pinpoint, Datadog 등) 사용해 병목 추적
- 쿼리 슬로우 로그, GC 로그 분석 병행