저고데

[ElasticSearch] 2. 관계형 데이터베이스와 엘라스틱 서치 성능 비교하기 본문

ElasticSearch

[ElasticSearch] 2. 관계형 데이터베이스와 엘라스틱 서치 성능 비교하기

진철 2024. 1. 29. 21:30
728x90
반응형

이번 시간에는 엘라스틱 서치와 관계형 데이터베이스 간의 성능 차이를 비교해보도록 하자.

공통 실험 배경은 다음과 같다.

각각의 데이터베이스에 14883개의 User 데이터를 저장한다.

User 객체는 id, name, age의 columm을 가지고 있다.

// 엘라스틱 서치에 데이터를 추가하는 코드
@GetMapping("/elasticadd")
public String addUser() {
    for (int i = 0; i < 14884; i++) {
        User user = new User();
        user.setId(String.valueOf(i));
        user.setName("temp"+String.valueOf(i));
        user.setAge(i);
        userService.saveUser(user);
    }
    return "redirect:/";
}
// 관계형 데이터베이스에 데이터를 추가하는 코드
@GetMapping("/rdbmsadd")
public String addrdbmsUser() {
    for (int i = 0; i < 14884; i++) {
        UserJPA user = new UserJPA();
        user.setId(String.valueOf(i));
        user.setName("temp"+String.valueOf(i));
        user.setAge(i);
        userJPAService.saveUser(user);
    }
    return "redirect:/";
}

위의 코드를 통해서 각각의 DB에 데이터를 저장한다.

@Repository
public interface UserRepository extends ElasticsearchRepository<User, String> {
    List<User> findByName(String name);
    @Query("{\"wildcard\":{\"name.keyword\":\"*?0*\"}}")
    List<User> findByNameWildcard(String name);
}
@Repository
public interface UserJPARepository extends JpaRepository<UserJPA, String> {
    List<UserJPA> findByName(String name);
    List<UserJPA> findByNameContaining(String name);
}

그리고 각각의 레포지토리를 다음과 같이 정의한다.

JPA의 경우에는 spring에서 제공하는 JpaRepository에서 SQL의 'like' 연산자로 검색을 할 수 있는 메서드를 제공하는 반면, 엘라스틱 서치는 그렇지 않다.

따라서 @Query 어노테이션을 통해서 json 형태로 검색을 하도록 한다.

@Query는 Elasticsearch에서 사용하는 Query DSL(Query Domain Specific Language)을 지정할 수 있다.

그 중에서도 필자는 Wildcard Query를 사용하였는데, 이는 와일드카드를 사용하여 부분적으로 일치하는 문서를 검색할 때 사용된다.

여기서 name.keyword는 Elasticsearch 매핑에서 사용되는 필드 이름이며, *?0*은 와일드카드 패턴이다.
(* : 임의의 문자열과 일치할 때, ? : 정확히 한 문자와 일치할 때, 0 : 매개변수로 전달된 값으로 대체할 때)

@GetMapping("/findelastic")
public List<User> findUser(@RequestParam String name) {
    List<User> users = userService.findByNameWildcard(name);

    return users;
}

@GetMapping("/findrdbms")
public List<UserJPA> findJPAUser(@RequestParam String name) {
    List<UserJPA> users = userJPAService.findByNameContaining(name);

    return users;
}

그리고 포스트맨을 통해서 데이터를 검색했을 때의 검색 시간을 구하기 위해서 다음과 같은 api 접근 컨트롤러를 추가하고

http://localhost:8080/api/users/findelastic?name=temp14

http://localhost:8080/api/users/findrdbms?name=temp14

위의 get 요청을 통해서 이름이 temp14를 포함하는 데이터를 검색하게 한다.

근데 ... 예상과 다르게 엘라스틱 서치가 더 시간이 오래걸린 것을 확인할 수 있다.

왜 그렇지 ㅠㅠㅠ

라고 생각하고 검색을 해보았다.

일단 이건 추측인데, 아마 데이터가 다양하지 않고 temp1, temp2, ... temp10000처럼 단순해서 그렇지가 않나 생각이 든다.

관계형 데이터베이스에서 검색을 담당하는 'like' 연산자의 경우, for문의 방식과 유사한 걸로 알고 있다.

따라서, 쿼리문이 복잡하지 않고 너무 단순해서 그렇지 않나 생각한다.

 

아무튼 오늘은 엘라스틱 서치와 관계형 데이터베이스 간의 검색 성능 차이를 알아보았다. (물론 내가 생각한 것과 달랐지만 ..)

다음 시간에는 엘라스틱 서치를 통해 어떻게 검색 엔진을 만드는 지에 대해서 알아보도록 하겠다.

 
 

 

728x90
반응형