DELETE시 IN 사용
트러블 슈팅에서 DELETE IN 사용에 관한 내용을 다뤘다.
하지만, 해당 작업이 실제로 의미가 있는지가 중요하다.
따라서, 직접 서비스 구동시 DB에 데이터를 추가하여 성능이
얼마나 향상되었는지 확인하기 위한 작업을 진행했다.
작업 대상으로 삼은 API는 채널 삭제 API이다.
- 포럼 채널에 속해있는 포럼 100개
- 각 포럼과 연관되어 있는 파일 100개
- 포럼 100개, 파일 10000개로 구성
서비스 구동시 DB Init 코드
@Slf4j
@Component
@RequiredArgsConstructor
public class BatchTest {
private final UserRepository userRepository;
private final ServerRepository serverRepository;
private final ChannelRepository channelRepository;
private final CategoryRepository categoryRepository;
private final ForumRepository forumRepository;
private final UserServiceFakeClient userServiceFakeClient;
private final ServerUserRepository serverUserRepository;
private final FileRepository fileRepository;
@PostConstruct
public void dbInit(){
User user1 = User.of(userServiceFakeClient.getUser(1L));
User user2 = User.of(userServiceFakeClient.getUser(2L));
User user3 = User.of(userServiceFakeClient.getUser(3L));
User user4 = User.of(userServiceFakeClient.getUser(4L));
userRepository.save(user1);
userRepository.save(user2);
userRepository.save(user3);
userRepository.save(user4);
log.info("User dbInit 완료");
Server server1 = Server.of("test1", null, 1L);
Server server2 = Server.of("test1", null, 2L);
serverRepository.save(server1);
serverRepository.save(server2);
log.info("Server dbInit 완료");
ServerUser serverUser1 = ServerUser.of(server1, user1);
ServerUser serverUser2 = ServerUser.of(server2, user1);
ServerUser serverUser3 = ServerUser.of(server1, user3);
serverUserRepository.save(serverUser1);
serverUserRepository.save(serverUser2);
serverUserRepository.save(serverUser3);
log.info("ServerUser dbInit 완료");
Category category1 = Category.of(server1, "채팅");
Category category2 = Category.of(server1, "음성");
Category category3 = Category.of(server2, "채팅");
Category category4 = Category.of(server2, "음성");
categoryRepository.save(category1);
categoryRepository.save(category2);
categoryRepository.save(category3);
categoryRepository.save(category4);
log.info("Category dbInit 완료");
Channel channel1 = Channel.of(server1, 1L, ChannelType.CHAT, "채팅");
Channel channel2 = Channel.of(server1, 2L, ChannelType.VOICE, "음성");
Channel channel3 = Channel.of(server2, 3L, ChannelType.CHAT, "채팅");
Channel channel4 = Channel.of(server2, 4L, ChannelType.VOICE, "음성");
Channel forumChannel = Channel.of(server1, null, ChannelType.FORUM, "포럼");
channelRepository.save(channel1);
channelRepository.save(channel2);
channelRepository.save(channel3);
channelRepository.save(channel4);
channelRepository.save(forumChannel);
log.info("Channel dbInit 완료");
for(int i = 0; i < 100; i++){
Forum newForum = Forum.of(5L, "test" + i, user1, "test" +i, ForumCategory.CALORIE);
forumRepository.save(newForum);
for(int j = 0; j < 100; j++){
File file = File.of(newForum, "test" + j);
fileRepository.save(file);
}
}
log.info("Forum & File dbInit 완료");
}
}
위의 코드로 테스트하기 위한 임시 데이터를 삽입했다.
IN
을 사용하지 않은 그냥 deleteAll()
메소드를 사용한 경우
@OneToMany(mappedBy = "forum", orphanRemoval = true)
// @OneToMany(mappedBy = "forum")
private List<File> files = new ArrayList<>();
API 실행 결과
포럼 100개, 파일 10000개로 구성되어있는 경우 1.658s
의 Latency
와 10105
개의 쿼리가 나갔다.
이는 어마어마한 수치이다. 만약, 상용 서비스였다면 훨씬 더 많은 데이터가 있을 것이며 동시에 큰 문제로 이어질 수 있다.
심지어 위에서 작업한 코드는 테스트를 위해 S3
에 이미지가 올라가지 않은 File
엔티티를 사용한 코드다.
만약, S3
삭제 작업까지 더해진다면 상상도 하고 싶지 않다.
그렇다면 DELETE
시 IN
을 사용한다면 어떤 결과가 나올까?
DELETE
시 IN
을 사용한 경우
// @OneToMany(mappedBy = "forum", orphanRemoval = true)
@OneToMany(mappedBy = "forum")
private List<File> files = new ArrayList<>();
API 실행 결과
Latency
는 1/4
로 줄고 쿼리는 단 7
개만 나간다.S3
삭제 작업은 그대로 유지되겠지만, 나가는 쿼리의 개수가 말도 안되게 줄었다.
데이터가 많아질수록 그 차이는 제가 테스트 해본 방법보다 커질 것으로 예상된다.
앞으로는 이번에 알게 된 내용을 꼭 적용하여 성능 최적화를 위한 노력을 해야겠다.
'프로젝트 > FitTrip' 카테고리의 다른 글
[MSA] FitTrip에서 MSA 설계 With Spring Cloud (0) | 2024.07.14 |
---|---|
[커뮤니티 서비스] Redis를 활용한 초대코드 구현 (0) | 2024.07.05 |
[커뮤니티 서비스] 커뮤니티 서비스 기능정리 (0) | 2024.06.29 |
[트러블슈팅] 각 서비스의 로그 확인을 위한 로깅 시스템 구축 (0) | 2024.06.26 |
[트러블슈팅] 오픈바이두 클라이언트 연결 오류 해결 과정 (0) | 2024.06.25 |