데이터베이스에서 무작위 선택 : 성능 고려 사항 : 서버 서비스 로직 생성

ZEDY·2023년 10월 8일
0

[백엔드] Spring Boot

목록 보기
16/27

데이터베이스에서 무작위 선택: 성능 고려 사항

무작위로 3개의 레슨을 선택하는 쿼리

제가 짠 쿼리 입니다. 같은 카테고리에 자기 자신을 제외한 무작위로 3개의 레슨을 뽑는 경우를 쿼리문을 날려 디비에서 가져왔습니다.

SELECT * FROM lesson l WHERE l.category = ?1 AND l.id <> ?2 ORDER BY RAND() LIMIT 3

이 쿼리는 특정 카테고리(category)에 속하면서 현재 레슨(id)을 제외한 모든 레슨 중에서 무작위로 3개를 선택합니다.
?1 ?2는 파라미터를 의미하며, mysql에서는 RAND() 함수가 있기에 사용했습니다.

성능 이슈: 데이터베이스 스코프와 무작위 함수

데이터베이스에서 무작위 함수를 사용하여 레슨을 선택하면 성능 이슈가 발생할 수 있습니다. 이러한 성능 이슈는 데이터베이스 스코프(scope)와 관련이 있습니다.

무작위 함수를 사용하면 데이터베이스가 모든 레슨 행을 스캔하고 무작위로 정렬해야 합니다. 이 작업은 스코프가 작을 때는 그다지 큰 문제가 되지 않지만, 스코프가 커질수록 성능 문제가 발생할 가능성이 높아집니다.

서버에서 무작위 선택 고려

무작위 선택에 대한 성능 이슈를 고려할 때, 서버에서 이 작업을 수행하는 것이 더 나은 방법일 수 있습니다. 서버에서 레슨 데이터를 검색한 후, 무작위로 3개를 선택하는 방법을 고려할 수 있습니다.

즉, 무작위로 선택하는 로직을 서비스 단에서 짜면 됩니다. 이때 인덱스를 활용하면 됩니다.

서버에서 처리하는 경우, 데이터베이스의 스코프와 관계없이 무작위 선택을 수행할 수 있으며, 레슨 데이터를 미리 캐싱하여 더 빠른 응답 시간을 제공할 수도 있습니다.

나의 해결 방법

저는 다음과 같은 로직을 서비스단에 생성했습니다.

public List<RecommendLesson> getRecommendLessons(LessonCategory category, Long lessonId){
		// 레포지토리에 카테고리에 맞는 Lesson 중, 자신을 제외한 Lesson을 모두 가져오는 로직
        // 원래 인덱스로 계산하고 한번에 가져오려고 했음........
        List<Lesson> filteredLessons = lessonRepository.findByCategoryNotCurrent(category, lessonId);

        // 무작위로 선택할 레슨의 개수
        // 위에 필터된 레슨의 크기가 작으면 그걸로 설정됨
        int numRandomLessons = Math.min(3, filteredLessons.size());

        List<Lesson> randomLessons = new ArrayList<>();
        Random random = new Random();

        while (randomLessons.size() < numRandomLessons) {
            int randomIndex = random.nextInt(filteredLessons.size());
            Lesson randomLesson = filteredLessons.get(randomIndex);

            // 중복된 레슨을 선택하지 않도록 필터링
            if (!randomLessons.contains(randomLesson)) {
                randomLessons.add(randomLesson);
            }
        }

        return randomLessons.stream()
                .map(RecommendLesson::new)
                .toList();
    }

결론

무작위로 데이터를 선택하는 경우, 데이터베이스에서 처리할 때 성능 이슈를 고려해야 합니다. 스코프가 큰 경우, 서버에서 무작위 선택을 수행하는 것이 더 효율적일 수 있습니다. 데이터베이스와 서버 간의 작업 분배를 고려하여 최적의 성능을 얻을 수 있도록 설계하는 것이 중요합니다.


profile
Spring Boot 백엔드 주니어 개발자

0개의 댓글