채용공고에 대용량 데이터 처리 의 활용 능력을 보는 회사들을 많이 볼 수 있다. 이 글은 내가 개인적 프로젝트 진행 시 .csv, DuckDB, Pandas 를 사용하며 다뤘던 데이터의 양이 많아질 때 다룰 수 있는 방법에 대해 알아보기 위해서 쓰는 글이다.
개인 프로젝트에서는 기껏해야 5천만건. 그것도 많아서 (더러운) 쿼리가 조금만 길어지면 응답이 길어지고, 심지어 안되는 경우가 있는데 실무에서 수억개의 데이터 로그를 LIMIT 제한을 걸지 않고 날리게되면 엄청난 부하가 걸리는 점을 인지한다.
대용량 데이터 처리
1. 문제점
- 메모리 내에서 계산 불가능
- 메모리를 올리지 않으면 기본적으로 디스크를 계속 읽어가면서 검색하게 되어 발견 불가능과 동시에 데이터 건수가 많으면 계산량이 많아지는 것보다 더 중요한 것은 디스크를 많이 읽고 있다는 점이다.
📌 메모리 VS 디스크
- 메모리 내의 특정 번지에 있는 데이터를 찾는 데이터 검색
- 디스크의 특정 원반에 있는 데이터를 찾는 데이터 검색
- 메모리가 디스크보다 몇 백만배는 더 빠르다.
Why? 디스크는 여러개의 판으로 이루어져있고, 헤더가 그 판을 트랙마냥 읽으며 정보를 읽는다. 따라서 정보를 읽어오기 위해서, 헤더의 이동과 원반의 회전 이라는 두가지 물리적인 이동이 필요.
- os는 이것을 어느 정도 커버하는 작용. 연속된 데이터를 같은 위치에 쌓으며, 데이터를 읽을 때 한꺼번에 한 단위의 데이터를 읽어옴.
- 탐색속도 뿐 아니라 전송속도도 차이
- 메모리 to CPU : 7.5GB/s
- 디스크 to 메모리 : 58MB/s
2. 규모조정의 요소
- 메모리와 디스크의 속도차는 데이터가 커지면 커질 수록 커짐. 대규모 환경이라고 하면 서버를 여러 대 나열해 놓고 그 서버로 부하를 분산한다라는 얘기를 들엇을텐데, 웹 서비스에서 자주 거론되는 규모조정(scaling), 확장성(scalability)가 그런 종류이다.
- 고가의 빠른 하드웨어를 사서 성능을 높이는 스케일업 전략 보다도, 저가이면서 일반적인 성능의 하드웨어를 많이 나열해서 시스템 전체 성능을 올리는 스케일아웃(scale-out) 전략이 주류. 스케일아웃 전략이 더 나은 이유는 웹 서비스에 적합한 형태이고 가성비가 좋다는 점이다.(10배 비싼 하드웨어가 10개 더 빠르지 않음)
- 스케일아웃을 통해 CPU 부하의 확장성을 확보하는 것은 쉽다. DB에 질의하고 응답 데이터를 가공해서 HTTP로 반환하는 것은 기본적으로 CPU의 몫. 하지만, I/O 부하를 해결하기 위해 스케일 아웃을 이용하면 동기화의 문제가 생김. 즉, write 하는 행위를 간단하게 분산할 수 없다.
- 서비스가 무거우니 서버를 늘리는 것은 어때? 라는 제안은 사실 서버를 늘려서 해결할 수 없고, 이런 동작은 CPU 부하를 해결해 줄 순 없지만 I/O 부하를 해결해주진 못함.
대용량 데이터를 다루기 위한 기초 지식
대용량 데이터 처리 기본원리
-
기본적인 원리는 데이터를 분산시켜 처리하는 것이다. 이는 데이터베이스 샤딩, 캐시 도입, 메시지 큐 사용 등 다양한 방법으로 구현된다. 이러한 방법들은 데이터 처리 부하를 분산시켜 시스템의 전반적인 성능 향상을 한다.
-
예를 들어, 레디스는 사용한 캐싱을 자주 접근하는 데이터를 메모리에 저장하여 DB의 부하를 줄이는 효과적인 방법. 왜냐하면 메모리 접근 속도 > 디스크 접근 속도
-
메시지 큐를 활용한 비동기 처리는 시스템의 응답성을 높이고, 부하를 분산시키는 데에도 유용. 왜냐하면 메시지 큐를 통해 처리해야 할 작업들을 분산시켜 병렬 처리 할 수 있기 때문이다.
멀티 모듈 설계
1. 용이성
- 대규모 애플리케이션 개발에 있어서 모듈화를 통한 관리의 용이성 제공. 멀티 모듈 설계를 통해 각 기능별로 모듈을 분리함으로써 코드의 가독성과 유지보수성이 향상 됨
- 스프링 부트 애플리케이션에서 멀티 모듈 설계를 적용하면, 공통 모듈, 도메인 모듈, 서비스 모듈 등으로 구분하여 개발 가능.
2. 실제 사례
- 대용량 데이터 처리를 위해 레디스 캐시와 메시지 큐를 도입. 사용자의 요청을 효율적으로 처리하기 위해 레디스를 사용하여 자주 접근하는 데이터를 캐싱하고, 메시지큐를 통해 비동기 처리 구현.이 방법을 통해 DB의 부하를 줄이고 시스템의 응답성 향상.
3. 구현 방법
- 주로 빌드 도구를 사용. 예를 들어, Gradle 이나 Maven과 같은 도구를 사용하여 각 모듈의 의존성 관리와 빌드 과정을 자동화 할 수 있다. 이러한 도구들은 멀티 모듈 프로젝트의 구성과 관리를 위한 다양한 기능을 제공한다.
- 또한 모듈 설계는 마이크로 서비스 아키텍처로의 전환을 용이하게 함. 왜냐하면 각 모듈을 독립적인 서비스로 분리하여 개발하고 배포할 수 있는 기반을 마련하기 때문이다.
효율 좋은 쿼리
📌 SQL 쿼리를 효율적으로 짜는 것? = 빨리 돈다, 메모리를 덜 쓴다.
빨리 돌고, 메모리를 덜 쓴다? = 필터링을 많이 한다.(join, group by 하는 데이터 최소화)
즉, 대용량의 데이터일 수록 데이터를 작게 만들어야 하는 것이 중요하다.
1. 데이터를 작게한다.
- 데이터를 한번에 잘라낼 수 있게
- 작은 데이터가 join 되고 group by 가 될 수 있도록
2. WHERE/GROUP BY
- 두 개 이상 테이블 join 시, join 전에 where/group by 등의 조건을 각각 테이블에 넣기
- join, group by 의 성능이 나아질 수 있다.
- 각 테이블에서 미리 group by 하고 join
3. 한번에 많은 JOIN NO!!
- 예를 들어 3개 테이블이 조인이 필요하다면 3개 테이블을 한번에 하는 것보다 2개 먼저하고, 후에 메인테이블과 한번 더 하는것이 효율적!!
- DBMS 가 가장 힘들어 하는 것은 JOIN이다. 따라서 필터를 해서 데이터를 많이 줄이고 필요한 데이터만 조인해서 붙여넣고 결과를 내는 것이 중요하다.
4. 너무 짧은 쿼리 NO!!
- 효율 관점에서 WINDOW 함수 같은 경우 Hive에서 돌아갈 때 느리다.
- rank 함수를 사용하게 되면, 전체 데이터를 한번 sorting을 해야하는 부분이 있어서, 메모리 관점에서 부하가 높고, 시간이 오래 걸리는 작업이다.
- rank 함수 대신 order by 로 정렬하고 limit 로 원하는 만큼 잘라 오는것이 쿼리는 더 길어지더라도, 효율적인 측면에서 더 좋음
- limit 을 사용하면 100번째에서 중지할 수 있고, rank하면 전체 테이블 sorting
- order by 와 limit을 사용한 쿼리가 window 함수를 쓴 짧은 쿼리보다 좋음
시퀀스와 시계열의 공통점과 차이점
시간을 갖고 있다는 공통점
시계열은 연속적이고 시퀀스는 비연속적
시퀀스데이터가 더 큰 개념. 주기는
주기는 시간을 떨어뜨려 놓고 말 할 수 없다.
시간은 결국에
결론
대용량 데이터 처리와 멀티 모듈 설계는 현대 웹 서비스 개발에서 중요한 요소이다. 왜냐하면 이를 통해 시스템의 성능을 향상시키고, 코드의 유지 보수성을 높이기 때문이다.
기술적인 문제 해결뿐만 아니라 사용자의 요구를 충족시키는 서비스를 제공하는 것이 최종 목표이다.