반응형

몽고디비 조회 속도가 너무 느려져서 인덱스를 추가했다.

 

추가하는데 엄청난 시간이 들지 예상하지 못해, 생성문을 실행했는데, 이게 실행이 되지 않아 당연히 클라이언트에서 실행중 수행시간이 길어져 프로세스가 꺼진줄 알고 그냥 뒀다.

robo 3T 라는 툴에서는 프로세스가 15초 이상 실행되어 실행되지 않는다~ 뭐 이런 식의 문구가 떠서 끄면 작업이 끝난줄 알았다.

 

그런데 이게 최초에 foreground 로 돌리던게 돌아갔던건지 background 로 돌리던게 돌아가는건지 몽기DB 쓰기 수행작업이 lock 이 걸렸습다.

백그라운드로 돌렸어도 전체에 락이 걸렸을거 같은데 확실치 않다.

 

인덱스 생성 명령어를 수행한지 2시간이 지나도 lock 이 안풀려있엇어서 서비스 병목 현상때문에 알게 되었다. 

 

나중이 되서야 인덱스 생성되는 프로세스를 끌 수 있다는걸 그 뒤에 알았다 ㅠㅠ.

안일하게 생성명령어만 돌리고 생성안되었다고 방치하지만 않았어도 이슈가 발생하지 않았는데 말이다.

 

최초에 금방 생성될 줄 알고 실수로 포그라운드에서 인덱스 생성을 날렸어서,

클라이언트에서 중지됐다는 alert 문구와 별개로 계속 백그라운드에서 실행중이였나 보다.

 

백그라운드로 돌려도 그런 형상이 나오는지는 잘 모르겠다.

 

해서 현재 만들어지고 있는 인덱스 생성 오퍼레이션을 취소해줘야 한다.

 

아래와 같은 방법이 있는지 알았으면.....

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)를 죽인다. 

일단 실행전에 인덱스 생성 리스트를 확인해본다.

 

리스트를 확인해보는 방법은 여러개가 있다.

db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
db
  .currentOp({"command.createIndexes": { $exists : true } })
  .inprog
  .forEach(function(op){ print(op.msg) })
db.currentOp({ 
    'msg' :{ $exists: true },
    'command': { $exists: true },
    $or: [ 
        { 'command.createIndexes': { $exists: true } }, 
        { 'command.reIndex': { $exists: true } }
    ]
}).inprog.forEach(function(op) { 
    print(op.msg); 
});

 

op 를 찾아서 해당 오퍼레이션을 지워줘야 하는데 문서를 보다 보니

Use the dropIndexes command or its shell helpers dropIndex() or dropIndexes() to terminate an in-progress index build. See Abort In-Progress Index Builds for more information.
Do not use killOp to terminate an in-progress index builds in replica sets or sharded clusters.

 

이런 말이 나왔다. 

killOp 를 쓰지말고 dropIndex() 를 사용해라. 혹시나 이런 일이 생길 경우에 dropIndex 를 써봐야겠다.

 

docs.mongodb.com/manual/core/index-creation/ [공식문서]
qkqhxla1.tistory.com/998 [인덱스 생성 취소 스크립트]
https://stackoverflow.com/questions/22309268/mongodb-status-of-index-creation-job [인덱스 생성 중인 상태보기]

 

 

반응형

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

[MongoDB] 몽고디비 인덱스 설명 및 생성  (0) 2020.12.17
반응형

Index 란

DB의 검색을 빠르게 하기 위해 미리 데이터의 순서를 정리해두는 과정

Index는 MongoDB에서 데이터 쿼리를 더욱 효율적으로 할 수 있게 해준다.

인덱스가 없이는, MongoDB는 collection scan – 컬렉션의 데이터를 하나하나 조회 – 방식으로 스캔을 하게 된다.

모든 도큐먼트를 스캔해야되는 비효율성을 줄임

 

한 쿼리당 하나의 index 만 유효하다.

두개의 index가 필요하다면 복합 index를 사용하면 된다.

 

* B트리

: 내부적으로 B-Tree 알고리즘을 이용하여 인덱스를 구성한다.

 

사용시 주의할 점

: 모든 인덱스를 갱신해야 하기 떄문에 모든 쓰기 작업은 인덱스 때문에 더 오래 걸림

: Collection 당 최대 64개까지 인덱스를 지닐수있지만, 2~3개만 지니는게 좋다.

: 몽고디비의 인덱스는 RDBMS와 유사하게 작동함

: 인덱스 구축시 background 옵션을 사용하면, 비동기로 작업이 가능하긴하지만 느리다.

 

 

Index 종류 

기본 인덱스 _id

모든 MongoDB의 컬렉션은 기본적으로 _id 필드에 인덱스가 존재합니다. 만약에 컬렉션을 만들 때  _id 필드를 따로 지정하지 않으면 mongod드라이버가 자동으로 _id 필드 값을 ObjectId로 설정해준다.

Single(단일) 필드 인덱스

사용자가 지정 할 수 있는 단일 필드 인덱스가 있다.

Compound (복합)  필드 인덱스,

두개 이상의 필드를 사용하는 인덱스를 복합 인덱스라고 부른다. 다음 이미지와 같이 첫번째 필드 (userid)는 오름차순으로, 두번째 필드 (score)는 내림차순으로 정렬 해야 하는 상황이 있을때 사용한다.

Multikey 인덱스

필드 타입이 배열인 필드에 인덱스를 적용 할 때는 Multikey 인덱스가 사용됩니다. 이 인덱스를 통하여 배열에 특정 값이 포함되어 있는 document를 효율적으로 스캔

Geospatial(공간적) Index

지도의 좌표와 같은 데이터를 효율적으로 쿼리하기 위해서 (예: 특정 좌표 반경 x 에 해당되는 데이터를 찾을 때) 사용되는 인덱스

Text 인덱스

텍스트 관련 데이터를 효율적으로 쿼리하기 위한 인덱스

해쉬 (hashed) 인덱스

이 인덱스를 사용하면 B Tree가아닌 Hash 자료구조를 사용합니다. Hash는 검색 효율이 B Tree보다 좋지만, 정렬을 하지 않습니다.

 

인덱스 사용

인덱스 확인

> db.[컬렉션명].getIndexes()    //    Collection의 인덱스 확인

인덱스 생성

> db.[컬렉션명].ensureIndex({name:1})    //    1이면 오름차순, -1 이면 내림차순

인덱스 생성(백그라운드에서 생성, 비동기방식)

 

> db.[컬렉션명].ensureIndex({name:1},{background:true})
인덱스 생성시 오래걸리면 백그라운드에서 생산해야함.

 

인덱스 생성( 고유인덱스 

> db.[컬렉션명].ensureIndex({name:1},{unique:true})    //    unique 속성을 지정해서 중복데이터가 저장되지 못하게 하여, 데이터 저장과 검색속도를 늘린다.

 

* 인덱스 생성( 중복데이터 삭제 )

> db.[컬렉션명].ensureIndex({name:1},{unique:true, dropDups:true})    //    Unique 하게 했을 때 이미 중복된 데이터가 있을 경우 중복되는 데이터는 삭제하고 인덱스를 저장한다

 

* Partial (부분적) 속성

> partial 속성은 document의 조건을 정하여 일부 document에만 인덱스를 적용 할 때 사용된다,.

partial 속성을 사용하면, 필요한 부분에만 인덱싱을 사용하여 저장공간도 아끼고 속도를 더 높일수 있다.

visitors 값이 1000 보다 높은 document에만 name 필드에 인덱스 적용

db.[컬렉션명].createIndex( { name: 1 }, { partialFilterExpression: { visitors: { $gt: 1000 } } } )

 

* ttl 속성 인덱스 생성

db.[컬렉션명].createIndex( { "notifiedDate": 1 }, { expireAfterSeconds: 3600 } )

예제: notifiedDate 가 현재 시각과 1시간 이상 차이나면 제거

document가 만료되어 제거 될 때, 시간이 아주 정확하지는 않다. 만료되는 document를 제거하는 thread는 매 60초마다 실행된다.

 

인덱스 삭제 

> db.[컬렉션명].dropIndex({name:1})    //    해당 인덱스 제거

 

* 인덱스 삭제( 모든 인덱스)

> db.[컬렉션명].dropIndexes()    //    _id를 제외한 모든 인덱스 제거

 

 

몽고디비 공식 문서 (인덱스 가이드)

docs.mongodb.com/manual/indexes/

 

Indexes — MongoDB Manual

MongoDB provides a number of different index types to support specific types of data and queries. Text Indexes MongoDB provides a text index type that supports searching for string content in a collection. These text indexes do not store language-specific

docs.mongodb.com

 

반응형

+ Recent posts