data engineering

mongodb make index background, cancel making index

qkqhxla1 2019. 4. 19. 10:32

어떤 디비든간에 특정 컬럼에 대해서 검색이 잦을 경우 그 컬럼에 인덱스를 걸어놓는다. 인덱스를 걸어놓으면 해당 컬럼에 대한 작업시 속도가 상당히 빨라진다. 나도 개발자로 일하기 전에는 속도에 이슈가 생길만큼.. 큰 디비를 다뤄본적이 없는지라 회사에서 중요한 인덱스 개념을 처음 습득했다.(인덱스 안걸면 진짜 죽음이다.)


어쨋든 현재 5억건의 데이터를 가지고 있는 몽고 디비가 있는데, 어떤 컬럼이 추가되면서 그 컬럼에 인덱스를 걸어야 할 일이 생겼다. 평소라면 그냥 인덱스를 걸었겠지만 문제는 이 몽고디비가 계속 사용중인 production이라는것과, 5억건의 데이터에 인덱스를 걸려면 경험상 3~4시간이 필요했다.(서버 성능에 따라 다르긴하지만) 

몽고디비를 거의 나만 쓰고 있어서 모든 컬렉션들을 컨트롤하고있다고 생각하고...별생각없이 인덱스를 걸었다가 몽고를 사용하는 서비스들이 멈춰버려서 장애를 내버렸다.(인덱스를 걸면 global lock이 잡히며 global lock이 잡히는 동안에는 아무런 동작도 수행할수 없다. global lock이 db단위로 잡히는지, 몽고디비 전체로 잡히는지는 확인하지 못했었다.


그래서 인덱스 관련 내용을 찾아보다 background로 만드는 옵션이 있다는걸 알았는데....


https://docs.mongodb.com/manual/core/index-creation/


많이 좋다. 요약하자면 foreground로 만드는것보다 속도는 느리다. 하지만 global lock을 잡지 않기 때문에 서비스에 문제가 생기지 않는다!. 이 중요한 옵션을... 왜 지금알았는지 모르겠다. 하지만 글을 다 읽어보면 알수 있듯이 램과 임시 파일을 사용해서 인덱스를 만드는데 램 용량이 모자랄정도로 데이터가 클경우 엄청나게 많이 느려지고 심각한 문제가 생길수 있다고한다. 근데 '크다'는 데이터 양이 얼마인지는 모르겠다.

현재 29개의 컬럼을 가지고 있는 5억건의 데이터로 돌리면서 모니터링하고있는데 오히려 foreground보다 빠른것같다(?)


다 만들고 다시 봐야겠다. 아예 index를 background로 만드는 옵션의 존재자체를 모르고 있었다니... 공부가 많이 부족하다. 몽고디비 공식 홈페이지나 한번 더 읽어봐야겠다.


아 그리고 나처럼 실수로 인덱스를 foreground로 만들어서 lock이 걸릴경우 이 인덱스생성 명령을 취소하고 싶으면..

killIndexMaking = function(a) {
    currOp = db.currentOp({"op": "command", 'query.createIndexes':'인덱스를 건 컬렉션명'})['inprog']
    //print(currOp) // 만들고있는 인덱스가 맞는지 check
    print("Killing opId: " + currOp[0].opid);
    //db.killOp(currOp[0].opid); // 죽인다.
};

killIndexMaking(1)

요 스크립트를 사용하면 된다. db.currentOp명령어로 'query.createIndexes'컬럼을 필터로 걸어 해당 컬렉션에 걸리고있는 인덱스 목록을 가져온다. 위에서는 인덱스를 하나만 만들고 있다고 가정하고 첫번째(currOp[0].opid)를 죽인다. 


+인덱스가 만들어지고 있는 진행상황은 mongod.log에 다 찍힌다. 

vi mongod.log로 로그를 열고 /Index Build/로 검색을 한다. 그리고 GN이 vi에서 가장 마지막으로 발견한 검색결과를 리턴하므로(여기서 참조) 요걸 찾아보면

Index Build (background): 514604400/545008447 94%

이런식으로 결과가 나온다.

아님 쉽게 db.currentOp({"op": "command", 'query.createIndexes':'인덱스를 건 컬렉션명'}) 로 찾으면 나온다.



또는

https://stackoverflow.com/questions/22309268/mongodb-status-of-index-creation-job

db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })

를 사용하자. op를 출력해보려고 하면 bson이 나오는데 bson은 printjson(op);처럼 출력하면 예쁘게 출력된다.


'data engineering' 카테고리의 다른 글

mysql partitioning, index  (0) 2019.06.08
mysql join.  (0) 2019.06.01
apache airflow tutorial.  (0) 2019.03.24
python으로 hive의 쿼리 자동화하기.  (0) 2019.03.13
spark processing parquet file from s3 with pass credentials.  (0) 2019.02.17