시냅스

그래서 싸우면 누가 이기는데? (MySQL, MongoDB 성능 비교) 본문

데이터베이스

그래서 싸우면 누가 이기는데? (MySQL, MongoDB 성능 비교)

ted k 2024. 4. 24. 21:53
개인적 차원에서 MySQL 과 MongoDB 의 Select 성능 비교를 수행한 글 입니다.
따라서 전혀 신뢰할 수 없으며, 참고용으로만 봐주시길 바랍니다.

 

 

https://medium.com/@rsk.saikrishna/when-to-use-mongodb-rather-than-mysql-d03ceff2e922

 

 

https://github.com/taesukang-dev/rdb-and-nosql

 

GitHub - taesukang-dev/rdb-and-nosql

Contribute to taesukang-dev/rdb-and-nosql development by creating an account on GitHub.

github.com

 

최근 대용량의 로그를 처리할 Database 가 필요하게 되었습니다.

한달에 약 1억건 정도를 핸들링해야하고 일정기간이 지나면 데이터를 만료시키거나 (TTL)

로그 데이터이므로 대체로 CR 만 수행하고 시간 별로 (Time Series) 저장하는 편이 좋을 것 같다는 생각이었습니다.

 

위의 특성들로 보아 재채기하듯 MongoDB!! 라는 결과를 도출해내었지만 직접 성능을 비교해본 적이 없었습니다.

Scale-out이 쉬운, 비정형의, 대용량의, 빠른 처리를 지원하는 Database 임을 알고 있지만 눈으로 확인하고 싶었습니다.

 

 

테스트 환경

실행 환경은 다음과 같습니다.

  • machine
    • CPU : 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz
    • RAM : 16GB 
    • OS : Windows
  • 데이터 천만 건 기준 (MySQL : Record 천만건, MongoDB : Document 천만건)
  • DDL (MongoDB 에도 비슷하게 저장하였음)
create table test_log(
	id serial,
    title varchar(255),
    content varchar(255),
    author varchar(255),
    created_at timestamp,
    primary key(id),
    index (title),
    index(created_at)
);
  • 실행 계획
    • 단순 select
    • PK Select
    • Index 가 없는 Column Select
    • Index 가 있는 Column Select
    • Paging
    • 시간을 기준으로 Range 탐색

대량의 데이터를 select 할 때 어떻게 되는지 궁금했습니다.

필요로 하는 결과는 클라이언트에 응답 할 때의 성능이기 때문입니다.

물론 검색이나 비쥬얼라이징을 하기에 ELK stack 이 더 낫겠지만 요구사항에서는 오버스펙이라는 판단이었습니다.

따라서 게시판 정도의 성능을 비교하기로 하였습니다.

 

 

테스트 결과

  • 아래 테스트는 caching, machine 상태, buffer pool 상태 등 운영 환경에 따라 상이할 수 있으므로 신뢰되지 않습니다.
  • 데이터는 MySQL, MongoDB 각각 10,000,000 건을 저장해두었습니다.
  • 1 - (빠른 응답 / 느린 응답) * 100 으로 얼마나 빠른지 계산하였습니다.
  • 각 실행 계획은 3번 씩 테스트한 값의 평균을 내었습니다.
  • 걸린 시간에 대한 산정은 아래와 같이 응답을 하며 기록하였습니다.
public Flux<TestLog> findAllMongo() {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    return logMongoService.findAll()
            .doOnComplete(() -> {
                stopWatch.stop();
                log.info("Data fetch duration: {} s", stopWatch.getTotalTimeSeconds());
            });
}
  • 쿼리
    • 단순 select
      • select * from tb_test;
    • PK Select
      • select * from tb_test where id = ?;
    • Index 가 없는 Column Select
      • select * from tb_test where no_indexed_column = ?;
    • Index 가 있는 Column Select
      • select * from tb_test wehre indexed_column = ?
    • Paging
      • select * from tb_test limit 0, 10;
      • select * from tb_test where created_at between :start and :end limit 0, 10;
    • 시간을 기준으로 Range 탐색
      • select * from tb_test wehre created_at between :start and :end;

 

실행 계획 MongoDB MySQL 우세
단순 Select (천만건 모두 fetch) 140s Exception MongoDB 우세
PK Select 평균 0.067s 평균 0.01s MySQL 85%
Index 가 없는 Column Select 평균 4.5s 평균 7.8s Mongo 42%
Index 가 있는 Column Select 평균 0.0053s 평균 0.205s Mongo 97%
Paging 평균 0.59s 평균 1.1925s Mongo 50.52% 
시간을 기준으로 Range 탐색 평균 1.8s 평균 2.03s Mongo 11%

 

위 테스트에서 특이사항은 MySQL 에서 AsyncRequestTimeoutException 으로

데이터 천만건 모두를 http response 로 내보내지 못했다는 점 입니다.

(Timeout 관련 설정을 해보았으나 해결되지 않아 다시 찾아봐야 할 것 같습니다.)

따라서 단순 Select, 천만건 모두를 http response 로 내보내는데 MySQL 의 경우 결과값을 내지 못했습니다.

몽고는 시간이 꽤 걸렸지만 (많은 양의 데이터이므로 당연하게도...) http response 를 받을 수 있었습니다.

 

 

결론과 참고

  • 대체로 MongoDB 의 성능이 우수하였습니다.
  • 따라서 대량의 데이터를 핸들링 할 때에는 몽고DB를 더욱 적극적으로 사용하게 될 것 같습니다.
    • 스키마가 없어도 되고, 테이블간 join 이 필요하지 않고 
    • BASE, MVCC, TRANSACTION 도 지원하고 sharding이 간편하니 굉장한 장점
    • 물론 String Consistency 를 요구할 경우, 데이터 변경이 자주 있는 경우에는 사용하기 어렵겠지만!
  • MongoDB 는 Auto Sharding 을 지원하며 간편한 Scale-Out 이 가능합니다.
    • 따라서 sharding 하게 된다면 위의 성능 격차는 벌어질 것입니다.
  • 데이터 / 클라이언트가 많아질 수록 성능 격차는 더 벌어지는 결과를 보여줍니다.
  • 그럼에도 여전히 갖고 있는 궁금증은 남아 있습니다. (남아 있는 궁금증들은 해결이 되면 update 하도록 하겠습니다!!!)
    • Index, Record(Document) 를 저장할 때 b tree 를 사용하는 것은 동일함에도 성능 차이는 어디에서 오는 것인지...
      • bson 으로 저장하면서 io 시에 cost 가 낮아지는 것인지...
        • rdb 에서 record 는 page, tablespace 등 고려할 것 들이 늘어나기 때문에...
        • bson 은 byte 로 변환해서 offset 주고 때려 넣으면 될 것 같다는 생각...
      • 추가로 MongoDB 는 index 를 caching 할 때 caching 에 적합한 데이터 구조로 변경하는 걸로 알고 있고 이걸로 압축률이 높다고 알고 있음
      • 또, MongoDB 는 memory 에 data 를 갖고 있다가 disk flush 시점은 비동기적으로 실행됨 (이건 MySQL도 마찬가지긴 함, change buffer, redo log...)
    • pk select 할 때에는 MySQL 이 더 우세했는데 이는 clustering key 로 저장 / 동작 되기 때문 아닐지...

 

끝!

Comments