일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 자료구조
- 디자인 패턴
- MySQL
- Heap
- Kafka
- mongoDB
- c언어
- JPA
- 운영체제
- 네트워크
- OS
- 파이썬
- Galera Cluster
- 백준
- Data Structure
- 컴퓨터구조
- react
- IT
- Algorithm
- JavaScript
- spring webflux
- 자바
- Proxy
- MSA
- Spring
- design pattern
- Java
- redis
- 알고리즘
- C
- Today
- Total
시냅스
그래서 싸우면 누가 이기는데? (MySQL, MongoDB 성능 비교) 본문
개인적 차원에서 MySQL 과 MongoDB 의 Select 성능 비교를 수행한 글 입니다.
따라서 전혀 신뢰할 수 없으며, 참고용으로만 봐주시길 바랍니다.
https://github.com/taesukang-dev/rdb-and-nosql
최근 대용량의 로그를 처리할 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 를 사용하는 것은 동일함에도 성능 차이는 어디에서 오는 것인지...
끝!