ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Mongo DB - 대량 데이터 Insert 성능 ( feat. mongoengine )
    NoSql/MongoDB 2021. 11. 24. 16:27
    반응형

    몽고를 제대로 쓰기 시작하면서 몇 가지 알게 될 것들을 정리해보고자 한다. 그 첫 번째 순서... 대량으로 입력할 때 어디까지 얼마나 걸릴까...? 

    막연하게 기존에 RDB 보다 대량 입력에 뛰어나다고는 알고 있지만 실제로 어느정도까지 수행이 가능할지 테스트해보고자 했다. 

    분명 환경이나 이런것들이 데이터 이관을 위한 스크립트를 작성하다가 문뜩 기록해보자는 생각이 들어서 작성한 것이기 때문에 완벽한 성능 테스트 구성을 해놓고 했다고 할 순 없다. 

    일단 환경 조건 자체는 아래와 같다. 

     

    1) 몽고 클러스터 : atlas cloud 기반 m10 급 

    2) 언어 환경 : python , mongoengine 

    4) select 대상 : AWS RDS 데이터 ( 약 2200만건 ) 중 특정 조건에 해당되는 필터링된 데이터 ( 750만 건 )

    4) selelct 기준 :  sequence PK 기준으로 50만건씩 구간 조회

    5) 밀어넣는 기준은 최대 50만 건 까지 나 누에서 bulk insert 시도 

     

    - 조회 

     

      본 목적이 테스트가 아니라서 약간의 문제가 있었다. 조회하는 데이터 테이블에 인덱스 자체가 없고 데이터 자체도 실시간으로 쌓이고 있는 상태였다. 좀 더 조회 쿼리를 최적화하기엔 PK 만 의존해야 돼서 개선이 불가능했다. 그렇기 때문에 조회하는데 최대 45초가량 정도 걸리는 경우도 종종 발생하였다. 

     

    - 입력

     

     내가 가장 궁금했던 부분이다. 과연 50만건 기준으로 어느 정도 속도를 보일 수 있을 것인가 

    495,334건 : 105.4초
    492,524건 : 100.2초
    414,414건  : 84.8초
    298,660건 : 69.1초 
    161,424건: 29.9초
    95,551건 :  17.8초
    50,000건 : 12.1초
    40,000건 : 9.5초 
    30,000건 : 6.4초 
    25,000건 : 5.4초 
    20,000건 : 3.6초 
    12,000건 : 3.6초
    11,000건 : 3.8초
    10,000건 : 2.3초
    9,000건 : 3.9초
    8,000건 : 2.3초
    7,000건 : 1.8초
    6,000건 : 1.8초
    5,000건 : 1.8초
    4,500건 : 0.9초
    4,000건 : 0.8초
    2,866건 : 0.5초
    2,085건 : 0.4초
    1,807건 :  0.4초 
    1,550건 : 0.2초
    991건 : 0.3초
    718건 : 0.3초
    276건 : 0.1초
    59건 : 0.06초

    50만 건 기준으로 조회는 했으나 데이터 구성상 50만 건을 꽉 차는 케이스는 확인할 수 없었지만 나름 그래도 참고할만한 결과가 나오지 않았나 싶다. 

     

     일단 기록들은 여러번 했을 때 각 건수별로 시간의 편차가 생기긴 했지만 나름 그래도 자주 나오는 값들로 나름 정리해봤을 때 생각보다 정직하게 시간이 걸린다(?)라는 게 보이는 지표였다. 네트워크 차이나 실제로 테스트한 장비의 환경에 영향이 있어 보이고 해당 로직 자체를 python에서 사용하는 mongoengine을 사용해서 벌크로 넣어 본 건데 다른 언어나 다른 라이브러리를 사용했을 때 어느 정도 차이가 생기지 않을까 싶다. 

     

     왜냐하면 실제로 Mongo compass 로 새로고침을 계속하면서 확인했을 때 이미 데이터가 추가된 것으로 보이는데 스크립트는 실제로 완료가 되지 않은 경우가 있었다. 추측이지만 데이터가 전부 들어가고 나서 앱에서 결과 리턴 받는 그 중간 사이에 라이프사이클상에 뭔가 딜레이 되는 행위들이 존재하는 거 같다. mongoengine 이 뭔가 작업을 하는 것인지 확인은 해봐야지만 일단 해당 작업은 메인이 테스트가 아녔기에... 일단 무시하고 넘어갔다. 

     

     의미 있는 건 일단 50만 건 정도를 altas cloud m10 급 환경에서 몽고를 사용할 때 약 2분 안에 모두 들어간다는 것이다. 한 번에 50만 건이면 개인적으로는 아주 많은 양이라고 본다. mysql 사용할 때 bulk로 insert 할 때 실제 보내는 패킷의 제한 때문에 문제가 생긴 경우도 있었고 벌크 자체가 양이 클 경우 중도에 중지할 때 문제가 발생했었고 개인적으로는 한 번에 만 건 정도로 잘라서 입력했었던 거 같다. 이것마저도 배치로 새벽에 돌려야 할 정도였던 거 같다. 

     몽고에서 실제 cpu, mem 사용량을 봤을때 m10 급이 atlas cloud에서 최소 기본급이기 때문에 굉장히 많은 양을 사용하는 것을 확인했다. 사용량만 봤을 땐 50%를 훌쩍 넘었지만 실제 m10급으로 서비스 하진 않을 것이라 생각하기 때문에... 괜찮지 않을까 싶다. 그리고 하나의 request 가 50만 건씩 들어오는 정상적인(?) 상황은 흔치 않을 거 같다. 

    • 5,000건 미만일시 1초 내로 처리 가능 하는것으로 예측
    • 25,000건 미만일시 5초 내로 처리 가능할것으로 예측
    • 40,000건 미만일시 10초 내로 처리 가능할것으로 예측
    • 95,000건 미만일시 20초 내로 처리 가능할것으로 예측
    • 16,000만 건 미만일시 30초 내로 처리 가능할것으로 예측
    • 약 50만건 미만일시 120초 이내에 입력 가능할 것으로 예측 ( bulk Insert 사용 시 )

     

     간단하게 정리하면 성능은 위와 같이 예상을 한다. 물론 환경이 달라지면 당연히 달라지겠지만 지금 내가 테스트할 수 있는 환경에선 결론적으로는 이렇다. m20, m30 급으로 올리면 좀 더 빨리 처리할 수 있을 것이라고 본다. 그리고 긍정적인 건 역시 nosql 답게 collection에 약 40만 건 정도 입력한 상태에서도 별다른 성능의 영향은 보이지 않았다. 

     

     나중에 추가로 확인해봐야하는건 인덱스가 존재할 경우 얼마나 성능의 영향을 줄지 확인이 필요해 보인다. 분명하게 인덱스가 존재할 경우 그만큼의 리소스의 손해를 본다고 하기 때문에 충분히 확인해 볼 이유는 있는 것 같다. 

     

     인덱스를 걸었을때 얼마나 영향이 있을까 위에 내용을 바로 테스트 해보았다... 생각보다 많은 차이를 보인다. 단순하게 보면 10초 걸리던게 20초는 가뿐하게 넘길수있다 라고 말할수 있다. 750만건이 넘어 갈경우 인덱스의 크기도 300메가 이상 잡히는것을 확인했다. 인덱스 크기 관리를 할때 유의미하게 사용할수 있는 수치 일거 같다. 

     

     그리고 테스트를 다시하면서 발견한사실인데 python mongoengine 을 사용하여 bulk insert 를 할때 insert() 메서드에 옵션을 줄수 있는데 옵션중 load_bulk 는 무조건 False 설정해야할것 같다. 이 옵션은 간단히 말하면 데이터 삽입한 결과에 대한 형태를 결정하는건데 이유는 모르겠지만 디폴트가 True 로 되있고 이럴 경우 삽입한 Document를 그대로 응답 리턴한다고 한다. 생각만해도 ... 내가 50만건을 넣으면 그걸 다시 리턴하는거라 생각하니 아찔했다. 그래서 이것을 False 로 해서 ObjectIds 만 받도록해야 리턴 값이 작아진다. 이 옵션은  실제로 성능상에도 아주 큰 영향을 끼쳤다. 

     

     2차 테스트 진행시 250만건 정도를 insert 하는데 ( 10만건씩 나누어 넣었다 ) 약 16분정도면 작업이 완료 되었다. 1분에 약 15만건정도 처리가 가능한것 같다. 위에 샘플링한 기준은 인덱스가 없을 경우 이기때문에 아무래도 더 빨리 처리된것 같다.

     

     추가로 확인 한부분은 실제로 데이터가 한건도 없는 빈 컬렉션과 약 1000만건정도 쌓여있는 컬렉션에 데이터를 대량으로 넣었을때 지연이 생기는지 확인해 보았는데 데이터가 누적된것에 대해선 생각보다 성능에 영향이 없었다. 

     

     최초에 데이터가 없고 인덱스가 아직 없을 경우 데이터가 입력될때 인덱스를 생성하는 시간은 오래 걸려서 인덱스 생성을 하려면 일단 한건 정도 샘플링 가능한 데이터를 먼저 입력해서 인덱스를 생성한 뒤 그다음 데이터를 대량으로 넣는게 효과적일것으로 보인다. 

     테스트 할때 확인 해본결과 1500만건 정도 쌓여있는 컬렉션에서 인덱스 신규 생성시 3분 안에는 처리가 완료 되는것을 확인 했다. 

     

     앞으로 몽고 디비에 대해서 여러가지를 사용해 보게 될거 같다. 유의미하지 않더라도 기록할수 있는건 최대한 기록하자! 

    반응형

    'NoSql > MongoDB' 카테고리의 다른 글

    MongoDB ( vs Mysql )  (0) 2021.04.08
Designed by Tistory.