새소식

반응형
MongoDB/성능

MongoDB 성능 개선! 빠른 속도 튜닝!을 위한 DB 인덱싱 적용 db.collection.createIndex

  • -
반응형

인덱싱은 데이터베이스 성능 최적화의 핵심이며, 제대로 사용하면 쿼리 속도를 크게 향상시킬 수 있습니다. 

MongoDB 인덱싱이란?

인덱싱은 데이터베이스 테이블의 검색 속도를 향상시키기 위해 사용되는 데이터 구조입니다. MongoDB에서 인덱스는 컬렉션 내 문서들의 특정 필드 값을 정렬하여 저장합니다. 이를 통해 MongoDB는 전체 컬렉션을 스캔하지 않고도 빠르게 원하는 데이터를 찾을 수 있습니다.

인덱싱의 장점

  1. 쿼리 성능 향상: 인덱스를 사용하면 쿼리 실행 시간이 크게 단축됩니다.
  2. 정렬 작업 최적화: 인덱스된 필드로 정렬할 때 성능이 향상됩니다.
  3. 고유성 보장: 유니크 인덱스를 사용하여 필드 값의 중복을 방지할 수 있습니다.
  4. 집계 연산 개선: 특정 집계 작업의 성능을 향상시킵니다.

자주 쿼리되는 데이터에 대해서는 컬렉션 자체를 계속적으로 조회하는 것은 성능 상으로 좋지 않습니다.

 

예를 들어 프로파일링 설정을 진행한 후,

참고 : 2024.08.26 - [MongoDB/성능] - MongoDB 성능 개선을 위한 점검 (DB 프로파일링 / db.setProfilingLevel)

system.profile 컬렉션에서 다음과 같은 데이터가 출력되었다고 하자

{
    "op" : "command",
    "ns" : "platform.archive",
    "command" : {
        "aggregate" : "archive",
        "pipeline" : [
            {
                "$match" : {
                    "$and" : [
                        {
                            "postId" : ObjectId("6614d8eed42b7bdeccef0d9b")
                        },
                        {
                            "createdAt" : {
                                "$gte" : ISODate("2024-04-16T00:00:00.000+0000")
                            }
                        },
                        {
                            "userStatus" : "block"
                        }
                    ]
                }
            },
            {
                "$group" : {
                    "_id" : NumberInt(1),
                    "n" : {
                        "$sum" : NumberInt(1)
                    }
                }
            }
        ],
        "cursor" : {

        },
        "lsid" : {
            "id" : UUID("5e0c946a-b9f0-4926-816c-15df7cce19ca")
        },
        "$db" : "platform",
        "$readPreference" : {
            "mode" : "primaryPreferred"
        }
    },
    "keysExamined" : NumberInt(0),
    "docsExamined" : NumberInt(720633),
    "cursorExhausted" : true,
    "numYield" : NumberInt(720),
    "nreturned" : NumberInt(0),
    "queryHash" : "7A94B51E",
    "planCacheKey" : "7A94B51E",
    "queryFramework" : "classic",
    "locks" : {
        "FeatureCompatibilityVersion" : {
            "acquireCount" : {
                "r" : NumberLong(723)
            }
        },
        "ReplicationStateTransition" : {
            "acquireCount" : {
                "w" : NumberLong(1)
            }
        },
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(723)
            }
        },
        "Mutex" : {
            "acquireCount" : {
                "r" : NumberLong(2)
            }
        }
    },
    "flowControl" : {

    },
    "storage" : {

    },
    "responseLength" : NumberInt(103),
    "protocol" : "op_msg",
    "millis" : NumberInt(467),
    "planSummary" : "COLLSCAN",
    "ts" : ISODate("2024-04-16T00:13:54.282+0000"),
    "client" : "127.0.0.1",
    "allUsers" : [
        {
            "user" : "user",
            "db" : "admin"
        }
    ],
    "user" : "user@admin"
}

millis 속성을 보면 쿼리 실행에 대한 결과 출력에 467 ms가 걸렸다는 것과, planSummary 속성에서는 “COLLSCAN” 으로 collection scan을 실시했다는 것을 알 수 있습니다.

 

즉, 위 쿼리 pipeline 이 주기적으로 자주 실행되는데 collection scan을 통해서 전체 컬렉션을 조회하므로 성능적으로 많은 리소스를 사용하는 것.

 

해당 쿼리에 대해서는 인덱싱을 적용하면 성능을 개선할 수 있습니다.(검색 효율 상승)


반응형

인덱싱 적용 코드

# archive 컬렉션에 대해서 postId, userStatus, createdAt 순으로 인덱싱하는 인덱스를 추가한 코드 예시
#db.{컬렉션명}.createIndex({"컬럼명1": 1, "컬럼명2": 1, ...);
db.archive.createIndex({"postId": 1, "userStatus": 1, "createdAt": 1});

인덱싱을 적용할 때는 반드시 쿼리문에서 조건 순서와 동일하게 인덱싱을 맞춰야 합니다.

그래야 mongodb에서 해당 인덱스를 쿼리에 사용합니다.(인덱싱이 효율적이지 않은 경우 mongodb 가 자체 판단하여 해당 인덱스를 사용하지 않음)

 


추가 MongoDB 인덱스 사용법

1. 단일 필드 인덱스 생성

가장 기본적인 형태의 인덱스입니다.

db.users.createIndex({ username: 1 })

이 명령어는 'users' 컬렉션의 'username' 필드에 오름차순 인덱스를 생성합니다.

 

2. 복합 인덱스 생성

두 개 이상의 필드를 조합한 인덱스입니다.

db.products.createIndex({ category: 1, price: -1 })

'category'는 오름차순, 'price'는 내림차순으로 정렬된 복합 인덱스가 생성됩니다.

3. 고유 인덱스 생성

중복 값을 허용하지 않는 인덱스입니다.

db.employees.createIndex({ email: 1 }, { unique: true })

이메일 주소의 유일성을 보장합니다.

4. TTL (Time-To-Live) 인덱스

일정 시간이 지나면 문서를 자동으로 삭제하는 인덱스입니다.

db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

'createdAt' 필드를 기준으로 1시간 후 문서가 자동 삭제됩니다.

5. 텍스트 인덱스

전문 검색을 위한 인덱스입니다.

db.articles.createIndex({ content: "text" })

'content' 필드에 대한 텍스트 검색이 가능해집니다.

인덱스 사용 시 주의사항

  1. 과도한 인덱스 생성 자제: 인덱스도 저장 공간을 차지하며, 쓰기 작업 시 오버헤드가 발생합니다.
  2. 쓰기 작업 고려: 인덱스가 많을수록 INSERT, UPDATE, DELETE 작업의 속도가 느려질 수 있습니다.
  3. 정기적인 인덱스 분석: explain() 명령어를 사용하여 쿼리 성능을 분석하고, 불필요한 인덱스는 제거하세요.
  4. 대용량 데이터셋 고려: 매우 큰 컬렉션에 인덱스를 생성할 때는 백그라운드 옵션을 사용하세요.
db.hugecollection.createIndex({ field: 1 }, { background: true })
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.