

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

# Amazon DocumentDB 문제 해결
<a name="troubleshooting"></a>

다음 섹션에는 Amazon DocumentDB(MongoDB 호환) 사용 시 발생할 수 있는 문제를 해결하는 방법에 대한 정보가 나와 있습니다.

**Topics**
+ [연결 문제](troubleshooting.connecting.md)
+ [인덱스](troubleshooting.index-creation.md)
+ [성능 및 리소스 사용률](user_diagnostics.md)
+ [가비지 수집](garbage-collection.md)

# 연결 문제 해결
<a name="troubleshooting.connecting"></a>

연결에 문제가 있으신가요? 다음에서는 몇 가지 일반적인 시나리오와 이에 대한 해결 방법에 대해 설명합니다.

**주제**
+ [Amazon DocumentDB 엔드포인트에 연결할 수 없습니다.](#troubleshooting-connecting)
+ [Amazon DocumentDB 인스턴스 연결 테스트](#troubleshooting.testing-connection)
+ [유효하지 않은 엔드포인트에 연결](#troubleshooting.invalid-endpoint)
+ [연결 수에 영향을 미치는 드라이버 구성](#troubleshooting.driver.config)

## Amazon DocumentDB 엔드포인트에 연결할 수 없습니다.
<a name="troubleshooting-connecting"></a>

다음은 Amazon DocumentDB에 연결하려고 할 때 표시될 수 있는 가장 일반적인 오류 메시지 중 하나입니다.

```
connecting to: mongodb://docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east-
1.docdb.amazonaws.com:27017/
2018-11-14T14:33:46.451-0800 W NETWORK [thread1] Failed to connect to
172.31.91.193:27017 after 5000ms milliseconds, giving up.
2018-11-14T14:33:46.452-0800 E QUERY [thread1] Error: couldn't connect to server
docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017,
connection attempt failed :
connect@src/mongo/shell/mongo.js:237:13
@(connect):1:6
exception: connect failed
```

이 오류 메시지의 일반적인 의미는 클라이언트(이 예제에서는 mongo 쉘)가 Amazon DocumentDB 엔드포인트에 액세스할 수 없다는 것입니다. 다음과 같이 여러 가지 원인이 있을 수 있습니다.

**Topics**
+ [퍼블릭 엔드포인트로부터 연결](#troubleshooting.cannot-connect.public-endpoints)
+ [리전 간 연결](#troubleshooting.cannot-connect.different-regions)
+ [다른 Amazon VPC에서 연결](#troubleshooting.cannot-connect.different-vpcs)
+ [보안 그룹이 인바운드 연결을 차단](#troubleshooting.cannot-connect.inbound-not-allowed)
+ [Java Mongo 드라이버 읽기 기본 설정 문제](#troubleshooting-cannot-connect-java-mongo-issue)

### 퍼블릭 엔드포인트로부터 연결
<a name="troubleshooting.cannot-connect.public-endpoints"></a>

**노트북 또는 로컬 개발 머신에서 직접 Amazon DocumentDB 클러스터에 연결하려고 시도하는 중입니다.**

노트북 또는 로컬 개발 머신과 같은 퍼블릭 엔드포인트에서 직접 Amazon DocumentDB 클러스터에 연결하려고 시도하는 것은 실패하게 됩니다. Amazon DocumentDB는 Virtual Private Cloud(VPC) 전용이며 현재 퍼블릭 엔드포인트를 지원하지 않습니다. 따라서 VPC 외부의 노트북 또는 개발 환경에서 Amazon DocumentDB 클러스터에 직접 연결할 수 없습니다.

Amazon VPC 외부에서 Amazon DocumentDB 클러스터에 연결하려면 SSH 터널을 사용할 수 있습니다. 자세한 내용은 [Amazon VPC 외부에서 Amazon DocumentDB 클러스터에 연결](connect-from-outside-a-vpc.md) 섹션을 참조하세요. 또한, 개발 환경이 다른 Amazon VPC에 있을 경우에는 VPC 피어링을 사용하여 동일한 리전 또는 다른 리전의 다른 Amazon VPC에서 Amazon DocumentDB 클러스터에 연결할 수 있습니다.

### 리전 간 연결
<a name="troubleshooting.cannot-connect.different-regions"></a>

**또 다른 리전에 있는 Amazon DocumentDB 클러스터에 연결하려고 합니다.**

클러스터 지역이 아닌 지역의 Amazon EC2 인스턴스에서 Amazon DocumentDB 클러스터에 연결하려고 시도할 경우(예: 미국 서부(오레곤) 지역(us-west-2)에서 미국 동부(버지니아 북부) 지역(us-east-1)의 클러스터에 연결하려고 하면 연결이 실패합니다.

Amazon DocumentDB 클러스터의 리전을 확인하려면 다음 명령을 실행합니다. 리전이 엔드포인트에 있습니다.

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].Endpoint'
```

이 작업의 출력은 다음과 같습니다.

```
[
    "sample-cluster.node.us-east-1.docdb.amazonaws.com"
]
```

EC2 인스턴스의 리전을 확인하려면 다음 명령을 실행합니다.

```
 aws ec2 describe-instances \
     --query 'Reservations[*].Instances[*].Placement.AvailabilityZone'
```

이 작업의 출력은 다음과 같습니다.

```
[
    [
        "us-east-1a"
    ]
]
```

### 다른 Amazon VPC에서 연결
<a name="troubleshooting.cannot-connect.different-vpcs"></a>

**클러스터가 배포된 Amazon VPC가 아닌 다른 Amazon DocumentDB 클러스터에 연결하려고 합니다.**

Amazon DocumentDB 클러스터와 Amazon EC2 인스턴스가 동일한에 AWS 리전있지만 동일한 Amazon VPC에는 없는 경우 두 Amazon VPC 간에 VPC 피어링이 활성화되지 않는 한 Amazon DocumentDB 클러스터에 직접 연결할 수 없습니다 VPCs.

Amazon DocumentDB 인스턴스의 Amazon VPC를 확인하려면 다음 명령을 실행합니다.

```
aws docdb describe-db-instances \
   --db-instance-identifier sample-instance \
   --query 'DBInstances[*].DBSubnetGroup.VpcId'
```

Amazon EC2 인스턴스의 Amazon VPC를 확인하려면 다음 명령을 실행합니다.

```
aws ec2 describe-instances \
   --query 'Reservations[*].Instances[*].VpcId'
```

### 보안 그룹이 인바운드 연결을 차단
<a name="troubleshooting.cannot-connect.inbound-not-allowed"></a>

**Amazon DocumentDB 클러스터에 연결하려고 하는데 클러스터의 보안 그룹이 클러스터 포트(기본 포트: 27017)의 인바운드 연결을 허용하지 않습니다.**

Amazon DocumentDB 클러스터와 Amazon EC2 인스턴스가 모두 동일한 리전 및 Amazon VPC에 있고 동일한 Amazon VPC 보안 그룹을 사용한다고 가정합니다. Amazon DocumentDB 클러스터에 연결할 수 없는 경우 가능성이 높은 원인은 클러스터에 대한 보안 그룹(예: 방화벽)이 Amazon DocumentDB 클러스터에 대해 선택한 포트(기본 포트: 27017)의 인바운드 연결을 허용하지 않기 때문입니다.

Amazon DocumentDB 클러스터의 포트를 확인하려면 다음 명령을 실행합니다.

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[DBClusterIdentifier,Port]'
```

클러스터에 대한 Amazon DocumentDB 보안 그룹을 가져오려면 다음 명령을 실행합니다.

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[VpcSecurityGroups[*],VpcSecurityGroupId]'
```

보안 그룹에 대한 인바운드 규칙을 확인하려면 Amazon EC2 설명서에서 다음 주제를 참조하십시오.
+ [ Linux 인스턴스의 인바운드 트래픽 권한 부여](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html)
+ [ Windows 인스턴스의 인바운드 트래픽 권한 부여](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/authorizing-access-to-an-instance.html)

### Java Mongo 드라이버 읽기 기본 설정 문제
<a name="troubleshooting-cannot-connect-java-mongo-issue"></a>

**클라이언트의 읽기 기본 설정이 적용되지 않으며 일부 클라이언트는 재부팅하지 않는 한 장애 조치 후 Amazon DocumentDB에 쓸 수 없습니다.**

Java Mongo Driver 3.7.x에서 처음 발견된 이 문제는 클라이언트가 특히 `MongoClientSettings` 메서드를 사용하여 Amazon DocumentDB에 연결할 때, 특히 `applyToClusterSettings` 메서드를 체인으로 연결할 때 발생합니다. MongoClient 클러스터 설정은 `hosts()`, `requiredReplicaSetName()`, `mode()`와(과) 같은 몇 가지 다른 방법을 사용하여 정의할 수 있습니다.

 클라이언트가 `hosts()` 메서드에서 호스트를 하나만 지정하면 모드가 `ClusterConnectionMode.SINGLE` 대신 `ClusterConnectionMode.MULTIPLE`으로 설정됩니다. 이렇게 하면 클라이언트는 읽기 기본 설정을 무시하고 `hosts()`에서 구성된 서버에만 연결합니다. 따라서 아래와 같이 클라이언트 설정을 초기화하더라도 모든 읽기는 여전히 보조 서버 대신 기본 서버로 이동합니다.

```
final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317));
    final MongoCredential credential = MongoCredential.createCredential("xxx",
            "admin", "xxxx".toCharArray());
    final MongoClientSettings settings = MongoClientSettings.builder()
            .credential(credential)
            .readPreference(ReadPreference.secondaryPreferred())
            .retryWrites(false)
            .applyToSslSettings(builder -> builder
                    .enabled(false))
            .applyToClusterSettings(builder -> builder.hosts(
                            Arrays.asList(serverAddress0
                            ))
                    .requiredReplicaSetName("rs0"))
            .build();
    MongoClient mongoClient = MongoClients.create(settings);
```

**장애 조치 사례**

위의 클라이언트 연결 설정을 사용하면 클러스터 작성기 엔드포인트에 대한 장애 조치 및 지연된 DNS 레코드 업데이트가 발생하는 경우 클라이언트는 여전히 이전 작성기(이제는 장애 조치 후 리더)에 쓰기를 시도합니다. 이로 인해 서버 측 오류(기본 아님)가 발생하는데, 이 오류는 Java 드라이버에서 적절하게 처리되지 않습니다(이 내용은 아직 조사 중임). 따라서 예를 들어 애플리케이션 서버가 재부팅될 때까지 클라이언트는 잘못된 상태로 남아 있을 수 있습니다.

이에 대한 두 가지 해결 방법이 있습니다.
+ 연결 문자열을 통해 Amazon DocumentDB에 연결하는 클라이언트는 읽기 기본 설정을 지정할 때 `ClusterConnectionMode`가 `MULTIPLE`로 설정되므로 이 문제가 발생하지 않습니다.

  ```
  MongoClientURI mongoClientURI = new MongoClientURI("mongodb://usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred");
  MongoClient mongoClient = MongoClients.create(mongoClientURI.getURI());
  ```

  `applyConnectionString` 메서드와 함께 `MongoClientSettings` 빌더를 사용할 수도 있습니다.

  ```
  final MongoClientSettings settings = MongoClientSettings.builder()
          .credential(credential)
          .applyConnectionString(new ConnectionString("usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred"))
          .retryWrites(false)
          .applyToSslSettings(builder → builder
                  .enabled(false))
          .build();
  MongoClient mongoClient = MongoClients.create(settings);
  ```
+ 명시적으로 `ClusterConnectionMode`을 `MULTIPLE`으로 설정합니다. 이는 `applyToClusterSettings` 및 `hosts().size() == 1`를 사용할 때만 필요합니다.

  ```
  final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317));
  final MongoCredential credential = MongoCredential.createCredential("xxx","admin", "xxxx".toCharArray());
  final MongoClientSettings settings = MongoClientSettings.builder()
      .credential(credential)
      .readPreference(ReadPreference.secondaryPreferred())
      .retryWrites(false)
      .applyToSslSettings(builder → builder
      .enabled(false))
      .applyToClusterSettings(builder → builder
                  .hosts(Arrays.asList(serverAddress0))
                  .requiredReplicaSetName("rs0"))
                  .mode(ClusterConnectionMode.MULTIPLE))
      .build();
  MongoClient mongoClient = MongoClients.create(settings);
  ```

## Amazon DocumentDB 인스턴스 연결 테스트
<a name="troubleshooting.testing-connection"></a>

공통 Linux 또는 Windows 도구를 사용하여 클러스터에 대한 연결을 테스트할 수 있습니다.

 Linux 또는 Unix 터미널에서 다음을 입력하여 연결을 테스트할 수 있습니다(`cluster-endpoint`를 해당 엔드포인트로 바꾸고 `port`를 인스턴스의 포트로 바꿈).

```
nc -zv cluster-endpoint port 
```

다음은 샘플 작업 및 반환 값의 예입니다.

```
nc -zv docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017
   
Connection to docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017 port [tcp/*] succeeded!
```

## 유효하지 않은 엔드포인트에 연결
<a name="troubleshooting.invalid-endpoint"></a>

Amazon DocumentDB 클러스터에 연결하고 유효하지 않은 클러스터 엔드포인트를 사용할 때 다음과 유사한 오류가 표시됩니다.

```
mongo --ssl \
   --host sample-cluster.node.us-east-1.docdb.amazonaws.com:27017 \
   --sslCAFile global-bundle.pem \
   --username <user-name> \
   --password <password>
```

출력은 다음과 같습니다.

```
MongoDB shell version v3.6
connecting to: mongodb://sample-cluster.node.us-east-1.docdb.amazonaws.com:27017/
2018-11-14T17:21:18.516-0800 I NETWORK [thread1] getaddrinfo("sample-cluster.node.us-east-1.docdb.amazonaws.com") failed: 
nodename nor servname provided, or not known 2018-11-14T17:21:18.537-0800 E QUERY [thread1] Error: couldn't initialize
connection to host sample-cluster.node.us-east-1.docdb.amazonaws.com, address is invalid :
connect@src/mongo/shell/mongo.js:237:13@(connect):1:6
exception: connect failed
```

클러스터에 대해 유효한 엔드포인트를 가져오려면 다음 명령을 실행합니다.

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[Endpoint,Port]'
```

인스턴스에 대해 유효한 엔드포인트를 가져오려면 다음 명령을 실행합니다.

```
aws docdb describe-db-instances \
   --db-instance-identifier sample-instance \
   --query 'DBInstances[*].[Endpoint.Address,Endpoint.Port]'
```

자세한 내용은 [Amazon DocumentDB 엔드포인트에 대한 이해](endpoints.md) 단원을 참조하십시오.

## 연결 수에 영향을 미치는 드라이버 구성
<a name="troubleshooting.driver.config"></a>

클라이언트 드라이버를 사용하여 Amazon DocumentDB 클러스터에 연결할 때는 `maxPoolSize` 구성 파라미터를 고려하는 것이 중요합니다. `maxPoolSize` 설정은 클라이언트 드라이버가 연결 풀에서 유지할 최대 연결 수를 결정합니다.

# 인덱스 문제 해결
<a name="troubleshooting.index-creation"></a>

다음 주제에서는 인덱스 또는 배경 인덱스 빌드에 실패한 경우 취해야 할 조치를 설명합니다.

**Topics**
+ [인덱스 빌드 실패](#troubleshooting.index-build-fails)
+ [백그라운드 인덱스 빌드 지연 문제 및 실패](#troubleshooting.background-index-build-fails)
+ [데이터베이스 인덱스 팽창](#troubleshooting-database-bloat)

## 인덱스 빌드 실패
<a name="troubleshooting.index-build-fails"></a>

Amazon DocumentDB는 인덱스 생성 프로세스의 일부로써 인스턴스의 로컬 스토리지를 활용합니다. **FreeLocalStorage** CloudWatch 지표(`CloudWatch -> Metrics -> DocDB -> Instance Metrics`)를 사용하여 이 디스크 사용량을 모니터링할 수 있습니다. 인덱스 빌드에 로컬 디스크 전체가 사용되고 실패할 경우 오류가 표시됩니다. 데이터를 Amazon DocumentDB로 마이그레이션할 경우 먼저 인덱스를 생성한 다음 데이터를 삽입하는 것이 좋습니다. 마이그레이션 전략 및 인덱스 생성에 대한 자세한 내용은 Amazon DocumentDB 설명서의 [Amazon DocumentDB로 마이그레이션](docdb-migration.md) 섹션과 [오프라인 방법을 사용한 MongoDB에서 Amazon DocumentDB로의 마이그레이션](https://aws.amazon.com/blogs/database/migrate-from-mongodb-to-amazon-documentdb-using-the-offline-method/) 블로그를 참조하십시오.

기존 클러스터에서 인덱스를 생성할 때 인덱스 빌드에 예상보다 시간이 오래 걸리거나 실패하는 경우, 인스턴스 크기를 늘려(규모 조정) 인덱스를 생성한 다음 다시 축소하는 것이 좋습니다. Amazon DocumentDB를 사용하면 AWS Management Console 또는를 사용하여 인스턴스 크기를 몇 분 만에 빠르게 조정할 수 있습니다 AWS CLI. 자세한 내용은 [인스턴스 클래스 관리](db-instance-classes.md) 단원을 참조하십시오. 초당 요금이 청구되는 경우, 초 단위로 계산하여 사용한 리소스에 대해서만 지불하면 됩니다.

## 백그라운드 인덱스 빌드 지연 문제 및 실패
<a name="troubleshooting.background-index-build-fails"></a>

Amazon DocumentDB의 백그라운드 인덱스 빌드는 인덱스 빌드가 시작되기 전에 시작된 기본 인스턴스의 모든 쿼리가 실행될 때까지 시작되지 않습니다. 쿼리가 오래 실행되는 경우 쿼리가 완료될 때까지 백그라운드 인덱스 빌드가 차단되므로 완료하는 데 예상보다 시간이 오래 걸릴 수 있습니다. 컬렉션이 비어 있는 경우에도 마찬가지입니다.

포그라운드 인덱스 빌드는 동일한 차단 동작을 나타내지 않습니다. 대신 포그라운드 인덱스 빌드는 인덱스 빌드가 완료될 때까지 컬렉션을 독점적으로 잠급니다. 따라서 빈 컬렉션에 인덱스를 만들고 장기 실행 쿼리가 차단되지 않도록 하려면 포그라운드 인덱스 빌드를 사용하는 것이 좋습니다.

**참고**  
Amazon DocumentDB는 특정 시간에 모음에서 발생하는 배경 인덱스 빌드를 하나만 허용합니다. 배경 인덱스 빌드 중에 동일한 컬렉션에 `createIndex()` 또는 `dropIndex()`와 같은 DDL(Data Definition Language) 연산이 발생하면 배경 인덱스 빌드가 실패합니다.

## 데이터베이스 인덱스 팽창
<a name="troubleshooting-database-bloat"></a>

Amazon DocumentDB는 다중 버전 동시성 제어(MVCC)를 사용하여 동시 트랜잭션을 관리합니다. 문서가 삭제되거나 업데이트되면 이전 버전은 컬렉션 및 인덱스에 ‘데드’ 버전으로 유지됩니다. 폐영역 회수 프로세스는 향후 작업을 위해 이러한 데드 버전에서 공간을 자동으로 회수합니다.

인덱스 팽창은 데드 버전 또는 더 이상 사용되지 않는 인덱스 항목이 누적되거나 페이지 내에 조각화되면서 컬렉션의 인덱스가 커질 때 발생합니다. 보고된 백분율은 향후 인덱스 항목에서 사용할 수 있는 인덱스 공간의 양을 나타냅니다. 이 팽창은 버퍼 캐시와 스토리지 모두에서 공간을 소비합니다. 팽창을 제거하려면 인덱스를 다시 빌드해야 합니다.

**Example 예제**  
다음 명령을 실행하여 인덱스의 미사용 스토리지를 확인합니다.  

```
db.coll.aggregate({$indexStats:{}});
```
다음과 비슷한 결과가 반환됩니다.  

```
{ 
    "name" : "_id_",
    "key" : { 
        "_id" : 1 
    },
    "host" : "devbox-test.localhost.a2z.com:27317",
    "size" : NumberLong(827392),
    "accesses" : {
        "ops" : NumberLong(40000),
        "docsRead" : NumberLong(46049),
        "since" : ISODate("2025-04-03T21:44:51.251Z") 
    },
    "cacheStats" : {
        "blksRead" : NumberLong(264),
        "blksHit" : NumberLong(140190),
        "hitRatio" : 99.8121
    }, 
    "unusedStorageSize" : {
        "unusedSizeBytes" : 409600,
        "unusedSizePercent" : 49.51
    }
}
```

전체 컬렉션을 스캔해야 하는 `reIndex` 명령을 사용하여 가동 중지 없이 인덱스를 다시 빌드할 수 있습니다. [`reIndex`를 사용한 인덱스 유지 관리](managing-indexes.md#reIndex)을(를) 참조하세요.

# 성능 및 리소스 사용률 문제 해결
<a name="user_diagnostics"></a>

이 섹션에서는 Amazon DocumentDB 배포 시 일반적인 진단 문제에 대한 질문과 솔루션을 제공합니다. 제공된 예제는 *mongo 쉘*을 사용하며 개별 인스턴스에 적용됩니다. 인스턴스 엔드포인트를 찾으려면 [Amazon DocumentDB 엔드포인트에 대한 이해](endpoints.md)을 참조하세요.

**Topics**
+ [Mongo API를 통해 내 컬렉션에 대해 수행된 삽입, 업데이트 및 삭제 작업 수를 확인하려면 어떻게 해야 하나요?](#user-diag-performed-operations)
+ [캐시 성능을 분석하려면 어떻게 해야 하나요?](#user-diag-cache-perf)
+ [장시간 실행 중이거나 차단된 쿼리를 찾아서 종료하려면 어떻게 해야 하나요?](#user_diagnostics-query_terminating)
+ [쿼리 계획을 보고 쿼리를 최적화하려면 어떻게 해야 하나요?](#user_diagnostics-query_plan)
+ [엘라스틱 클러스터에서 쿼리 계획을 확인하려면 어떻게 해야 하나요?](#user-diagnostics-ec-query-plan)
+ [인스턴스에서 실행 중인 작업을 모두 나열하려면 어떻게 해야 하나요?](#user_diagnostics-list_queries)
+ [쿼리 진행 상황을 어떻게 알 수 있나요?](#user_diagnostics-query_progressing)
+ [시스템이 갑자기 느리게 실행되는 이유를 어떻게 알 수 있나요?](#user_diagnostics-speed_change)
+ [하나 이상의 클러스터 인스턴스에서 높은 CPU 사용률의 원인을 어떻게 확인하나요?](#user_diagnostics-cpu_utilization)
+ [인스턴스에서 열려 있는 커서를 어떻게 확인하나요?](#user_diagnostics-open_cursors)
+ [현재 Amazon DocumentDB 엔진 버전은 어떻게 확인하나요?](#user_diagnostics-engine_version)
+ [인덱스 사용량을 분석하고 사용하지 않는 인덱스를 식별하려면 어떻게 해야 하나요?](#user-diag-index-usage)
+ [누락된 인덱스는 어떻게 식별하나요?](#user_diagnostics-identify_missing_indexes)
+ [데이터베이스 수집 팽창을 확인하려면 어떻게 해야 하나요?](#performance-collection-bloat)
+ [유용한 쿼리 요약](#user_diagnostics-useful_queries)

## Mongo API를 통해 내 컬렉션에 대해 수행된 삽입, 업데이트 및 삭제 작업 수를 확인하려면 어떻게 해야 하나요?
<a name="user-diag-performed-operations"></a>

특정 컬렉션에서 수행된 삽입, 업데이트 및 삭제 작업 수를 보려면 해당 컬렉션에서 다음 명령을 실행합니다.

```
db.collection.stats()
```

명령에 대한 출력은 `opCounters` 필드에서 다음과 같습니다.
+ **numDocsIns** - 이 컬렉션에 삽입된 문서 수입니다. 여기에는 `insert` 및 `insertMany` 명령을 사용하여 삽입한 문서와 업서트로 삽입한 문서가 포함됩니다.
+ **numDocsUpd** - 이 컬렉션에서 업데이트된 문서 수입니다. 여기에는 `update` 및 `findAndModify` 명령을 사용하여 업데이트한 문서가 포함됩니다. 
+ **numDocsDel** - 이 컬렉션에서 삭제된 문서 수입니다. 여기에는 `deleteOne`, `deleteMany`, `remove`, 및 `findAndModify` 명령을 사용하여 삭제된 문서가 포함됩니다. 
+ **lastReset** - 이 카운터를 마지막으로 재설정한 시간입니다. 이 명령으로 제공된 통계는 클러스터를 시작/중지하거나 인스턴스를 스케일 업/다운할 때 재설정됩니다.

`db.collection.stats()`를 실행한 예제 출력은 다음과 같습니다.

```
{
    "ns" : "db.test",
    "count" : ...,
    "size" : ...,
    "avgObjSize" : ...,
    "storageSize" : ...,
    "capped" : false,
    "nindexes" : ...,
    "totalIndexSize" : ...,
    "indexSizes" : {
        "_id_" : ...,
        "x_1" : ...
    },
    "collScans" : ...,
    "idxScans" : ...,
    "opCounter" : {
        "numDocsIns" : ...,
        "numDocsUpd" : ...,
        "numDocsDel" : ...
    },
    "cacheStats" : {
        "collBlksHit" : ...,
        "collBlksRead" : ..,
        "collHitRatio" : ...,
        "idxBlksHit" : ...,
        "idxBlksRead" : ...,
        "idxHitRatio" : ...
    },
    "lastReset" : "2022-09-02 19:41:40.471473+00",
    "ok" : 1,
    "operationTime" : Timestamp(1662159707, 1)
}
```

이 stats 명령은 Mongo API를 통해 삽입, 업데이트 및 삭제 작업에 대한 컬렉션별 카운터를 볼 때 사용해야 합니다. 컬렉션별 작업 카운터를 보는 또 다른 방법은 DML 감사를 활성화하는 것입니다. 1분 간격 동안의 모든 컬렉션에 대한 삽입, 업데이트 및 삭제 작업 수는 [CloudWatch를 사용하여 Amazon DocumentDB 모니터링](cloud_watch.md)에서 확인할 수 있습니다.

## 캐시 성능을 분석하려면 어떻게 해야 하나요?
<a name="user-diag-cache-perf"></a>

캐시 성능을 분석하면 캐시와 비교하여 디스크에서 읽은 데이터의 양을 기반으로 데이터 검색 효율성과 시스템 성능에 대한 통찰력을 얻을 수 있습니다. 캐시 성능에 대한 통찰력을 제공하기 위해 캐시 적중 수(캐시에서 읽은 데이터) 및 캐시 실패(캐시에 없고 디스크에서 읽은 데이터) 에 대한 캐시 통계를 제공합니다. 특정 컬렉션에 대한 캐시 통계는 해당 컬렉션에서 다음 명령을 실행하여 확인할 수 있습니다.

```
db.collection.stats()
```

이 명령 출력의 `cacheStats` 필드 값은 컬렉션에 대한 캐시 통계는 물론 컬렉션에 생성된 인덱스의 전체 캐시 통계도 제공합니다. 이러한 통계는 다음과 같습니다.
+ **`collBlksHit`** - 이 컬렉션에 대한 작업 중에 캐시에서 읽은 블록 수입니다.
+ **`collBlksRead`** - 이 컬렉션에 대한 작업 중에 디스크에서 읽은 블록 수(캐시 누락)입니다.
+ **`collHitRatio`** - 이 컬렉션의 캐시 적중률(`100 * [collBlksHit / (collBlksHit + collBlksRead)]`).
+ **`idxBlksHit`** - 이 컬렉션에서 생성된 인덱스에 대해 캐시에서 읽은 블록 수입니다.
+ **`idxBlksRead`** - 이 컬렉션에서 생성된 인덱스에 대해 디스크에서 읽은 블록 수(캐시 누락)입니다.
+ **`idxHitRatio`** - 이 컬렉션에서 생성된 인덱스의 캐시 적중률(`100 * [idxBlksHit / (idxBlksHit + idxBlksRead)]`).
+ **`lastReset`** - 이 통계가 마지막으로 재설정된 시간. `db.collection.stats()`에 의해 제공된 통계는 클러스터를 시작/중지하거나 인스턴스를 스케일 업/다운할 때 재설정됩니다.

`indexStats` 명령을 사용하여 각 인덱스의 `idxBlksHit` 및 `idxBlksRead` 필드의 분류를 확인할 수도 있습니다. 인덱스별 캐시 통계는 다음 명령을 실행하여 확인할 수 있습니다.

```
db.collection.aggregate([{$indexStats:{}}]).pretty()
```

각 인덱스에 대해 `cacheStats` 필드 아래에서 다음과 같은 캐시 통계를 찾을 수 있습니다.
+ **`blksHit`** - 이 인덱스에 대해 캐시에서 읽은 블록 수입니다.
+ **`blksRead`** - 이 인덱스에 대해 디스크에서 읽은 블록 수입니다.
+ **`blksHitRatio`** - `100 * [blksHit / (blksHit + blksRead)]`에서 캐시 적중률을 소수점 네 자리로 반올림하여 계산합니다.

## 장시간 실행 중이거나 차단된 쿼리를 찾아서 종료하려면 어떻게 해야 하나요?
<a name="user_diagnostics-query_terminating"></a>

사용자 쿼리는 최적화되지 않은 쿼리 계획으로 인해 실행 속도가 느려지거나 리소스 경합으로 인해 차단될 수 있습니다.

최적이지 않은 쿼리 계획으로 인해 느려지고 오래 실행되는 쿼리나, 속도가 느려지거나 리소스 경합으로 인해 차단된 쿼리를 찾으려면 `currentOp` 명령을 사용하세요. 명령을 필터링하면 종료할 쿼리의 목록을 좁힐 수 있습니다. 쿼리를 종료하려면 장시간 실행 중인 쿼리와 연결된 `opid`가 필요합니다.

다음 쿼리는 `currentOp` 명령을 사용하여 차단되었거나 10초 이상 실행 중인 모든 쿼리를 나열합니다.

```
db.adminCommand({
    aggregate: 1,
    pipeline: [
        {$currentOp: {}},
        {$match: 
            {$or: [
                {secs_running: {$gt: 10}},
                {WaitState: {$exists: true}}]}},
        {$project: {_id:0, opid: 1, secs_running: 1}}],
    cursor: {}
});
```

다음으로, 쿼리 결과를 좁혀 10초를 초과하여 실행 중인 쿼리의 `opid`를 찾아 종료할 수 있습니다.

**10초를 초과하여 실행 중인 쿼리를 찾아 종료하려면**

1. 쿼리의 `opid`를 찾습니다.

   ```
   db.adminCommand({
       aggregate: 1,
       pipeline: [
           {$currentOp: {}},
           {$match: 
               {$or: 
                   [{secs_running: {$gt: 10}},
                    {WaitState: {$exists: true}}]}}],
       cursor: {}
   });
   ```

   이 작업의 출력은 다음과 같습니다(JSON 형식).

   ```
   {
       "waitedMS" : NumberLong(0),
       "cursor" : {
           "firstBatch" : [
               {
                   "opid" : 24646,
                   "secs_running" : 12 
               }
           ],
           "id" : NumberLong(0),
           "ns" : "admin.$cmd"
       },
       "ok" : 1
   }
   ```

1. `killOp` 작업을 사용하여 쿼리를 종료합니다.

   ```
   db.adminCommand({killOp: 1, op: 24646});
   ```

## 쿼리 계획을 보고 쿼리를 최적화하려면 어떻게 해야 하나요?
<a name="user_diagnostics-query_plan"></a>

쿼리의 실행 속도가 느린 경우 이 상황은 쿼리 실행 시 모음 전체 검색하여 관련 문서를 선택해야 하기 때문에 발생했을 수 있습니다. 경우에 따라 적절한 인덱스를 생성하면 쿼리 실행 속도가 빨라질 수도 있습니다. 이 시나리오를 찾아내어 인덱스를 생성할 기준 필드를 결정하려면 `explain` 명령을 사용합니다.

**참고**  
Amazon DocumentDB는 분산, 내결함성, 자가 치유 스토리지 시스템을 활용하는 목적으로 만들어진 목적별 데이터베이스 엔진에서 MongoDB 3.6 API를 에뮬레이션합니다. 그 결과, 쿼리 계획과 `explain()`의 출력은 Amazon DocumentDB와 MongoDB 간에 다를 수 있습니다. 쿼리 계획을 제어하려는 고객은 `$hint` 연산자를 사용하여 기본 인덱스를 선택할 수 있습니다.

다음과 같이 `explain` 명령에서 개선하려는 쿼리를 실행합니다.

```
db.runCommand({explain: {<query document>}})
```

예는 다음과 같습니다.

```
db.runCommand({explain:{
    aggregate: "sample-document",
    pipeline: [{$match: {x: {$eq: 1}}}],
    cursor: {batchSize: 1}}
});
```

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "db.test",
        "winningPlan" : {
            "stage" : "COLLSCAN"
        }
    },
    "serverInfo" : {
        "host" : "...",
        "port" : ...,
        "version" : "..."
    },
    "ok" : 1
}
```

위의 출력은 `$match` 단계에서 전체 모음을 검색하고 각 문서의 `"x"` 필드가 1인지 확인해야 함을 나타냅니다. 모음에 여러 문서가 있는 경우 모음 검색 및 전체 쿼리 성능이 매우 느려질 수 있습니다. 그러므로 `explain` 명령의 출력에 `"COLLSCAN"`이 있는 경우 이는 적정 인덱스를 생성하여 쿼리 성능을 향상시킬 수 있음을 나타냅니다.

이 예제에서 쿼리는 모든 문서에서 `"x"` 필드가 1인지 확인합니다. 따라서 `"x"` 필드에서 인덱스를 작성하면 쿼리가 전체 컬렉션 스캔을 피하고 인덱스를 사용하여 관련 문서를 더 빨리 반환할 수 있습니다.

`"x"` 필드에 인덱스를 생성한 후 `explain` 출력은 다음과 같습니다.

```
{
    "queryPlanner" : {
         "plannerVersion" : 1,
         "namespace" : "db.test",
         "winningPlan" : {
             "stage" : "IXSCAN",
             "indexName" : "x_1",
             "direction" : "forward"
         }
    },
    "serverInfo" : {
        "host" : "...",
        "port" : ...,
        "version" : "..."
    },
    "ok" : 1
}
```

그러므로 `"x"` 필드에 대한 인덱스를 생성하면 `$match` 단계에서 인덱스 검색을 통해 조건자 `"x = 1"`을 평가해야 하는 문서 수를 줄일 수 있습니다.

작은 컬렉션에서는 성능 이득이 무시할 수준인 경우 Amazon DocumentDB 쿼리 프로세서는 인덱스를 사용하지 않도록 결정할 수 있습니다.

## 엘라스틱 클러스터에서 쿼리 계획을 확인하려면 어떻게 해야 하나요?
<a name="user-diagnostics-ec-query-plan"></a>

엘라스틱 클러스터의 쿼리 계획을 검사하려면 `explain` 명령을 사용합니다. 다음은 샤딩된 컬렉션을 대상으로 하는 찾기 쿼리의 예제 `explain` 작업입니다.

```
db.runCommand(
   {
     explain: { find: "cities", filter: {"name": "Seoul"}}
   }
)
```

**참고**  
Amazon DocumentDB는 특별히 구축된 목적별 데이터베이스 엔진에서 MongoDB를 에뮬레이션합니다. 그 결과, 쿼리 계획과 `explain()`의 출력은 Amazon DocumentDB와 MongoDB 간에 다를 수 있습니다. `$hint` 연산자를 사용하여 기본 인덱스를 선택하도록 하여 쿼리 계획을 제어할 수 있습니다.

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{
  "queryPlanner" : {
    "elasticPlannerVersion" : 1,
    "winningPlan" : {
      "stage" : "SINGLE_SHARD",
      "shards" : [
        {
          "plannerVersion" : 1,
          "namespace" : "population.cities",
          "winningPlan" : {
            "stage" : "SHARD_MERGE",
            "shards" : [
              {
                "shardName" : "f2cf5cfd-fe9c-40ca-b4e5-298ca0d11111",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 21
                    }
                  ]
                }
              },
              {
                "shardName" : "8f3f80e2-f96c-446e-8e9d-aab8c7f22222",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 21
                    }
                  ]
                }
              },
              {
                "shardName" : "32c5a06f-1b2b-4af1-8849-d7c4a033333",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 22
                    }
                  ]
                }
              }
            ]
          },
          "shardName" : "32c5a06f-1b2b-4af1-8849-d7c4a0f3fb58"
        }
      ]
    }
  },
  "serverInfo" : {
    "host" : "example-4788267630.us-east-1.docdb-elastic.amazonaws.com:27017",
    "version" : "5.0.0"
  },
  "ok" : 1,
  "operationTime" : Timestamp(1695097923, 1)
}
```

위 출력은 3개 샤드 클러스터의 `find` 쿼리에 대한 쿼리 계획을 보여줍니다. 각 샤드에는 입력 단계가 서로 다를 수 있는 데이터 파티션이 여러 개 있습니다. 이 예시에서는 결과가 각 샤드의 ‘PARTITION\$1MERGE’ 단계에서 병합되기 전에 모든 파티션에서 ‘COLLSCAN’(컬렉션 스캔)이 실행됩니다. 그런 다음 샤드 전체의 결과가 'SHARD\$1MERGE' 단계에서 병합된 후 클라이언트로 다시 전송됩니다.

## 인스턴스에서 실행 중인 작업을 모두 나열하려면 어떻게 해야 하나요?
<a name="user_diagnostics-list_queries"></a>

사용자 또는 기본 사용자로서, 진단 및 문제 해결을 위해 인스턴스에서 실행 중인 모든 현재 작업을 나열해야 하는 경우가 흔히 있습니다. (사용자 관리에 대한 자세한 내용은 [Amazon DocumentDB 사용자 관리](security.managing-users.md) 섹션을 참조하세요.)

`mongo` 쉘을 사용하여 다음 쿼리를 통해 Amazon DocumentDB 인스턴스에서 실행 중인 모든 작업을 나열할 수 있습니다.

```
db.adminCommand({currentOp: 1, $all: 1});
```

이 쿼리는 현재 인스턴스에서 실행 중인 모든 사용자 쿼리 및 내부 시스템 작업의 전체 목록을 반환합니다.

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{
    "inprog" : [
        {
            "desc" : "INTERNAL"
        },
        {
            "desc" : "TTLMonitor",
            "active" : false
        },
        {
            "client" : ...,
            "desc" : "Conn",
            "active" : true,
            "killPending" : false,
            "opid" : 195,
            "ns" : "admin.$cmd",
            "command" : {
                "currentOp" : 1,
                "$all" : 1
            },
            "op" : "command",
            "$db" : "admin",
            "secs_running" : 0,
            "microsecs_running" : NumberLong(68),
            "clientMetaData" : {
            "application" : {
                "name" : "MongoDB Shell"
            },
            "driver" : {
                ...
            },
            "os" : {
                ...
            }
          }
       },
       {
          "desc": "GARBAGE_COLLECTION",
          "garbageCollection": {
             "databaseName": "testdb",
             "collectionName": "testCollectionA"
          },
          "secs_running": 3,
          "microsecs_running": NumberLong(3123456)
       },
       {
          "desc": "GARBAGE_COLLECTION",
          "garbageCollection": {
             "databaseName": "testdb",
             "collectionName": "testCollectionB"
          },
          "secs_running": 4,
          "microsecs_running": NumberLong(4123456)
       }
    ],
    "ok" : 1
}
```

`"desc"` 필드의 유효한 값은 다음과 같습니다.
+ **INTERNAL** - 커서 정리 또는 기한 경과 사용자 정리 작업 같은 내부 시스템 작업입니다.
+ **TTLMonitor** - 유지 시간(TTL) 모니터 스레드입니다. 실행 중 상태가 `"active"` 필드에 반영됩니다.
+ **GARBAGE\$1COLLECTION** - 내부 가비지 수집기 스레드입니다.
+ **CONN** - 사용자 쿼리입니다.
+ **CURSOR** - 이 작업은 사용자가 ‘getMore’ 명령을 호출하여 다음 일괄 결과를 가져오기를 기다리는 유휴 상태의 커서입니다. 이 상태에서는 커서가 메모리를 소비하지만 컴퓨팅은 소비하지 않습니다.

이전 출력에는 시스템에서 실행 중인 모든 사용자 쿼리도 나열됩니다. 각 사용자 쿼리는 데이터베이스 및 모음의 컨텍스트에서 실행되며 이들의 결합을 *네임스페이스*라고 합니다. 각 사용자 쿼리의 네임스페이스는 `"ns"` 필드에서 사용할 수 있습니다.

때로는 특정 네임스페이스에서 실행 중인 모든 사용자 쿼리를 나열해야 합니다. 따라서 `"ns"` 필드에서 이전 출력을 필터링해야 합니다. 필터링할 출력을 얻기 위한 예제 쿼리는 다음과 같습니다. 쿼리는 데이터베이스 `"db"` 및 `"test"` 컬렉션(즉, `"db.test"` 네임스페이스)에서 현재 실행 중인 모든 사용자 쿼리를 나열합니다.

```
db.adminCommand({aggregate: 1,
    pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
               {$match: {ns: {$eq: "db.test"}}}],
    cursor: {}
});
```

시스템의 기본 사용자는 모든 사용자의 쿼리와 및 모든 내부 시스템 작업을 볼 수 있습니다. 다른 모든 사용자는 각자의 쿼리만 볼 수 있습니다.

총 쿼리 수와 내부 시스템 작업 수가 기본 배치 커서 크기를 초과하는 경우 `mongo` 쉘에서 반복자 객체 `'it'`이 자동으로 생성되어 나머지 결과를 표시합니다. 모든 결과가 표시될 때까지 `'it'` 명령을 계속 실행합니다.

## 쿼리 진행 상황을 어떻게 알 수 있나요?
<a name="user_diagnostics-query_progressing"></a>

사용자 쿼리는 최적화되지 않은 쿼리 계획으로 인해 실행 속도가 느려지거나 리소스 경합으로 인해 차단될 수 있습니다. 이러한 쿼리를 디버깅하는 작업은 다단계 프로세스로 경우에 따라서는 동일 단계를 여러 번 실행해야 할 수도 있습니다.

디버깅의 첫 번째 단계는 장시간 실행 중이거나 차단된 모든 쿼리를 나열하는 것입니다. 다음 쿼리는 실행 시간이 10초를 넘었거나 리소스 대기 중인 모든 사용자 쿼리를 나열합니다.

```
db.adminCommand({aggregate: 1,
                 pipeline: [{$currentOp: {}},
                            {$match: {$or: [{secs_running: {$gt: 10}},
                                            {WaitState: {$exists: true}}]}},
                            {$project: {_id:0,
                                        opid: 1,
                                        secs_running: 1,
                                        WaitState: 1,
                                        blockedOn: 1,
                                        command: 1}}],
                 cursor: {}
                });
```

위의 쿼리를 주기적으로 반복 실행하여 쿼리 목록의 변경 여부를 확인하고 장시간 실행 중이거나 차단된 쿼리를 찾습니다.

해당 쿼리의 출력 문서에 `WaitState` 필드가 있는 경우 이는 쿼리 실행 속도가 느리거나 쿼리 실행이 차단된 이유가 리소스 경합 때문임을 나타냅니다. 리소스 경합은 I/O, 내부 시스템 작업 또는 다른 사용자 쿼리가 원인일 수 있습니다.

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{
    "waitedMS" : NumberLong(0),
    "cursor" : {
        "firstBatch" : [
            {
                "opid" : 201,
                "command" : {
                    "aggregate" : ...
                },
                "secs_running" : 208,
                "WaitState" : "IO"
            }
        ],
        "id" : NumberLong(0),
        "ns" : "admin.$cmd"
    },
    "ok" : 1
}
```

동일 인스턴스에 대해 동시에 여러 모음에 대한 여러 쿼리가 있거나 쿼리가 실행 중인 데이터 세트에 비해 인스턴스 크기가 너무 작은 경우 IO가 병목 요인일 수 있습니다. 쿼리가 읽기 전용 쿼리인 경우 이전 상황에 대한 완화 방법은 여러 복제본에 대해 각 모음별로 쿼리를 분리하는 것입니다. 다양한 모음을 동시에 업데이트하거나 인스턴스 크기가 데이터 세트에 비해 너무 작은 경우 완화 방법은 인스턴스 크기를 스케일 업하는 것입니다.

리소스 경합이 다른 사용자 쿼리로 인해 발생하는 경우 출력 문서의 `"blockedOn"` 필드에 이 쿼리에 영향을 주는 쿼리의 `"opid"`가 있습니다. 모든 쿼리의 `"WaitState"` 및 `"blockedOn"` 필드 체인 뒤에 `"opid"`를 사용하여 체인의 헤드에서 쿼리를 찾습니다.

체인의 헤드에 있는 작업이 내부 작업이면 이 경우 유일한 완화 방법은 쿼리를 종료했다가 잠시 후에 다시 실행하는 방법뿐입니다.

아래에는 다른 작업이 소유하는 모음 잠금에서 찾기 쿼리가 차단된 샘플 출력이 나와 있습니다.

```
{
    "inprog" : [
        {
            "client" : "...",
            "desc" : "Conn",
            "active" : true,
            "killPending" : false,
            "opid" : 75,
            "ns" : "...",
            "command" : {
                "find" : "...",
                "filter" : {

                }
            },
            "op" : "query",
            "$db" : "test",
            "secs_running" : 9,
            "microsecs_running" : NumberLong(9449440),
            "threadId" : 24773,
            "clientMetaData" : {
                "application" : {
                   "name" : "MongoDB Shell"
                },
                "driver" : {
                    ...
                },
                "os" : {
                    ...
                }
            },
            "WaitState" : "CollectionLock",
            "blockedOn" : "INTERNAL"
        },
        {
            "desc" : "INTERNAL"
        },
        {
            "client" : "...",
            ...
            "command" : {
                "currentOp" : 1
            },
            ...
        }
    ],
    "ok" : 1
}
```

`"WaitState"`의 값이 `"Latch"`, `"SystemLock"`, `"BufferLock"`, `"BackgroundActivity"` 또는 `"Other"`이면 리소스 경합의 원인은 내부 시스템 작업입니다. 이 상황이 장시간 지속되는 경우 유일한 완화 방법은 쿼리를 종료했다가 나중에 다시 실행하는 방법뿐입니다.

## 시스템이 갑자기 느리게 실행되는 이유를 어떻게 알 수 있나요?
<a name="user_diagnostics-speed_change"></a>

다음은 시스템 속도가 느려지는 몇 가지 일반적인 이유입니다.
+ 동시 쿼리 간 과도한 리소스 경합 
+ 시간이 지남에 따라 증가하는 활성 동시 쿼리 수
+ `"GARBAGE_COLLECTION"` 같은 내부 시스템 작업

시간 경과에 따른 시스템 사용량을 모니터링하려면 다음 `"currentOp"` 쿼리를 주기적으로 실행하고 그 결과를 외부 저장소로 출력합니다. 이 쿼리는 시스템의 각 네임스페이스에서 쿼리 및 작업 수를 셉니다. 그 다음에는 시스템 사용량 결과를 분석하여 시스템에 대한 부하를 파악하고 그에 따른 적절한 조치를 취할 수 있습니다.

```
db.adminCommand({aggregate: 1,
                 pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
                            {$group: {_id: {desc: "$desc", ns: "$ns", WaitState: "$WaitState"}, count: {$sum: 1}}}],
                 cursor: {}
                });
```

이 쿼리는 각 네임스페이스에서 실행 중인 모든 쿼리, 모든 내부 시스템 작업, 그리고 네임스페이스별 고유한 대기 상태 수의 집계 값을 반환합니다.

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{
    "waitedMS" : NumberLong(0),
    "cursor" : {
        "firstBatch" : [
            {
                "_id" : {
                    "desc" : "Conn",
                    "ns" : "db.test",
                    "WaitState" : "CollectionLock"
                },
               "count" : 2
            },
            {
                "_id" : {
                    "desc" : "Conn",
                    "ns" : "admin.$cmd"
                },
                "count" : 1
            },
            {
                "_id" : {
                    "desc" : "TTLMonitor"
                },
                "count" : 1
            }
        ],
        "id" : NumberLong(0),
        "ns" : "admin.$cmd"
    },
    "ok" : 1
}
```

이전 출력에서, 모음 잠금에 대해 차단된 네임스페이스 `"db.test"`에 사용자 쿼리 2개가 있고, 네임스페이스 `"admin.$cmd"`의 쿼리 1개, 그리고 내부 `"TTLMonitor"` 작업 1개가 있습니다.

출력에 차단 대기 상태인 쿼리가 여러 개 있으면 [장시간 실행 중이거나 차단된 쿼리를 찾아서 종료하려면 어떻게 해야 하나요?](#user_diagnostics-query_terminating) 섹션을 참조합니다.

## 하나 이상의 클러스터 인스턴스에서 높은 CPU 사용률의 원인을 어떻게 확인하나요?
<a name="user_diagnostics-cpu_utilization"></a>

다음 섹션은 인스턴스 CPU 사용률이 높은 원인을 식별하는 데 도움이 될 수 있습니다. 워크로드에 따라 결과가 달라질 수 있습니다.
+ 인스턴스가 갑자기 느리게 실행되는 이유를 확인하려면 [시스템이 갑자기 느리게 실행되는 이유를 어떻게 알 수 있나요?](#user_diagnostics-speed_change) 섹션을 참조하세요.
+ 특정 인스턴스에서 장기 실행 쿼리를 식별하고 종료하려면 [장시간 실행 중이거나 차단된 쿼리를 찾아서 종료하려면 어떻게 해야 하나요?](#user_diagnostics-query_terminating) 섹션을 참조합니다.
+ 쿼리가 진행 중인지 알아보려면 [쿼리 진행 상황을 어떻게 알 수 있나요?](#user_diagnostics-query_progressing) 섹션을 참조하세요.
+ 쿼리를 실행하는 데 시간이 오래 걸리는 이유를 확인하려면 [쿼리 계획을 보고 쿼리를 최적화하려면 어떻게 해야 하나요?](#user_diagnostics-query_plan) 섹션을 참조하세요.
+ 시간의 경과에 따라 장기 실행 쿼리를 추적하려면 [Amazon DocumentDB 작업 프로파일링](profiling.md) 섹션을 참조합니다.

높은 인스턴스 CPU 사용률의 이유에 따라 다음 중 하나 이상을 수행하면 도움이 될 수 있습니다.
+ 기본 인스턴스의 CPU 사용률이 높지만 복제본 인스턴스는 그렇지 않은 경우 클라이언트 읽기 기본 설정(예: `secondaryPreferred`)을 통해 복제본에 읽기 트래픽을 분산시키는 것을 고려하세요. 자세한 내용은 [Amazon DocumentDB에 복제본 세트로 연결](connect-to-replica-set.md) 단원을 참조하십시오.

  읽기에 복제본을 사용하면 기본 인스턴스가 더 많은 쓰기 트래픽을 처리할 수 있게 하여 클러스터 리소스를 더 잘 활용할 수 있습니다. 복제본에서의 읽기는 최종적으로 일관됩니다.
+ 높은 CPU 사용률이 쓰기 워크로드의 결과인 경우 클러스터 인스턴스의 크기를 더 큰 인스턴스 유형으로 변경하면 워크로드를 처리하는 데 사용할 수 있는 CPU 코어 수가 증가합니다. 자세한 내용은 [인스턴스](what-is.md#what-is-db-instances) 및 [인스턴스 클래스 사양](db-instance-classes.md#db-instance-class-specs) 섹션을 참조하세요.
+ 모든 클러스터 인스턴스의 CPU 사용률이 높고 워크로드에서 읽기 전용 복제본을 사용하는 경우 클러스터에 복제본을 더 추가하면 읽기 트래픽에 사용할 수 있는 리소스가 늘어납니다. 자세한 내용은 [클러스터에 Amazon DocumentDB 인스턴스 추가](db-instance-add.md) 단원을 참조하십시오.

## 인스턴스에서 열려 있는 커서를 어떻게 확인하나요?
<a name="user_diagnostics-open_cursors"></a>

Amazon DocumentDB 인스턴스에 연결되면 `db.runCommand("listCursors")` 명령을 사용하여 해당 인스턴스에서 열려 있는 커서를 나열할 수 있습니다. 인스턴스 유형에 따라 특정 Amazon DocumentDB 인스턴스에서 한 번에 최대 4,560개의 활성 커서를 열 수 있습니다. 일반적으로 커서는 인스턴스의 리소스를 사용하고 상한이 있으므로 더 이상 사용하지 않는 커서를 닫는 것이 좋습니다. 구체적인 한도는 [Amazon DocumentDB 할당량 및 제한](limits.md) 섹션을 참조하세요.

```
db.runCommand("listCursors") 
```

## 현재 Amazon DocumentDB 엔진 버전은 어떻게 확인하나요?
<a name="user_diagnostics-engine_version"></a>

현재 Amazon DocumentDB 엔진 버전을 확인하려면 다음 명령을 실행합니다.

```
db.runCommand({getEngineVersion: 1})
```

이 작업의 출력은 다음과 같습니다(JSON 형식).

```
{ "engineVersion" : "2.x.x", "ok" : 1 }
```

**참고**  
Amazon DocumentDB 3.6의 엔진 버전은 1.x.x이고, Amazon DocumentDB 4.0의 엔진 버전은 2.x.x이고, Amazon DocumentDB 5.0의 엔진 버전은 3.x.x이고, Amazon DocumentDB 8.0의 엔진 버전은 4.x.x입니다.

## 인덱스 사용량을 분석하고 사용하지 않는 인덱스를 식별하려면 어떻게 해야 하나요?
<a name="user-diag-index-usage"></a>

지정된 컬렉션에 대한 인덱스를 식별하려면 다음 명령을 실행합니다.

```
db.collection.getIndexes()
```

`collStats` 및 `indexStats` 명령을 사용하여 컬렉션에서 작업을 수행하는 동안 사용되는 인덱스의 양을 분석할 수 있습니다. 인덱스를 사용하여 수행한 총 스캔 수(인덱스 스캔)를 인덱스 없이 수행한 스캔 수(컬렉션 스캔)와 비교하여 보려면 다음 명령을 실행합니다.

```
db.collection.stats()
```

이 명령의 출력에는 다음과 같은 값이 포함됩니다.
+ **`idxScans`**- 인덱스를 사용하여 이 컬렉션에 대해 수행한 스캔 횟수.
+ **`collScans`**- 인덱스를 사용하지 않고 이 컬렉션에 대해 수행한 스캔 횟수. 이러한 스캔에서는 컬렉션에 있는 문서를 한 번에 하나씩 살펴봐야 했을 것입니다.
+ **`lastReset`** - 이 카운터를 마지막으로 재설정한 시간. 이 명령으로 제공된 통계는 클러스터를 시작/중지하거나 인스턴스를 스케일 업/다운할 때 재설정됩니다.

각 인덱스의 사용량에 대한 분석은 다음 명령의 출력에서 확인할 수 있습니다. 인덱스를 유지 관리하는 데 사용되는 불필요한 컴퓨팅, 스토리지 및 I/O를 제거하므로 성능을 개선하고 비용을 절감하기 위해 사용되지 않는 인덱스를 정기적으로 식별하고 제거하는 것이 가장 좋습니다.

```
db.collection.aggregate([{$indexStats:{}}]).pretty()
```

이 명령의 출력은 컬렉션에 생성된 각 인덱스에 대해 다음 값을 제공합니다.
+ **`ops`** - 인덱스를 사용한 작업 수. 작업 로드가 충분히 오랫동안 실행 중이고 작업 로드가 정상 상태에 있다고 확신하는 경우 `ops` 값이 0이면 인덱스가 전혀 사용되지 않음을 나타냅니다.
+ **`numDocsRead`**- 이 인덱스를 사용하여 작업을 수행하는 동안 읽은 문서 수.
+ **`since`** - Amazon DocumentDB에서 인덱스 사용량에 대한 통계를 수집하기 시작한 이후의 시간으로서, 일반적으로 마지막 데이터베이스 재시작 또는 유지 관리 작업 이후의 값.
+ **`size`** - 이 인덱스의 크기(바이트).

다음은 위 명령을 실행한 출력 예제입니다.

```
{
    "name" : "_id_",
    "key" : {
        "_id" : 1
    },
    "host" : "example-host.com:12345",
    "size" : NumberLong(...),
    "accesses" : {
        "ops" : NumberLong(...),
        "docsRead" : NumberLong(...),
        "since" : ISODate("...")
    },
    "cacheStats" : {
        "blksRead" : NumberLong(...),
        "blksHit" : NumberLong(...),
        "hitRatio" : ...
    }
}
{
    "name" : "x_1",
    "key" : {
        "x" : 1
    },
    "host" : "example-host.com:12345",
    "size" : NumberLong(...),
    "accesses" : {
        "ops" : NumberLong(...),
        "docsRead" : NumberLong(...),
        "since" : ISODate("...")
    },
    "cacheStats" : {
        "blksRead" : NumberLong(...),
        "blksHit" : NumberLong(...),
        "hitRatio" : ...
    }
}
```

컬렉션의 전체 인덱스 크기를 확인하려면 다음 명령을 실행합니다.

```
db.collection.stats()
```

사용되지 않는 인덱스를 삭제하려면 다음 명령을 실행합니다.

```
db.collection.dropIndex("indexName")
```

## 누락된 인덱스는 어떻게 식별하나요?
<a name="user_diagnostics-identify_missing_indexes"></a>

[Amazon DocumentDB 프로파일러를 사용하여 느린 쿼리를 로깅할 수 있습니다](https://docs.aws.amazon.com//documentdb/latest/developerguide/profiling.html). 느린 쿼리 로그에 반복적으로 나타나는 쿼리는 해당 쿼리의 성능을 향상하기 위해 추가 인덱스가 필요함을 나타낼 수 있습니다.

하나 이상의 `COLLSCAN` 단계를 수행하는 하나 이상의 단계가 있는 장기 실행 쿼리를 검색하여 유용한 인덱스의 기회를 식별할 수 있습니다. 즉, 쿼리 단계에서 쿼리에 대한 응답을 제공하기 위해 컬렉션의 모든 문서를 읽어야 합니다.

다음 예제에서는 대규모 컬렉션에서 실행된 택시 타기 컬렉션에 대한 쿼리를 보여 줍니다.

```
db.rides.count({"fare.totalAmount":{$gt:10.0}}))
```

이 예제를 실행하려면 `fare.totalAmount` 필드에 인덱스가 없으므로 쿼리는 컬렉션 스캔(즉, 컬렉션의 모든 단일 문서 읽기)을 수행해야 했습니다. 이 쿼리에 대한 Amazon DocumentDB 프로파일러의 출력은 다음과 같습니다.

```
{
    ...
    "cursorExhausted": true,
    "nreturned": 0, 
    "responseLength": 0,
    "protocol": "op_query",
    "millis": 300679,
    "planSummary": "COLLSCAN",
    "execStats": {
        "stage": "COLLSCAN",
        "nReturned": "0",
        "executionTimeMillisEstimate": "300678.042"
    },
    "client": "172.31.5.63:53878",
    "appName": "MongoDB Shell",
    "user": "example"
}
```

이 예에서 쿼리 속도를 높이기 위해 아래 그림과 같이 `fare.totalAmount` 색인을 작성하려고 합니다.

```
db.rides.createIndex( {"fare.totalAmount": 1}, {background: true} )
```

**참고**  
포그라운드에서 생성된 인덱스(인덱스를 만들 때 `{background:true}` 옵션이 제공되지 않은 경우)는 독점적 인 쓰기 잠금을 통해 인덱스 빌드가 완료될 때까지 애플리케이션이 컬렉션에 데이터를 쓰지 못하게 합니다. 프로덕션 클러스터에서 인덱스를 만들 때 이러한 잠재적인 영향을 고려해야 합니다. 인덱스를 만들 때 `{background:true}`로 설정하는 것이 좋습니다.

일반적으로 카디널리티가 높은 필드(예: 많은 수의 고유 값)에 인덱스를 만드는 경향이 있습니다. 카디널리티가 낮은 필드에 인덱스를 만들면 사용되지 않는 큰 인덱스가 발생할 수 있습니다. Amazon DocumentDB 쿼리 최적화 프로그램은 쿼리 계획을 만들 때 컬렉션의 전체 크기와 인덱스의 선택성을 고려합니다. 인덱스가 있는 경우에도 쿼리 프로세서가 `COLLSCAN`을 선택하는 경우가 있습니다. 이는 인덱스를 사용하는 경우 전체 컬렉션을 스캔하는 데 비해 성능 이점이 없을 것으로 쿼리 프로세서가 예측할 때 발생합니다. 특정 인덱스를 활용하기 위해 쿼리 프로세서를 강제하려면 아래 그림과 같이 `hint()` 연산자를 사용할 수 있습니다.

```
db.collection.find().hint("indexName")
```

## 데이터베이스 수집 팽창을 확인하려면 어떻게 해야 하나요?
<a name="performance-collection-bloat"></a>

컬렉션 팽창은 데드 버전 또는 더 이상 사용되지 문서가 누적되거나 데이터베이스 페이지 내에 조각화되면서 컬렉션의 크기가 커질 때 발생합니다. 보고된 백분율은 향후 문서에서 사용할 수 있는 문서 공간의 양을 나타냅니다. 이 팽창은 버퍼 캐시와 스토리지 모두에서 공간을 소비합니다. 팽창을 제거하려면 덤프/복원을 통해 또는 유지 관리 기간 동안 마이그레이션 루프백 및 전환을 사용하여 컬렉션을 다시 로드해야 합니다.

**Example 예제**  
다음 명령을 실행하여 컬렉션의 미사용 스토리지를 확인합니다.  

```
db.runCommand({collStats:'coll'})
```
다음과 비슷한 결과가 반환됩니다.  

```
{
        "ns" : "test.coll",
        "count" : 7500,
        "size" : 23250,
        "avgObjSize" : 31,
        "storageSize" : 106496,
        "unusedStorageSize" : {
                "unusedBytes" : 16384,
                "unusedPercent" : 25.12
        },
        "compression" : {
                "enable" : false
        },
        "capped" : false,
        "nindexes" : 1,
        "totalIndexSize" : 57344,
        "indexSizes" : {
                "_id_" : 57344
        },
        "collScans" : 4,
        "idxScans" : 10000,
        "opCounter" : {
                "numDocsIns" : 1000,
                "numDocsUpd" : 0,
                "numDocsDel" : 250
        },
        "cacheStats" : {
                "collBlksHit" : 3570,
                "collBlksRead" : 8,
                "collHitRatio" : 99.7765,
                "idxBlksHit" : 12293,
                "idxBlksRead" : 6,
                "idxHitRatio" : 99.9513
        },
        "lastReset" : "2024-12-18 00:30:21.552019+00",
        "ok" : 1,
        "operationTime" : Timestamp(1734632375, 1)
}
```

## 유용한 쿼리 요약
<a name="user_diagnostics-useful_queries"></a>

다음 쿼리는 Amazon DocumentDB의 성능 및 리소스 사용률을 모니터링하는 데 유용할 수 있습니다.
+ 다음 명령을 사용하여 작업 카운터, 캐시 통계, 액세스 통계, 크기 통계를 비롯한 특정 컬렉션에 대한 통계를 볼 수 있습니다.

  ```
  db.collection.stats()
  ```
+ 다음 명령을 사용하여 인덱스 크기, 인덱스별 캐시 통계, 인덱스 사용 통계를 포함하여 컬렉션에 생성된 각 인덱스에 대한 통계를 볼 수 있습니다.

  ```
  db.collection.aggregate([{$indexStats:{}}]).pretty()
  ```
+ 다음 쿼리를 사용하여 모든 활동을 나열하세요.

  ```
  db.adminCommand({currentOp: 1, $all: 1});
  ```
+ 다음 코드는 오래 실행되거나 차단된 모든 쿼리를 나열합니다.

  ```
  db.adminCommand({aggregate: 1,
                   pipeline: [{$currentOp: {}},
                              {$match: {$or: [{secs_running: {$gt: 10}},
                                              {WaitState: {$exists: true}}]}},
                              {$project: {_id:0,
                                          opid: 1,
                                          secs_running: 1,
                                          WaitState: 1,
                                          blockedOn: 1,
                                          command: 1}}],
                   cursor: {}
                  });
  ```
+ 다음 코드는 쿼리를 종료합니다.

  ```
  db.adminCommand({killOp: 1, op: <opid of running or blocked query>});
  ```
+ 다음 코드를 사용하여 시스템 상태를 종합적으로 볼 수 있습니다.

  ```
  db.adminCommand({aggregate: 1,
                   pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
                              {$group: {_id: {desc: "$desc", ns: "$ns", WaitState: "$WaitState"}, count: {$sum: 1}}}],
                   cursor: {}
                  });
  ```

# Amazon DocumentDB의 폐영역 회수
<a name="garbage-collection"></a>

Amazon DocumentDB는 모든 업데이트 작업에 대한 문서 및 인덱스 항목의 새 버전을 생성하는 다중 버전 동시성 제어(MVCC) 데이터베이스 아키텍처를 구현합니다. 이 아키텍처는 트랜잭션 격리를 활성화하여 한 트랜잭션의 변경 사항이 다른 트랜잭션에 나타나지 않도록 합니다.

**Topics**
+ [Amazon DocumentDB의 가비지 수집 이해](#understanding-garbage-collection)
+ [폐영역 회수 프로세스](#garbage-collection-process)
+ [스토리지 아키텍처 및 확장 스토리지](#storage-architecture)
+ [폐영역 회수 모니터링](#monitoring-garbage-collection)
+ [collStats 출력 예제](#example-collstats-output)
+ [자주 묻는 질문(FAQ)](#garbage-collection-faq)

## Amazon DocumentDB의 가비지 수집 이해
<a name="understanding-garbage-collection"></a>

폐영역 회수(GC)는 Amazon DocumentDB에서 최적의 시스템 성능과 가용성을 유지하는 자동화된 백그라운드 프로세스입니다. 여러 최신 데이터베이스와 마찬가지로 Amazon DocumentDB의 MVCC 아키텍처는 각 업데이트마다 새 문서 및 인덱스 버전을 생성합니다. 각 쓰기 작업은 유한 카운터에서 고유한 MVCC ID를 사용합니다. 이러한 IDs 문서 버전이 속한 트랜잭션과 커밋 또는 롤백 여부를 식별합니다. 시간이 지남에 따라 이러한 이전 버전과 해당 MVCC IDs 누적되므로 성능 저하를 방지하기 위해 정리가 필요합니다.

### 폐영역 회수의 함수
<a name="w2aac49c15b7b5"></a>

폐영역 회수기는 세 가지 필수 함수를 제공합니다.
+ **스토리지 공간 회수** - 활성 쿼리에 더 이상 필요하지 않은 더 이상 사용되지 않는 문서 및 인덱스 버전을 제거하여 향후 쓰기 작업을 위한 공간을 확보합니다.
+ **MVCC ID 오버플로 방지** - MVCC ID의 유한 카운터를 관리하여 MVCC ID 오버플로를 방지합니다. 이 관리가 없으면 카운터가 결국 한도에 도달하여 데이터베이스를 ID가 재활용될 때까지 임시 읽기 전용 모드로 강제 적용합니다,
+ **쿼리 성능 유지** - 쿼리 처리가 누적되고 느려지는 데드 문서 버전을 제거하여 최적의 쿼리 성능을 유지합니다.

## 폐영역 회수 프로세스
<a name="garbage-collection-process"></a>

GC 프로세스는 컬렉션별로 작동하며 여러 컬렉션에서 여러 프로세스를 동시에 실행할 수 있습니다. 이 프로세스는 4개의 순차적 단계로 구성됩니다.

1. **식별** - 시스템은 활성 트랜잭션 또는 쿼리에서 더 이상 참조하지 않는 문서 및 인덱스 버전을 식별합니다.

1. **메모리 로드** - 문서와 인덱스 항목이 아직 없는 경우 이전 문서와 인덱스 항목이 메모리에 로드됩니다.

1. **삭제** - 더 이상 사용되지 않는 버전이 영구적으로 삭제되어 스토리지 공간을 회수합니다.

1. **MVCC ID 재활용** - 시스템은 새 작업을 위해 삭제된 버전에서 MVCC ID를 재활용합니다.

폐영역 회수가 이전 문서 버전 처리를 완료하면 시스템에서 가장 오래된 MVCC ID가 제거됩니다. 이 정리는 MVCC ID를 재활용하여 클러스터 전체에서 새 쓰기 작업에 사용할 수 있도록 하여 MVCC ID 오버플로를 방지하는 데 매우 중요합니다. 이 재활용 프로세스가 없으면 시스템은 결국 유한 MVCC ID 카운터를 소진하고 읽기 전용 상태가 됩니다.

### 폐영역 회수 일정
<a name="w2aac49c15b9b9"></a>

폐영역 회수는 주기적으로 백그라운드에서 자동으로 실행됩니다. 타이밍 및 빈도는 시스템 로드, 사용 가능한 리소스, 쓰기 볼륨 및 MVCC ID 소비 수준에 따라 동적으로 조정됩니다. 쓰기 작업이 많은 동안에는 GC 프로세스가 더 자주 실행되어 문서 버전의 수가 증가합니다.

## 스토리지 아키텍처 및 확장 스토리지
<a name="storage-architecture"></a>

Amazon DocumentDB는 문서 스토리지를 두 개의 개별 세그먼트로 분리하는 정교한 스토리지 아키텍처를 사용합니다.

### 기본 스토리지 세그먼트
<a name="w2aac49c15c11b5"></a>

기본 스토리지 세그먼트에는 기본 문서 데이터와 메타데이터가 포함되어 있습니다. 이 세그먼트는 다음을 저장합니다.
+ 표준 페이지 크기(8KB)에 맞는 콘텐츠를 문서화합니다.
+ 메타데이터 및 구조 정보를 문서화합니다.
+ 기본 인덱스 및 해당 항목.
+ 컬렉션 수준 통계 및 구성.

### 확장 스토리지 세그먼트
<a name="w2aac49c15c11b7"></a>

확장 스토리지 세그먼트는 표준 스토리지 페이지 크기를 초과하는 문서를 처리하도록 설계된 특수 대형 문서 객체 스토어를 활용합니다. 이 세그먼트는 다음을 제공합니다.
+ **효율적인 대용량 문서 처리** - 기본 스토리지 임계값보다 큰 문서는 확장 스토리지 세그먼트로 자동으로 이동됩니다.
+ **최적화된 스토리지 레이아웃** - 세그먼트는 큰 객체에 최적화된 다른 스토리지 형식을 사용하여 조각화를 줄이고 액세스 패턴을 개선합니다.
+ **독립 가비지 수집** - 확장 스토리지 세그먼트에는 기본 스토리지 정리와 독립적으로 실행할 수 있는 자체 가비지 수집 프로세스가 있습니다.
+ **투명한 액세스** - 애플리케이션이 데이터가 포함된 스토리지 세그먼트를 알 필요 없이 대용량 문서에 원활하게 액세스합니다.

확장 스토리지 세그먼트는 다음과 같은 경우에 특히 유용합니다.
+ 대형 임베디드 배열이 포함된 문서가 포함된 컬렉션입니다.
+ 광범위한 중첩 구조가 있는 문서.
+ 바이너리 데이터 또는 큰 텍스트 필드를 저장하는 컬렉션입니다.
+ 일부 문서가 평균 크기를 크게 초과하는 혼합 문서 크기가 있는 애플리케이션.

## 폐영역 회수 모니터링
<a name="monitoring-garbage-collection"></a>

### 클러스터 수준 지표
<a name="w2aac49c15c13b3"></a>

**`AvailableMVCCIds`**
+ **위치** - Amazon CloudWatch
+ **설명** - 최대 18억 개의 제한에서 사용 가능한 나머지 쓰기 작업 수를 보여주는 카운터입니다. 이 카운터가 0에 도달하면 ID가 회수되고 재활용될 때까지 클러스터가 읽기 전용 모드로 전환됩니다. 카운터는 각 쓰기 작업에 따라 감소하고 폐영역 회수가 이전 MVCC ID를 재활용함에 따라 증가합니다.
+ **권장 사항** - 값이 13억 미만으로 떨어질 때 경보를 설정합니다. 이 조기 경고를 사용하면 나중에 설명하는 권장 단계를 수행할 수 있습니다.

**`LongestActiveGCRuntime`**
+ **위치** - Amazon CloudWatch
+ **설명** - 가장 긴 활성 폐영역 회수 프로세스의 초 단위 기간입니다. 1분마다 업데이트하고 1분 내에 완료되는 프로세스를 제외한 활성 작업만 추적합니다.
+ **권장 사항** - `gcRuntimeStats` 과거 데이터와 비교하여 대량 삭제 중 연장된 런타임과 같은 비정상적인 가비지 수집 동작을 식별합니다.

### 컬렉션 수준 지표
<a name="w2aac49c15c13b5"></a>

**`MVCCIDStats: MVCCIdScale`**
+ **위치** - 데이터베이스 collStats 명령
+ **설명** - 0\$11의 척도로 MVCC ID 수명을 측정합니다. 여기서 1은 클러스터가 읽기 전용 상태가 되기 전의 최대 수명을 나타냅니다. 이 지표를 `AvailableMVCCIds`와 함께 사용하여 클러스터를 노후화하는 가장 오래된 MVCC ID가 포함된 컬렉션을 식별합니다.
+ **권장 사항** - 각 컬렉션에 대해 0.3 미만의 값을 유지합니다.

**`gcRuntimeStats`**
+ **위치** - 데이터베이스 collStats 명령
+ **설명** - 총 실행 횟수, 평균 기간, 최대 기간을 포함한 폐영역 회수 지표의 2개월 기록을 제공합니다. 의미 있는 통계를 보장하기 위해 5분 이상 지속되는 폐영역 회수 작업만 포함합니다.

**중요**  
`gcRuntimeStats`및에 대한 컬렉션 수준 지표의 `documentFragmentStats`, `storageSegmentBase` 및 분류`storageSegmentExtended`는 Amazon DocumentDB 8.0에서만 사용할 수 있습니다.

**`storageSizeStats`**
+ **위치** - 데이터베이스 collStats 명령
+ **설명** - 다양한 스토리지 세그먼트의 스토리지 사용률을 자세히 분석합니다.
  + `storageSegmentBase` - 표준 문서의 기본 스토리지 세그먼트에서 사용하는 스토리지
  + `storageSegmentExtended` - 대용량 문서의 확장 스토리지 세그먼트에서 사용하는 스토리지
+ **사용량** - 상당히 큰 문서 스토리지가 있는 컬렉션을 식별하고 스토리지 배포 패턴을 이해하는 데 도움이 됩니다.

**`unusedStorageSize`**(수집 수준)
+ **위치** - 데이터베이스 collStats 명령
+ **설명** - 샘플링된 통계를 기반으로 컬렉션의 미사용 스토리지 공간을 추정합니다. 여기에는 삭제된 문서와 빈 세그먼트의 공간이 포함됩니다. 지표는 결합된 합계와 세그먼트별 분석을 모두 제공합니다.
  + 모든 스토리지 세그먼트`unusedPercent`에서 `unusedBytes` 및 통합
  + `storageSegmentBase` - 기본 스토리지 세그먼트에서 특별히 사용되지 않는 공간
  + `storageSegmentExtended` - 확장 스토리지 세그먼트에서 특별히 사용되지 않는 공간

**`documentFragmentStats`**
+ **위치** - 데이터베이스 collStats 명령
+ **설명** - 컬렉션 내의 문서 조각 및 데드 데이터에 대한 자세한 정보를 제공합니다. 문서 조각은 데이터베이스 엔진에서 사용하는 내부 스토리지 단위를 나타내며, 데드 조각은 더 이상 액세스할 수 없지만 아직 회수되지 않은 데이터를 나타냅니다. 이 지표에는 다음이 포함됩니다.
  + `totalDocFragmentsCount` - 컬렉션의 총 문서 조각 수
  + `deadDocFragmentsCount` - 데드(액세스할 수 없음) 데이터가 포함된 조각 수
  + `deadDocFragmentsPercent` - 데드 데이터가 포함된 조각의 백분율
  + `deadDocFragmentBytes` - 배달 못한 문서 조각에서 소비되는 예상 바이트
  + `storageSegmentBase` 및에 대한 세그먼트별 분석 `storageSegmentExtended`
+ **사용량** -이 지표를 모니터링하여 가비지 수집의 효과를 이해하고 유지 관리 작업의 이점을 얻을 수 있는 컬렉션을 식별합니다. 데드 조각의 비율이 높으면 가비지 수집이 뒤처지거나 수집이 최적화의 이점을 누릴 수 있음을 나타냅니다.

### 인덱스 수준 지표
<a name="w2aac49c15c13b7"></a>

**`unusedStorageSize`**(인덱스 수준)
+ **위치** - 데이터베이스 indexStats 명령
+ **설명** - 샘플링된 통계를 기반으로 인덱스의 미사용 스토리지 공간을 추정합니다. 여기에는 더 이상 사용되지 않는 인덱스 항목과 빈 세그먼트의 공간이 포함됩니다.
+ **권장 사항** - `reIndex` 명령을 사용하여 가동 중지 없이 인덱스를 다시 빌드하고 미사용 공간을 회수합니다. 자세한 내용은 인덱스 관리를 참조하세요.

## collStats 출력 예제
<a name="example-collstats-output"></a>

다음 예제에서는 가비지 수집 및 스토리지 지표가 포함된 일반적인 `collStats` 출력을 보여줍니다.

```
{
    "ns" : "Mvcc_consumption_test_db.mvcc_test_collection",
    "MVCCIdStats" : {
        "MVCCIdScale" : 0.03
    },
    "gcRuntimeStats" : {
        "numRuns" : 1,
        "historicalAvgRuntime" : 3295,
        "historicalMaxRuntime" : 3295,
        "lastRuntime" : 3295,
        "lastRuntimeStart" : ISODate("2025-06-24T08:47:14Z")
    },
    "documentFragmentStats" : {
        "totalDocFragmentsCount" : 45000000,
        "deadDocFragmentsCount" : 2250000,
        "deadDocFragmentsPercent" : 5.0,
        "deadDocFragmentBytes" : 98304000,
        "storageSegmentBase" : {
            "totalDocFragmentsCount" : 30000000,
            "deadDocFragmentsCount" : 1500000,
            "deadDocFragmentsPercent" : 5.0,
            "deadDocFragmentBytes" : 65536000
        },
        "storageSegmentExtended" : {
            "totalDocFragmentsCount" : 15000000,
            "deadDocFragmentsCount" : 750000,
            "deadDocFragmentsPercent" : 5.0,
            "deadDocFragmentBytes" : 32768000
        }
    },
    "collScans" : 14,
    "count" : 30000000,
    "size" : 1320000000,
    "avgObjSize" : 44,
    "storageSize" : 6461497344,
    "storageSizeStats" : {
        "storageSegmentBase" : 4307664896,
        "storageSegmentExtended" : 2153832448
    },
    "capped" : false,
    "nindexes" : 2,
    "totalIndexSize" : 9649553408,
    "indexSizes" : {
        "_id_" : 1910661120,
        "c_1" : 7738892288
    },
    "unusedStorageSize" : {
        "unusedBytes" : 4201881600,
        "unusedPercent" : 65.05,
        "storageSegmentBase" : {
            "unusedBytes" : 2801254400,
            "unusedPercent" : 65.05
        },
        "storageSegmentExtended" : {
            "unusedBytes" : 1400627200,
            "unusedPercent" : 65.05
        }
    },
    "cacheStats" : {
        "collBlksHit" : 171659016,
        "collBlksRead" : 754061,
        "collHitRatio" : 99.5627,
        "idxBlksHit" : 692563636,
        "idxBlksRead" : 1177921,
        "idxHitRatio" : 99.8303
    },
    "idxScans" : 41823984,
    "opCounter" : {
        "numDocsIns" : 0,
        "numDocsUpd" : 20911992,
        "numDocsDel" : 0
    },
    "lastReset" : "2025-06-24 05:57:08.219711+00",
    "ok" : 1,
    "operationTime" : Timestamp(1750968826, 1)
}
```

## 자주 묻는 질문(FAQ)
<a name="garbage-collection-faq"></a>

### 폐영역 회수의 효율적 작동 여부를 확인하려면 어떻게 해야 하나요?
<a name="w2aac49c15c17b3"></a>

비효율적인 폐영역 회수를 나타내는 다음 경고 신호를 모니터링합니다.
+ **과도한 수집 부풀림** - 특히 큰 인덱스의 경우 쓰기가 많거나 대량 삭제 시 `unusedStorageSize` 지표를 지속적으로 증가시킵니다.
+ **높은 데드 조각 비율** - 일관되게 높은 `deadDocFragmentsPercent` 값(10\$115% 이상)을 `documentFragmentStats` 표시합니다.
+ **성능 저하된 쿼리 지연 시간** - 누적된 배달 못한 문서로 인해 쿼리 지연 시간이 늘어났습니다.
+ **연장된 GC 기간** -의 과거 평균보다 더 오래 걸리는 가비지 수집 작업입니다`gcRuntimeStats`.
+ **GC 처리 기능 향상** - 가비지 수집기가 시스템 수요를 따라잡을 수 없음을 `LongestActiveGCRuntime` 나타냅니다.

### 폐영역 회수가 데이터베이스 성능에 영향을 미치나요?
<a name="w2aac49c15c17b5"></a>

정상적인 조건에서는 폐영역 회수가 성능에 미치는 영향을 최소화합니다. 그러나 폐영역 회수가 뒤처지면 다음과 같은 상황이 발생할 수 있습니다.
+ 누적된 배달 못한 문서로 인해 스토리지 비용이 증가합니다.
+ 더 이상 사용되지 않는 인덱스 항목으로 인해 쿼리 성능이 느려집니다.
+ MVCC IDs 고갈된 경우 임시 읽기 전용 모드입니다.
+ 특히 더 작은 인스턴스에서 집약적인 수집 실행 중 리소스 사용량이 증가합니다.
+ 대용량 문서에 대한 확장 스토리지 세그먼트 작업의 효율성이 감소했습니다.

### 폐영역 회수를 수동으로 트리거할 수 있나요?
<a name="w2aac49c15c17b7"></a>

아니요. Amazon DocumentDB의 폐영역 회수는 수동으로 트리거할 수 없습니다. 시스템은 내부 유지 관리 작업의 일부로 폐영역 회수를 자동으로 관리합니다.

### 운영 모범 사례로 설정해야 하는 경보는 무엇인가요?
<a name="w2aac49c15c17b9"></a>

Amazon DocumentDB 시스템의 성능을 최적화하려면 클러스터 및 컬렉션 수준 모두에서 모니터링을 설정하는 것이 좋습니다.

클러스터 수준 모니터링의 경우 먼저 임계값이 `AvailableMVCCIds` 13억인 지표에 대한 Amazon CloudWatch 경보를 생성합니다. 이렇게 하면 지표가 0에 도달하기 전에 조치를 취할 수 있는 충분한 시간을 확보할 수 있습니다. 그러면 클러스터가 읽기 전용 모드로 전환됩니다. 이 지표는 특정 사용 패턴에 따라 변동할 수 있습니다. 일부 고객은 가비지 수집이 작업을 완료하면 지표가 13억 미만으로 감소한 다음 15억 이상으로 복구됩니다.

Amazon CloudWatch를 통해 `LongestActiveGCRuntime` 지표를 모니터링하는 것도 중요합니다. 이 지표는 `gcRuntimeStats`와 함께 시스템 전체에서 폐영역 회수가 얼마나 효율적으로 수행되고 있는지 이해하는 데 도움이 됩니다.

컬렉션 수준 모니터링의 경우 다음 주요 지표에 집중하세요.
+ `MVCCIdScale` - MVCC IDs 오래되어 주의가 필요할 수 있음을 나타내는 값이 증가하는지 확인합니다.
+ `gcRuntimeStats` - 비정상적으로 오래 걸리거나 며칠에 걸쳐 연장되는 가비지 수집 프로세스를 식별합니다.
+ `documentFragmentStats` - `deadDocFragmentsPercent` 값 모니터링 - 지속적으로 높은 비율(10\$115% 이상)은 가비지 수집이 뒤처지고 있음을 나타낼 수 있습니다.
+ `storageSizeStats` 및 `unusedStorageSize`- 스토리지 사용률 패턴을 추적하고 두 스토리지 세그먼트 중 하나에서 상당한 미사용 공간이 있는 컬렉션을 식별합니다.

쓰기 작업이 빈번한 컬렉션은 폐영역 회수기에 더 많은 작업을 생성하므로 각별한 주의가 필요합니다. 폐영역 회수가 워크로드를 따라잡을 수 있도록 쓰기 활동이 많은 컬렉션에 대해 이러한 지표를 더 자주 확인하는 것이 좋습니다.

이러한 모니터링 권장 사항은 시작점 역할을 합니다. 시스템 동작에 더 익숙해지면 특정 사용 패턴 및 요구 사항에 더 잘 맞게 이러한 임계값을 조정하는 것이 좋습니다.

### `AvailableMVCCIds`가 13억 이하로 떨어지면 어떻게 해야 하나요?
<a name="w2aac49c15c17c11"></a>

`AvailableMVCCIds` 지표가 13억 미만으로 떨어지면 클러스터가 읽기 전용 모드로 전환되지 않도록 즉각적인 조치를 취하는 것이 좋습니다. 먼저 인스턴스 크기를 확장하여 폐영역 회수기에 더 많은 컴퓨팅 리소스를 제공하는 것이 좋습니다. 이는 애플리케이션이 가비지 수집기에 따라 잡는 데 필요한 추가 전력을 제공하면서 정상적인 작업을 계속할 수 있도록 하기 위한 기본 권장 사항입니다.

확장만으로도 상황이 개선되지 않는 경우 쓰기 작업의 감소를 고려하는 것이 좋습니다. `MVCCIdScale` 지표를 사용하여 주의가 필요한 이전 MVCC ID가 포함된 특정 컬렉션을 식별합니다. 또한를 모니터링`documentFragmentStats`하여 가비지 수집 비효율성에 기여할 수 있는 데드 조각 비율이 높은 컬렉션을 식별합니다.

이러한 컬렉션을 식별한 후에는 폐영역 회수가 따라잡을 수 있도록 컬렉션에 대한 쓰기 작업을 일시적으로 줄여야 할 수 있습니다. 복구 기간 동안 `AvailableMVCCIds` 지표를 면밀히 모니터링하여 작업에 원하는 효과가 있는지 확인하는 것이 좋습니다. `AvailableMVCCIds` 값이 15억 이상으로 반환되면 클러스터가 정상으로 간주됩니다.

이러한 단계는 시스템이 중요한 상태에 도달하기 전에 복구하는 데 도움이 되는 예방 조치입니다. 지표가 13억 미만으로 감소한 것을 확인한 후 더 빨리 조치를 취할수록 쓰기 작업에 미치는 영향을 피할 가능성이 높아집니다.