| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | 
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | 
| 30 | 
- 백준
 - 컴퓨터구조
 - design pattern
 - Algorithm
 - Heap
 - 네트워크
 - Spring
 - 알고리즘
 - OS
 - 디자인 패턴
 - MySQL
 - Kafka
 - c언어
 - 파이썬
 - JPA
 - IT
 - C
 - Java
 - 운영체제
 - JavaScript
 - spring webflux
 - redis
 - MSA
 - 자료구조
 - Galera Cluster
 - mongoDB
 - Proxy
 - Data Structure
 - 자바
 - react
 
- Today
 
- Total
 
시냅스
그래서 싸우면 누가 이기는데? (MySQL, MongoDB 성능 비교) 본문
개인적 차원에서 MySQL 과 MongoDB 의 Select 성능 비교를 수행한 글 입니다.
따라서 전혀 신뢰할 수 없으며, 참고용으로만 봐주시길 바랍니다.

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;
 
 
 - 단순 select
 
| 실행 계획 | 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...)
 
 - bson 으로 저장하면서 io 시에 cost 가 낮아지는 것인지...
 - pk select 할 때에는 MySQL 이 더 우세했는데 이는 clustering key 로 저장 / 동작 되기 때문 아닐지...
 
 - Index, Record(Document) 를 저장할 때 b tree 를 사용하는 것은 동일함에도 성능 차이는 어디에서 오는 것인지...
 
끝!