다음을 통해 공유


Azure Cosmos DB for MongoDB에서 인덱싱 관리

Azure Cosmos DB for MongoDB를 사용하면 인덱싱을 사용하여 쿼리 성능을 높일 수 있습니다. 이 문서에서는 더 빠른 데이터 검색과 더 나은 효율성을 위해 인덱스를 관리하고 최적화하는 방법을 보여 줍니다.

MongoDB 서버 버전 3.6 이상에 대한 인덱싱

Azure Cosmos DB for MongoDB 서버 버전 3.6 이상은 _id 필드 및 분할된 데이터베이스 키(분할된 컬렉션에서만)를 자동으로 인덱싱합니다. API는 분할 키별 _id 필드의 고유성을 적용합니다.

MongoDB용 API는 기본적으로 모든 필드를 인덱싱하는 Azure Cosmos DB for NoSQL과 다르게 작동합니다.

인덱싱 정책 편집

Azure Portal의 Data Explorer에서 인덱싱 정책을 편집합니다. Data Explorer의 인덱싱 정책 편집기에서 단일 필드 및 와일드카드 인덱스를 추가합니다.

Azure Cosmos DB for MongoDB의 인덱싱 정책 편집기 스크린샷.

참고

데이터 탐색기에서 인덱싱 정책 편집기를 사용하여 복합 인덱스를 만들 수는 없습니다.

인덱스 형식

단일 필드

단일 필드에 인덱스를 만듭니다. 단일 필드 인덱스의 정렬 순서는 중요하지 않습니다. 다음 명령을 사용하여 필드 name에 인덱스를 만듭니다.

db.coll.createIndex({name:1})

Azure Portal의 name에 동일한 단일 필드 인덱스를 만듭니다.

인덱싱 정책 편집기에서 이름 인덱스를 추가하는 것을 보여 주는 스크린샷.

쿼리는 가능한 경우 여러 개의 단일 필드 인덱스를 사용합니다. 컬렉션당 최대 500개의 단일 필드 인덱스를 만듭니다.

복합 인덱스(MongoDB 서버 버전 3.6 이상)

MongoDB API에서 여러 필드를 한 번에 정렬하는 쿼리와 함께 복합 인덱스를 사용합니다. 정렬할 필요가 없는 여러 필터가 포함된 쿼리의 경우 인덱싱 비용을 절약하기 위해 복합 인덱스 대신 단일 필드 인덱스를 여러 개 만듭니다.

복합 인덱스 또는 복합 인덱스의 각 필드에 대한 단일 필드 인덱스는 쿼리 필터링에서 동일한 성능을 제공합니다.

배열의 제한 사항으로 인해 중첩된 필드의 복합 인덱스는 기본적으로 지원되지 않습니다. 중첩된 필드에 배열이 없으면 인덱스는 의도한 대로 작동합니다. 중첩된 필드에 경로의 어느 곳에나 배열이 있는 경우 해당 값은 인덱스에서 무시됩니다.

예를 들어, people.dylan.age를 포함하는 복합 인덱스는 경로에 배열이 없기 때문에 이 경우에 작동합니다.

{
  "people": {
    "dylan": {
      "name": "Dylan",
      "age": "25"
    },
    "reed": {
      "name": "Reed",
      "age": "30"
    }
  }
}

이 경우에는 경로에 배열이 있기 때문에 동일한 복합 인덱스가 작동하지 않습니다.

{
  "people": [
    {
      "name": "Dylan",
      "age": "25"
    },
    {
      "name": "Reed",
      "age": "30"
    }
  ]
}

'EnableUniqueCompoundNestedDocs' 기능을 사용하도록 설정하여 데이터베이스 계정에서 이 기능을 사용하도록 설정합니다.

참고

배열에는 복합 인덱스를 만들 수 없습니다.

다음 명령은 nameage 필드에 복합 인덱스를 만듭니다.

db.coll.createIndex({name:1,age:1})

다음 예제와 같이 복합 인덱스를 사용하여 여러 필드에서 한 번에 효율적으로 정렬할 수 있습니다.

db.coll.find().sort({name:1,age:1})

또한 앞의 복합 인덱스를 사용하여 모든 필드에서 반대의 정렬 순서로 쿼리를 효율적으로 정렬할 수도 있습니다. 예를 들면 다음과 같습니다.

db.coll.find().sort({name:-1,age:-1})

그러나 복합 인덱스의 경로 시퀀스는 쿼리와 정확히 일치해야 합니다. 추가 복합 인덱스가 필요한 쿼리의 예는 다음과 같습니다.

db.coll.find().sort({age:1,name:1})

Multikey 인덱스

Azure Cosmos DB는 배열의 콘텐츠를 인덱싱하기 위해 다중 키 인덱스를 만듭니다. 배열 값으로 필드를 인덱싱하면 Azure Cosmos DB는 자동으로 배열의 각 요소를 인덱싱합니다.

지리 공간적 인덱스

많은 지리 공간적 연산자가 지리 공간적 인덱스를 활용합니다. Azure Cosmos DB for MongoDB는 2dsphere 인덱스를 지원합니다. API는 아직 2d 인덱스를 지원하지 않습니다.

location 필드에 지리 공간적 인덱스를 만드는 예는 다음과 같습니다.

db.coll.createIndex({ location : "2dsphere" })

텍스트 인덱스

Azure Cosmos DB for MongoDB는 텍스트 인덱스를 지원하지 않습니다. 문자열에 대한 텍스트 검색 쿼리의 경우 Azure Cosmos DB와 Azure AI 검색 통합을 사용합니다.

와일드카드 인덱스

알 수 없는 필드에 대한 쿼리를 지원하려면 와일드카드 인덱스를 사용합니다. 가족에 대한 데이터가 담긴 컬렉션을 상상해보세요.

해당 컬렉션의 예 문서의 일부는 다음과 같습니다.

"children": [
  {
    "firstName": "Henriette Thaulow",
    "grade": "5"
  }
]

children에 다른 속성 집합이 있는 또 다른 예는 다음과 같습니다.

"children": [
  {
    "familyName": "Merriam",
    "givenName": "Jesse",
    "pets": [
      { "givenName": "Goofy" },
      { "givenName": "Shadow" }
    ]
  },
  {
    "familyName": "Merriam",
    "givenName": "John",
  }
]

이 컬렉션의 문서는 다양한 속성을 가질 수 있습니다. children 배열의 모든 데이터를 인덱싱하려면 각 속성에 대해 별도의 인덱스를 만들거나 전체 children 배열에 대해 하나의 와일드카드 인덱스를 만듭니다.

와일드카드 인덱스 만들기

children 내의 모든 속성에 대한 와일드카드 인덱스를 만들려면 다음 명령을 사용합니다.

db.coll.createIndex({"children.$**" : 1})
  • MongoDB와 달리 와일드카드 인덱스는 쿼리 조건자의 여러 필드를 지원할 수 있습니다. 각 속성에 대해 별도의 인덱스를 만드는 대신 단일 와일드카드 인덱스를 사용하더라도 쿼리 성능에는 차이가 없습니다.

와일드카드 구문을 사용하여 다음 인덱스 형식을 만듭니다.

  • 단일 필드
  • 지리 공간적

모든 속성 인덱싱

다음 명령을 사용하여 모든 필드에 와일드카드 인덱스를 만듭니다.

db.coll.createIndex( { "$**" : 1 } )

Azure Portal의 Data Explorer를 사용하여 와일드카드 인덱스를 만듭니다.

인덱싱 정책 편집기에서 와일드카드 인덱스 추가

참고

개발을 막 시작했다면 모든 필드에 와일드카드 인덱스를 추가합니다. 이러한 방식은 개발을 간소화하고 쿼리를 최적화하기 쉽게 만듭니다.

필드가 많은 문서의 경우 쓰기 및 업데이트에 대한 RU(요청 단위) 요금이 높을 수 있습니다. 쓰기 워크로드가 많은 경우 와일드카드 대신 개별적으로 인덱싱된 경로를 사용합니다.

제한 사항

와일드카드 인덱스는 다음 인덱스 유형 또는 속성을 지원하지 않습니다.

  • 복합

  • TTL

  • 고유한

  • MongoDB와 달리 Azure Cosmos DB for MongoDB에는 다음에 대한 와일드카드 인덱스를 사용할 수 없습니다.

  • 여러 특정 필드를 포함하는 와일드카드 인덱스 만들기

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection " :
        {
          "children.givenName" : 1,
          "children.grade" : 1
        }
      }
    )
    
  • 여러 특정 필드를 제외하는 와일드카드 인덱스 만들기

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection" :
        {
          "children.givenName" : 0,
          "children.grade" : 0
        }
      }
    )
    

대안으로, 여러 개의 와일드카드 인덱스를 만듭니다.

인덱스 속성

다음 작업은 Wire Protocol 버전 ​​4.0 이하 버전을 사용하는 계정에서 일반적으로 수행됩니다. 지원되는 인덱스 및 인덱싱된 속성에 대해 자세히 알아봅니다.

고유 인덱스

고유 인덱스는 두 개 이상의 문서가 인덱스된 필드에 동일한 값을 갖지 않도록 하는 데 도움이 됩니다.

student_id 필드에 고유 인덱스를 만들려면 다음 명령을 실행합니다.

db.coll.createIndex( { "student_id" : 1 }, {unique:true} )

{
  "_t" : "CreateIndexesResponse",
  "ok" : 1,
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 4
}

분할된 컬렉션의 경우, 고유 인덱스를 만들려면 분할(파티션) 키를 제공합니다. 분할 컬렉션의 모든 고유 인덱스는 복합 인덱스이며, 필드 중 하나는 분할 키입니다. 분할 키는 인덱스 정의의 첫 번째 필드여야 합니다.

다음 명령을 실행하여 coll이라는 이름의 분할된 컬렉션(university를 분할 키로 사용)과 student_iduniversity 필드에 대한 고유 인덱스를 만듭니다.

db.runCommand({shardCollection: db.coll._fullName, key: { university: "hashed"}});
{
  "_t" : "ShardCollectionResponse",
  "ok" : 1,
  "collectionsharded" : "test.coll"
}
db.coll.createIndex( { "university" : 1, "student_id" : 1 }, {unique:true});
{
  "_t" : "CreateIndexesResponse",
  "ok" : 1,
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 3,
  "numIndexesAfter" : 4
}

이전 예에서 "university":1 절을 생략하면 다음과 같은 오류 메시지가 표시됩니다.

cannot create unique index over {student_id : 1.0} with shard key pattern { university : 1.0 }

제한 사항

컬렉션이 비어 있는 동안 고유 인덱스를 만듭니다.

연속 백업을 사용하는 MongoDB용 Azure Cosmos DB 계정은 기존 컬렉션에 대한 고유 인덱스 만들기를 지원하지 않습니다. 이러한 계정의 경우 컬렉션 만들기와 함께 고유 인덱스를 만들어야 하며, 컬렉션 확장 프로그램 만들기 명령을 사용해야 하고 수행할 수 있습니다.

db.runCommand({customAction:"CreateCollection", collection:"coll", shardKey:"student_id", indexes:[
{key: { "student_id" : 1}, name:"student_id_1", unique: true}
]});

배열의 제한 사항으로 인해 중첩된 필드의 고유 인덱스는 기본적으로 지원되지 않습니다. 중첩된 필드에 배열이 없으면 인덱스가 의도한 대로 작동합니다. 중첩된 필드에 경로의 어느 곳에나 배열이 있는 경우 해당 값은 고유 인덱스에서 무시되고 해당 값의 고유성은 유지되지 않습니다.

예를 들어, 경로에 배열이 없기 때문에 people.tom.age에 대한 고유 인덱스가 이 경우에 작동합니다.

{
  "people": {
    "tom": {
      "age": "25"
    },
    "mark": {
      "age": "30"
    }
  }
}

하지만 이 경우에는 경로에 배열이 있기 때문에 작동하지 않습니다.

{
  "people": {
    "tom": [
      {
        "age": "25"
      }
    ],
    "mark": [
      {
        "age": "30"
      }
    ]
  }
}

'EnableUniqueCompoundNestedDocs' 기능을 활성화하여 데이터베이스 계정에 이 기능을 사용할 수 있습니다.

TTL 인덱스

컬렉션에서 문서가 만료되도록 하려면 TTL(수명) 인덱스를 만듭니다. TTL 인덱스는 _ts 필드에 expireAfterSeconds 값을 사용한 인덱스입니다.

예제:

db.coll.createIndex({"_ts":1}, {expireAfterSeconds: 10})

이전 명령은 db.coll 컬렉션에서 10초 전에 수정된 모든 문서를 삭제합니다.

참고

_ts 필드는 Azure Cosmos DB에만 해당하며 MongoDB 클라이언트에서는 액세스할 수 없습니다. 이는 문서의 마지막 수정 타임스탬프를 포함하는 예약된(시스템) 속성입니다.

인덱스 진행률 추적

Azure Cosmos DB for MongoDB 버전 3.6 이상에서는 데이터베이스 인스턴스의 인덱스 진행률을 추적하기 위한 currentOp() 명령을 지원합니다. 이 명령은 데이터베이스 인스턴스에서 진행 중인 작업에 대한 정보가 포함된 문서를 반환합니다. currentOp 명령을 사용하여 네이티브 MongoDB에서 진행 중인 모든 작업을 추적합니다. Azure Cosmos DB for MongoDB에서 이 명령은 인덱스 작업만 추적합니다.

currentOp 명령을 사용하여 인덱스 진행률을 추적하는 방법에 대한 몇 가지 예는 다음과 같습니다.

  • 컬렉션에 대한 인덱스 진행률 가져오기:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • 데이터베이스의 모든 컬렉션에 대한 인덱스 진행률을 가져옵니다.

    db.currentOp({"command.$db": <databaseName>})
    
  • Azure Cosmos DB 계정의 모든 데이터베이스 및 컬렉션에 대한 인덱스 진행률을 가져옵니다.

    db.currentOp({"command.createIndexes": { $exists : true } })
    

인덱스 진행률 출력의 예

인덱스 진행률 세부 정보는 현재 인덱스 작업의 진행률을 백분율로 보여 줍니다. 다음은 인덱스 진행의 다양한 단계에 대한 출력 문서 형식의 예입니다.

  • "foo" 컬렉션과 "bar" 데이터베이스에 대한 인덱스 작업이 60% 완료되었으며, 출력 문서는 다음과 같습니다. Inprog[0].progress.total 필드는 목표 완료 백분율로 100을 표시합니다.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 60 %",
          "progress": {
            "done": 60,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • "foo" 컬렉션과 "bar" 데이터베이스에서 인덱스 작업이 시작된 경우, 측정 가능한 수준에 도달할 때까지 출력 문서는 0%의 진행률을 표시할 수 있습니다.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 0 %",
          "progress": {
            "done": 0,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • 인덱스 작업이 완료되면 출력 문서에 빈 inprog 작업이 표시됩니다.

    {
      "inprog" : [],
      "ok" : 1
    }
    

백그라운드 인덱스 업데이트

백그라운드 인덱스 속성에 대해 어떤 값을 설정하든 인덱스 업데이트는 항상 백그라운드에서 실행됩니다. 인덱스 업데이트는 다른 데이터베이스 작업보다 우선 순위가 낮은 RU(요청 단위)를 사용하므로 인덱스 변경으로 인해 쓰기, 업데이트 또는 삭제로 인한 가동 중지 시간이 발생하지 않습니다.

새 인덱스를 추가해도 읽기 가용성에는 영향을 미치지 않습니다. 인덱스 변환이 완료된 후에만 쿼리는 새 인덱스를 사용합니다. 변환하는 동안 쿼리 엔진은 기존 인덱스를 계속 사용하므로 인덱싱 변경을 시작하기 전과 비슷한 읽기 성능을 볼 수 있습니다. 새 인덱스를 추가해도 쿼리 결과가 불완전하거나 일관되지 않을 위험이 없습니다.

인덱스를 제거한 후 삭제된 인덱스를 필터링하는 쿼리를 즉시 실행하면 인덱스 변환이 완료될 때까지 결과가 일관되지 않고 불완전할 수 있습니다. 쿼리 엔진은 새로 제거된 인덱스를 필터링하는 쿼리에 대해 일관되거나 완전한 결과를 제공하지 않습니다. 대부분의 개발자는 인덱스를 삭제한 후 바로 쿼리를 실행하지 않으므로 이런 상황은 발생하지 않을 가능성이 큽니다.

참고

인덱스 진행률을 추적할 수 있습니다.

reIndex 명령

reIndex 명령은 컬렉션의 모든 인덱스를 다시 만듭니다. 드물지만 reIndex 명령을 실행하면 컬렉션의 쿼리 성능이나 기타 인덱스 문제가 해결될 수 있습니다. 인덱싱 문제가 발생하는 경우 reIndex 명령을 사용하여 인덱스를 다시 만들어 보세요.

다음 구문을 사용하여 reIndex 명령을 실행합니다.

db.runCommand({ reIndex: <collection> })

다음 구문을 사용하여 reIndex 명령을 실행하면 컬렉션의 쿼리 성능이 개선되는지 확인합니다.

db.runCommand({"customAction":"GetCollection",collection:<collection>, showIndexes:true})

샘플 출력:

{
  "database": "myDB",
  "collection": "myCollection",
  "provisionedThroughput": 400,
  "indexes": [
    {
      "v": 1,
      "key": {
        "_id": 1
      },
      "name": "_id_",
      "ns": "myDB.myCollection",
      "requiresReIndex": true
    },
    {
      "v": 1,
      "key": {
        "b.$**": 1
      },
      "name": "b.$**_1",
      "ns": "myDB.myCollection",
      "requiresReIndex": true
    }
  ],
  "ok": 1
}

reIndex가 쿼리 성능을 개선하면 requiresReIndex가 true입니다. reIndex가 쿼리 성능을 개선하지 못하면 이 속성은 생략됩니다.

인덱스를 사용하여 컬렉션 마이그레이션

컬렉션에 문서가 없는 경우에만 고유 인덱스를 만들 수 있습니다. 인기 있는 MongoDB 마이그레이션 도구는 데이터를 가져온 후 고유 인덱스를 만들려고 합니다. 이 문제를 해결하려면 마이그레이션 도구에서 시도하도록 두지 말고 해당 컬렉션과 고유 인덱스를 수동으로 만듭니다. 명령줄에서 mongorestore 플래그를 사용하여 --noIndexRestore에 대해 이 동작을 달성합니다.

MongoDB 버전 3.2에 대한 인덱싱

MongoDB 유선 프로토콜 버전 3.2를 사용하는 Azure Cosmos DB 계정의 인덱싱 기능과 기본값은 다릅니다. feature-support-36.md#protocol-support에서 계정 버전을 확인하고 upgrade-version.md에서 버전 3.6으로 업그레이드합니다.

버전 3.2를 사용하는 경우, 이 섹션에서는 버전 3.6 이상과의 주요 차이점을 강조 표시하여 설명합니다.

기본 인덱스 삭제(버전 3.2)

버전 3.6 이상과 달리 Azure Cosmos DB for MongoDB 버전 3.2는 기본적으로 모든 속성을 인덱싱합니다. 다음 명령을 사용하여 컬렉션(coll)에 대한 기본 인덱스를 삭제합니다.

db.coll.dropIndexes()
{ "_t" : "DropIndexesResponse", "ok" : 1, "nIndexesWas" : 3 }

기본 인덱스를 삭제한 후 버전 3.6 이상에서 하는 것처럼 인덱스를 추가합니다.

복합 인덱스(버전 3.2)

복합 인덱스는 문서의 여러 필드를 참조하세요. 복합 인덱스를 만들려면 upgrade-version.md에서 버전 3.6 또는 4.0으로 업그레이드합니다.

와일드카드 인덱스(버전 3.2)

와일드카드 인덱스를 만들려면 upgrade-version.md에서 버전 4.0 또는 3.6으로 업그레이드합니다.

다음 단계