

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Java를 사용한 Amazon DocumentDB의 인덱스 관리
<a name="index-management-java"></a>

인덱스를 사용하면 Amazon DocumentDB 컬렉션에서 데이터를 효율적으로 검색할 수 있습니다. 인덱스가 없으면 DocumentDB는 컬렉션의 모든 문서를 스캔하여 지정된 쿼리를 충족하는 결과를 반환해야 합니다. 이 주제에서는 MongoDB Java 드라이버를 사용하여 인덱스를 생성, 삭제 및 나열하는 방법에 대한 정보를 제공합니다. 또한 쿼리에서 특정 인덱스가 사용되고 있는지 확인하는 방법과 특정 인덱스를 사용하도록 Amazon DocumentDB에 힌트를 제공하는 방법도 설명합니다.

**Topics**
+ [인덱스 생성](#creating-indexes)
+ [인덱스 삭제](#dropping-indes)
+ [인덱스 선택 결정 및 인덱스 힌트 제공](#w2aac45b9b7c17c13)

Amazon DocumentDB는 다양한 유형의 인덱스를 지원합니다. 지원되는 모든 인덱스에 대한 포괄적인 개요는 이 [블로그 게시물](https://aws.amazon.com/blogs/database/how-to-index-on-amazon-documentdb-with-mongodb-compatibility/)을 참조하세요.

## Java를 사용하여 인덱스 생성
<a name="creating-indexes"></a>

MongoDB Java 드라이버를 사용하여 Amazon DocumentDB에서 인덱스를 생성하는 두 가지 메커니즘은 `runCommand()`를 통한 방법과 단일 인덱스의 경우 `createIndex()` 메서드 또는 여러 인덱스의 경우 `createIndexes()` 메서드를 통한 방법입니다. `createIndex()` 및 `createIndexes()` 메서드를 사용하는 한 가지 이유는 인덱스 생성과 관련된 특정 오류를 포착하여 오류 처리를 개선할 수 있기 때문입니다. `runCommand()`에서 이러한 방법을 사용하는 또 다른 이유는 MongDB Java 드라이버가 인덱스 생성 및 조작을 위한 풍부한 지원 클래스 세트를 제공하기 때문입니다. 이러한 지원 클래스는 `createIndex()` 또는 `createIndexes()` 메서드를 사용하는 경우에만 사용할 수 있습니다. 다음 세 가지 지원 클래스가 있습니다.
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html)** - 이 클래스는 다양한 유형의 인덱스를 생성하기 위한 정적 팩토리 메서드를 제공하는 유틸리티 클래스 역할을 합니다. 복잡한 인덱스 정의를 생성하는 프로세스를 간소화하며 일반적으로 다른 인덱스 관련 클래스와 함께 사용됩니다.
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html)** - 이 클래스는 인덱스 키 정의 및 해당 옵션을 모두 캡슐화하는 기본 클래스입니다. 인덱싱할 항목(키)과 인덱싱 방법( 옵션)을 결합한 전체 인덱스 사양을 나타냅니다. 이 클래스는 `createIndexes()` 메서드에 전달할 수 있는 인덱스 사양 모음을 정의할 수 있기 때문에 여러 인덱스를 동시에 생성할 때 특히 유용합니다.
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html)** - 인덱스 동작을 사용자 지정하기 위한 다양한 메서드를 제공하는 포괄적인 구성 클래스입니다. 여기에는 고유 인덱스, 희소 인덱스, 만료 시간(TTL) 및 부분 필터 표현식에 대한 설정이 포함됩니다. 메서드 체인을 통해 백그라운드 인덱스 구축 및 고유한 제약 조건과 같은 여러 옵션을 구성할 수 있습니다.

**단일 인덱스 생성**

이 예제에서는 백그라운드에서 `createIndex(`) 메서드를 사용하여 단일 인덱스를 생성하는 방법을 보여줍니다. 배경 및 포그라운드 인덱스 생성을 이해하려면 섹션을 참조하세요[인덱스 빌드 유형](managing-indexes.md#index-build-types). 다음 코드 예제에서는 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html)를 사용하여 백그라운드에서 이름이 “unique\_restaurantId\_idx”인 고유 인덱스를 생성합니다. 그러면 이 `IndexOptions` 객체가 `createIndex()` 메서드로 전달됩니다.

```
collection.createIndex(
    Indexes.ascending("restaurantId"),
    new IndexOptions()
        .unique(true)
        .name("unique_restaurantId_idx")
        .background(true));
```

**여러 인덱스 생성**

이 예제에서는 `createIndexes()` 메서드를 사용하여 여러 인덱스를 생성합니다. 먼저 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html) 객체를 사용하여 각 인덱스에 대한 옵션을 빌드한 다음 `IndexModel` 객체 목록을 `createIndexes()` 메서드에 전달합니다. 다음 코드 예제에서는 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html) 유틸리티 클래스를 사용하여 복합 인덱스를 생성하는 방법을 보여줍니다. 이 클래스는 오름차순 또는 내림차순 정렬 순서를 사용하여 인덱스를 생성할지 여부를 지정하는 데에도 사용됩니다. 여러 인덱스를 생성한 후 `listIndexes()` 메서드를 호출하여 인덱스 생성을 확인합니다.

```
// Single Field Index on cuisine
IndexModel singleIndex = new IndexModel(
    Indexes.ascending("cuisine"),
    new IndexOptions().name("cuisine_idx"));

// Compound Index
IndexModel compoundIndex = new IndexModel(
    Indexes.compoundIndex(
        Indexes.ascending("address.state"),
        Indexes.ascending("priceRange")),
    new IndexOptions().name("location_price_idx"));

// Build a list of IndexModel for the indexes
List < IndexModel > indexes = Arrays.asList(
    singleIndex,
    compoundIndex
);

collection.createIndexes(indexes);

// Verify created indexes
collection.listIndexes().forEach(index - > System.out.println("Created index: " + index.toJson()));
```

**희소 인덱스 및 부분 인덱스 생성**

이 예제에서는 각 인덱스 유형에 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html)을 생성하여 희소 인덱스와 부분 인덱스를 생성합니다.

```
// Sparse Index Model, this will identify only those documents that have a
// michelin star rating
IndexModel sparseIndex = new IndexModel(
    Indexes.ascending("michelin.star"),
    new IndexOptions()
    .name("michelin_sparse_idx")
    .sparse(true));

// Partial Index Model where the restaurant is active and has a rating of 4 and above
IndexModel partialIndex = new IndexModel(
    Indexes.ascending("rating.average"),
    new IndexOptions()
    .name("high_rated_active_idx")
    .partialFilterExpression(
        Filters.and(
            Filters.eq("isActive", true),
            Filters.gte("rating.average", 4.0))));
```

**텍스트 인덱스 생성**

이 예제에서는 텍스트 인덱스를 생성하는 방법을 보여줍니다. 컬렉션에는 하나의 텍스트 인덱스만 허용되지만 하나의 텍스트 인덱스는 여러 필드를 포함하는 복합 인덱스일 수 있습니다. 텍스트 인덱스에서 여러 필드를 사용하는 경우 인덱스의 각 필드에 가중치를 할당할 수도 있습니다. 배열 필드의 텍스트 인덱스는 Amazon DocumentDB에서 지원되지 않으며 복합 텍스트 인덱스에 최대 30개의 필드를 사용할 수 있지만 세 개의 필드만 가중치를 할당할 수 있습니다.

```
IndexModel textIndex = new IndexModel(
    new Document()
    .append("name", "text")
    .append("description", "text")
    .append("cuisine", "text"),
    new IndexOptions()
    .name("restaurant_text_idx")
    .weights(new Document()
        .append("name", 10) // Restaurant name gets highest weight
        .append("description", 5) // Description get medium weight
        .append("cuisine", 2) // Cuisine type gets low weight
    ));

collection.createIndex(textIndex.getKeys(), textIndex.getOptions());
```

**`runCommand()`를 사용하여 인덱스 생성**

Amazon DocumentDB는 병렬 인덱스 생성을 지원하여 인덱스를 생성하는 데 걸리는 시간을 줄입니다. 병렬 인덱싱은 여러 동시 작업자를 사용합니다. 인덱스 생성에 사용되는 기본 작업자는 2명입니다. 이 [블로그 게시물](https://aws.amazon.com/blogs/database/unlock-the-power-of-parallel-indexing-in-amazon-documentdb/)에서는 병렬 인덱싱에 대한 심층적인 설명을 제공합니다. 현재 MongDB Java 드라이버는 `createIndex()` 또는 `createIndexes()`를 사용할 때 작업자 옵션 지정을 지원하지 않으므로 작업자를 지정하는 유일한 방법은 `runCommand`를 통하는 것입니다. 다음 코드 예제에서는 `runCommand`를 사용하여 작업자를 4명으로 늘리는 인덱스를 생성하는 방법을 보여줍니다.

```
Document command = new Document("createIndexes", "Restaurants")
    .append("indexes", Arrays.asList(
        new Document("key", new Document("name", 1))
        .append("name", "restaurant_name_idx")
        .append("workers", 4) // Specify number of workers
    ));

Document commendResult = connectedDB.runCommand(command);
```

## 인덱스 삭제
<a name="dropping-indes"></a>

MongoDB Java 드라이버는 인덱스를 삭제하는 여러 방법을 제공하여 다양한 시나리오와 기본 설정에 맞게 조정할 수 있습니다. 이름이나 키 사양별으로 인덱스를 삭제하거나 모든 인덱스를 한 번에 삭제할 수 있습니다. 컬렉션 객체에서 메서드 `dropIndex()` 및 `dropIndexes()`를 호출하여 인덱스를 삭제할 수 있습니다. 이름별로 인덱스를 삭제할 때는 특히 복합 또는 자동 생성된 인덱스의 경우 항상 직관적이지 않을 수 있는 올바른 인덱스 이름을 사용해야 합니다. 존재하지 않는 인덱스를 삭제하려고 하면 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoCommandException.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoCommandException.html)이 발생합니다. `default _id` 인덱스는 컬렉션 내에서 문서 고유성을 보장하기 때문에 삭제할 수 없습니다.

다음 코드 예제에서는 인덱스가 생성되는 필드 이름을 제공하거나 모든 인덱스를 삭제하여 인덱스를 삭제하는 방법을 보여줍니다.

```
String indexName = "unique_restaurantId_idx";
Document keys = new Document("cuisine", 1);
// Drop index by name
collection.dropIndex(indexName);
            
// Drop index by keys
collection.dropIndex(keys);
            
// Drop all indexes
collection.dropIndexes();
```

여러 키를 사용하여 인덱스를 삭제할 때는 지정된 모든 키가 포함된 복합 인덱스가 있고 키 순서가 올바른지 확인합니다. 위의 인덱스 생성 예제 코드는 "cuisine" 및 기능에 대한 복합 키를 보여줍니다. 해당 복합 키를 삭제하려고 시도하지만 해당 순서가 생성에 사용된 순서가 아닌 경우 MongoCommnadException 오류는 다음과 같이 발생합니다.

```
Document keys = new Document("features", 1)
    .append("cuisine", 1);
try {
    // Drop index by keys
    collection.dropIndex(keys);
    System.out.println("Successfully dropped index with keys: " + keys.toJson());

} catch (MongoCommandException commErr) {
    System.out.println("Error dropping index: " + commErr.getErrorMessage());
    throw new RuntimeException("MongoCommandException was thrown while dropping index", commErr);
}
```

다음 오류가 표시됩니다.

```
{{Error dropping index: Cannot drop index: index not found.}}
{{Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.819 sec <<< FAILURE!
com.amazon.docdb.guide.DocDBGuideTest.testindexGuide()  Time elapsed: 0.817 sec  <<< FAILURE!
org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.RuntimeException: MongoCommandException was thrown while dropping index}}
```

## 인덱스 선택 결정 및 인덱스 힌트 제공
<a name="w2aac45b9b7c17c13"></a>

Amazon DocumentDB에서 설명 기능을 사용하는 작업은 쿼리 성능 및 인덱스 사용량을 이해하는 데 매우 중요합니다. 쿼리를 실행할 때 `explain()` 메서드를 추가하여 사용 중인 인덱스를 포함하여 쿼리 계획에 대한 자세한 정보를 얻을 수 있습니다. `explain()` 출력은 쿼리 실행 단계, 검사된 문서 수, 각 단계에 소요된 시간에 대한 인사이트를 제공합니다. 이 정보는 특정 인덱스가 효과적으로 사용되고 있는지 또는 쿼리가 다른 인덱스 구조의 이점을 누릴 수 있는지 식별하는 데 매우 중요합니다.

`explain()` 메서드는 `find()` 메서드와 함께 연결할 수 있습니다. `explain()` 메서드는 `explain()`에서 반환되는 세부 수준을 결정하는 선택적 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity.html) 열거형을 사용할 수 있습니다. 현재 DocumentDB에서는 `EXECUTION_STATS` 및 `QUERY_PLANNER` 열거자만 지원됩니다. 다음 코드 예제에서는 특정 쿼리에 대한 쿼리 플래너를 가져오는 방법을 보여줍니다.

```
// Query we want to analyze
Document query = new Document()
    .append("cuisine", "Thai")
    .append("rating.average", new Document("$gte", 4.0));


Document allPlansExplain = collection.find(query).explain(ExplainVerbosity.QUERY_PLANNER);
System.out.println("All Plans Explain:\n" + allPlansExplain.toJson());
```

쿼리 플래너 세부 수준에 대해 다음 JSON 문서가 반환됩니다.

```
{
  "queryPlanner": {
    "plannerVersion": 1,
    "namespace": "ProgGuideData.Restaurants",
    "winningPlan": {
      "stage": "IXSCAN",
      "indexName": "cuisine_idx",
      "direction": "forward"
    }
  },
  "serverInfo": {
    "host": "guidecluster3",
    "port": 27017,
    "version": "5.0.0"
  },
  "ok": 1,
  "operationTime": {
    "$timestamp": {
      "t": 1739221668,
      "i": 1
    }
  }
}
```

Amazon DocumentDB가 특정 인덱스를 사용하도록 영향을 미치거나 강제하는 몇 가지 옵션이 있습니다. `hint()` 및 `hintString()` 메서드를 사용하면 쿼리에 사용할 인덱스를 명시적으로 지정하여 쿼리 최적화 프로그램의 기본 인덱스 선택 동작을 재정의할 수 있습니다. DocumentDB의 쿼리 최적화 프로그램은 일반적으로 인덱스 선택에 적합한 선택이지만 왜곡된 데이터를 처리하거나 인덱스 성능을 테스트하는 등 `hint()` 또는 `hintString()`을 통해 특정 인덱스를 강제 적용하는 경우 유용할 수 있습니다.

다음 코드 예제에서는 위 코드에서 실행된 동일한 쿼리에 복합 인덱스 “cuisine\_features\_idx”를 강제로 사용합니다.

```
// Query we want to analyze
Document query = new Document()
    .append("cuisine", "Thai")
    .append("rating.average", new Document("$gte", 4.0));

List < Document > queryDocs = new ArrayList < > ();
collection.find(query).hintString("cuisine_features_idx").forEach(doc - > queryDocs.add(doc));
```