2023년 01월 7일
오늘은 실무에서 이야기했던 내용들을 정리하려고 합니다.
[상황발생]
운영하는 웹사이트가 4년 동안 1개의 테이블에 1억 개의 row를 적재하고 있습니다.
문제
- 많은 데이터를 조회하기 때문에 부하 및 슬로우 쿼리가 발생합니다.
- 요청사항으로 1년치, 분기마다 데이터를 정제해서 엑셀로 다운받고 싶어합니다.
한 달치 데이터를 조회하는 것조차 슬로우 쿼리와 부하가 발생하는데, 이를 어떻게 해결해야 할지 많은 고민을 했지만 확실한 해답을 찾지 못하여 다른 개발자와 회의를 진행하게 되었습니다.
[해결방법]
- RDBMS로 1억 개를 조회해서 슬로우 쿼리와 부하가 발생하는 것은 샤딩, 파티션 분할로 충분히 해결 가능하다고 생각합니다. 이를 하둡이나 몽고DB로 전환하는 것은 닭 잡는 데 소 잡는 칼을 사용하는 것과 같습니다.
- 현재 ORM을 사용하는데, 조회하는 부분은 mybatis로 변경하고 DBA분과 인덱싱, 튜닝을 하는 것이 정답인 것 같습니다.
- [일괄 데이터 처리] 위에 언급한 테이블을 업데이트할 때마다 API를 전송해야 되는데, 이를 일괄로 처리하고 있습니다. 일반 유저를 대상으로 하는 웹사이트가 아니기 때문에 쓰레드로 하는 것이 맞다고 생각하는데, 일반 유저가 사용하는 부분이라면 비동기 방식으로 작업을 진행해야 합니다.
샤딩
DB분산처리를 위한 sharding | 우아한형제들 기술블로그
LINE Manga 데이터베이스 샤딩 - 데이터베이스 엔지니어 편
파티션
[후기]
첫째로 든 생각은, 제가 좀 더 프로젝트의 환경과 소스를 잘 이해하고 있어야 한다는 것이었습니다. 서로 이야기를 진행하는데, 상대방이 물어봤을 때 '원하는 대답을 해줄 수 있었을까?'라는 생각을 하였습니다. 상대방은 궁금한 대답을 듣기 위해 질문을 하는 것인데, 질문을 받았을 때 시원하게 대답해주지 못할 것 같다는 생각이 들었습니다. 좀 더 프로젝트의 환경과 소스를 이해하는 부분이 필요합니다. 웹사이트의 환경, WAS, 웹 서버의 구조 등에 대한 지식이 많이 필요합니다.
둘째, 경험이 많이 부족하다고 느꼈습니다. RDB의 문제인지 ORM의 문제인지 정확하게 파악하지 못했다는 것입니다. 데이터가 많다고 RDB의 문제인 것은 아닙니다. DBA와 이야기를 해보는 것도 하나의 좋은 해결 방법이 될 수 있습니다.
오늘은 처음으로 외부의 해박한 개발자와 회의를 진행하였는데, 아직도 배울 것은 많고 해야 할 것도 많다고 생각하였습니다. 더 열심히 해보겠습니다.
2023년 3월 06일
오늘은 DB 메모리가 93%로 가득 찬 상황이 발생했습니다. 기존에 프로젝트를 만들 때 예상 수치보다 너무 높은 데이터가 유입되었고(한 달에 30만 건이 유입될 것을 기준으로 프로젝트를 진행), 평균적으로 하루에 30만 건 정도의 데이터가 유입되는데도 삭제 정책이 마련되지 않았습니다. 이 때문에 데이터가 계속 쌓였고, 결국 93%까지 차는 상황이 발생했습니다.
해결방법
- 일단은 과거의 히스토리 데이터를 삭제하는 방법으로 메모리 여유를 만들고
- 기획자분들과 의견을 조율해서 삭제 정책을 마련합니다.
- 삭제 정책에 따른 개발을 착수합니다.
작업을 진행하면서 배웠던 점
- 데이터를 delete하면 용량이 늘어날 것으로 기대했지만, delete문으로는 용량이 늘어나지 않습니다. 이는 데이터가 직접 삭제되는 것이 아니라 삭제되었다고 표기해두고, 새로운 데이터가 들어왔을 때 표기한 데이터 위에 덮어쓰는 방식이기 때문입니다. 이를 해결하려면 alter문과 테이블 재구성이 필요합니다.
- 파티셔닝을 하면 데이터를 삭제할 때 유리합니다. 파티션 단위로 나누어 놓으면 해당 파티션만 삭제하면 되기 때문입니다. 파티셔닝을 하지 않고 데이터를 삭제할 때는 alter문을 작성해야 하고 테이블 재구성이 불가피하게 발생합니다. 따라서 파티셔닝을 해야 할 때는 삭제 정책과 보관해야 하는 기간을 미리 알아두는 것이 유리합니다.
- 기획자와 이야기를 진행하였는데, 데이터를 유지하면서 보관하는 방법에 대해 이야기하였습니다. 하지만 계속되는 데이터 적재 문제로 DB 관련 부서에서는 삭제를 해야 한다는 쪽으로 이야기가 진행되면서 업무가 진행되지 않았습니다. 이를 해결하기 위해 유의미한 데이터는 인덱스의 날짜를 변경하여 데이터를 올리고, 불필요한 데이터는 삭제하는 방식으로 파티셔닝을 나누는 방법을 선택하였습니다. 이렇게 하면 유지할 데이터는 최신 날짜로만 업데이트되어 보관될 수 있으며, 불필요한 데이터는 삭제되면서 메모리 부족 문제도 해결할 수 있습니다.
파티셔닝 인덱스 → idx_createAt 때문에 불필요한 데이터는 그대로 유지, 필요한 데이터는 최신 날짜로 업데이트
이렇게 하면 유지한 데이터는 최신 데이터와 별개로 파티셔닝이 분리되기 때문에 삭제하기가 편해집니다.
현재 데이터
| 1 | 2021-02-01 | 유의미한 데이터 |
|---|---|---|
| 2 | 2021-02-02 | 불필요한 데이터 |
| 3 | 2021-02-03 | 유의미한 데이터 |
변경 데이터
| 1 | 2023-02-01 | 유의미한 데이터 |
|---|---|---|
| 2 | 2021-02-02 | 불필요한 데이터 |
| 3 | 2023-02-03 | 유의미한 데이터 |
불필요한 데이터와 유의미한 데이터가 파티셔닝으로 나뉘어 있으므로, 과거 데이터 파일을 삭제하기만 하면 됩니다. 이와 같은 작업을 java batch로 계속 진행합니다.
후기
오늘은 DB 메모리 적재 문제에 대해서 작성하게 되었습니다. 직접 작업을 진행하지는 않았지만, 옆에서 회의 및 해결 방법을 듣고 이해하는 것만으로도 다음에 발생하는 문제에 대해 미리 생각할 수 있었고, 차후에 이러한 문제가 발생할 때 어떻게 대처하면 좋을지 배울 수 있어서 좋았던 것 같습니다.
댓글
GitHub 계정으로 로그인하시면 댓글과 질문을 남기실 수 있습니다. 남겨 주신 글은 이 저장소의 Discussions에 쌓입니다.