PyMongo 를 이용하여 마이그레이션 스크립트 작성하기 (2)

·2020년 8월 29일
0

Database

목록 보기
2/2

지난 포스팅을 쓴 후, 막상 라이브와 유사한 환경에서 테스트를 진행하고 나니 좋은 현상, 나쁜 현상 하나씩을 얻게 되어 뜻하지 않게 2 편을 포스팅하게 되었다.

🔗 PyMongo 를 이용하여 마이그레이션 스크립트 작성하기 1편

😆 DB 에 부담이 많이 가는 작업이 아니다

몽고가 또 터지기 직전까지 가는 것은 아닐까 걱정 또 걱정하며 떨리는 마음으로 스크립트를 실행시켰는데,

인덱스를 걸고 read preference 를 secondary preferred 로 설정한 효과가 있었는지 걱정했던 것에 비해 DB 에 무리가 가지 않았다.

😞 생각보다 시간이 오래 걸린다

사실 스크립트를 다 돌리는데 얼마나 시간이 걸릴지는 고려하지 않았었는데 (어차피 새벽 작업일테니) 막상 테스트를 해보니 생각보다 시간이 많이 소요되었다. (아무리 새벽 작업이라도 끝나고 잘 시간은 있어야지)

💡 100배(?) 빠르게!

생각보다 몽고가 잘 버텨주는 상황이라면, 좀 더 query 요청을 해도 괜찮겠다고 생각되어 한 명 한 명 동기적으로 처리하던 부분을 파이썬의 concurrent.futures 모듈에서 제공하는 ThreadPoolExecutor 를 이용하여 비동기적으로 수정해보았다.

  • 병렬적 처리를 위해 멀티스레드, 멀티프로세스를 이용하여 스레드나 프로세서를 제어하곤 한다. 관련 모듈로 threading.thread 와 multiprocessing.process 가 있는데 이 모듈들은 스레드, 프로세스를 생성하고 실행하는 것만 담당하고 있다보니 처리된 결과를 메인 스레드로 다시 전달하는 등 스레드 간의 전달을 위해서는 또 별도 처리가 (queue, 소켓, 파이프 등등) 필요해서 사실상 사용이 까다로웠다고 한다.

  • 3.2 부터 도입된 concurrent.futures 모듈은 스레드/프로세스 사이의 데이터 교환을 쉽게 처리하기 위해 Future 개념을 도입하였다. (자바스크립트에서 비동기 작업을 실행하면 Promise 객체를 반환받는 것과 유사해보였다.) 이 Future 객체를 통해 별도 스레드에서 실행되는 작업의 상태 (아직 실행 중, 혹은 작업 완료) 를 확인할 수 있고 완료되었을 경우 결과 값도 받아올 수 있다.

  • concurrent.futures 에서 병렬 작업을 실행하기 위해서는 Executor 객체를 이용한다. 이름 그대로 스레드/프로세스를 생성하고, 작업을 스케줄링하는 역할인데 실제 사용을 할 때는 Executor 의 서브 클래스인 ThreadPoolExecutor 와 ProcessPoolExecutor 를 사용한다.

  • 나는 여러 doc 을 조회한 후 조회된 doc 내 특정 필드들의 총 합을 필요로 했는데 총 합을 계산하는 작업까지 몽고의 aggregation pipeline 에서 진행하고 있었다. 즉 CPU 연산 보다는 IO 기반 작업이었기 때문에 ThreadPoolExecutor 를 이용하였다. (반대로 CPU 로드가 걸리는 작업을 분산시키기 위해서는 ProcessPullExecutor 를 사용하는 것이 더 효율적이다!)

전체 유저 아이디 정보가 담긴 CSV 파일을 100 개로 분할한 후 executor 에 DB 조회, 연산, 생성 작업을 진행하는 함수와 함수의 인자 (= 처리해야하는 파일명) 를 submit 메소드에 넘겨 별도 스레드에서 해당 함수가 실행되게 하였다.

files = [func 에 인자로 넘길 파일명 리스트]
with concurrent.futures.ThreadPoolExecutor(max_workers=100) 
as executor:
    futures = 
    [executor.submit(func, files[i]) for i in range(len(files))]

    for index, future in 
        enumerate(concurrent.futures.as_completed(futures)):
        res = future.result()

결과는! DB 도 잘 버텨주었고 무엇보다 전체 처리 시간이 획기적으로 줄어들었다. 🥳

0개의 댓글