성능 및 리소스 사용률 - Amazon DocumentDB

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

성능 및 리소스 사용률

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

Mongo API를 통해 내 컬렉션에 대해 수행된 삽입, 업데이트 및 삭제 작업 수를 확인하려면 어떻게 해야 하나요?

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

db.collection.stats()

명령에 대한 출력은 opCounters 필드에서 다음과 같습니다.

  • numDocsIns- 이 컬렉션에 삽입된 문서 수 여기에는 insertinsertMany 명령을 사용하여 삽입한 문서와 업서트로 삽입한 문서가 포함됩니다.

  • numDocsUpd- 이 컬렉션에서 업데이트된 문서 수입니다. 여기에는 updatefindAndModify 명령을 사용하여 업데이트한 문서가 포함됩니다.

  • 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 모니터링에서 확인할 수 있습니다.

캐시 성능을 분석하려면 어떻게 해야 하나요?

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

db.collection.stats()

이 명령 출력의 cacheStats 필드 값은 컬렉션에 대한 캐시 통계는 물론 컬렉션에 생성된 인덱스의 전체 캐시 통계도 제공합니다. 이러한 통계는 다음과 같습니다.

  • collBlksHit - 이 컬렉션에 대한 작업 중에 캐시에서 읽은 블록 수입니다.

  • collBlksRead - 이 컬렉션에 대한 작업 중에 디스크에서 읽은 블록 수(캐시 누락)입니다.

  • collHitRatio - 이 컬렉션의 캐시 적중률(100 * [collBlksHit / (collBlksHit + collBlksRead)]).

  • idxBlksHit - 이 컬렉션에서 생성된 인덱스에 대해 캐시에서 읽은 블록 수입니다.

  • idxBlksRead - 이 컬렉션에서 생성된 인덱스에 대해 디스크에서 읽은 블록 수(캐시 누락)입니다.

  • idxHitRatio - 이 컬렉션에서 생성된 인덱스의 캐시 적중률(100 * [idxBlksHit / (idxBlksHit + idxBlksRead)]).

  • lastReset - 이 통계가 마지막으로 재설정된 시간. db.collection.stats()에 의해 제공된 통계는 클러스터를 시작/중지하거나 인스턴스를 스케일 업/다운할 때 재설정됩니다.

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

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

각 인덱스에 대해 cacheStats 필드 아래에서 다음과 같은 캐시 통계를 찾을 수 있습니다.

  • blksHit - 이 인덱스에 대해 캐시에서 읽은 블록 수입니다.

  • blksRead - 이 인덱스에 대해 디스크에서 읽은 블록 수입니다.

  • blksHitRatio - 100 * [blksHit / (blksHit + blksRead)]에서 캐시 적중률을 소수점 네 자리로 반올림하여 계산합니다.

장시간 실행 중이거나 차단된 쿼리를 찾아서 종료하려면 어떻게 해야 하나요?

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

최적이지 않은 쿼리 계획으로 인해 느려지고 오래 실행되는 쿼리나, 속도가 느려지거나 리소스 경합으로 인해 차단된 쿼리를 찾으려면 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 }
  2. killOp 작업을 사용하여 쿼리를 종료합니다.

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

쿼리 계획을 보고 쿼리를 최적화하려면 어떻게 해야 하나요?

쿼리의 실행 속도가 느린 경우 이 상황은 쿼리 실행 시 모음 전체 검색하여 관련 문서를 선택해야 하기 때문에 발생했을 수 있습니다. 경우에 따라 적절한 인덱스를 생성하면 쿼리 실행 속도가 빨라질 수도 있습니다. 이 시나리오를 찾아내어 인덱스를 생성할 기준 필드를 결정하려면 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 쿼리 프로세서는 인덱스를 사용하지 않도록 결정할 수 있습니다.

엘라스틱 클러스터에서 쿼리 계획을 확인하려면 어떻게 해야 하나요?

엘라스틱 클러스터의 쿼리 계획을 검사하려면 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_MERGE’ 단계에서 병합되기 전에 모든 파티션에서 ‘COLLSCAN’(컬렉션 스캔)이 실행됩니다. 그런 다음 샤드 전체의 결과가 'SHARD_MERGE' 단계에서 병합된 후 클라이언트로 다시 전송됩니다.

인스턴스에서 실행 중인 작업을 모두 나열하려면 어떻게 해야 하나요?

사용자 또는 기본 사용자는 진단 및 문제 해결을 위해 인스턴스에서 실행 중인 현재 작업을 모두 나열하려는 경우가 많습니다. (사용자 관리에 대한 자세한 내용은 Amazon DocumentDB 사용자 관리 섹션을 참조하세요.)

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_COLLECTION - 내부 가비지 수집기 스레드입니다.

  • 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' 명령을 계속 실행합니다.

쿼리 진행 상황을 어떻게 알 수 있나요?

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

디버깅의 첫 번째 단계는 장시간 실행 중이거나 차단된 모든 쿼리를 나열하는 것입니다. 다음 쿼리는 실행 시간이 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"이면 리소스 경합의 원인은 내부 시스템 작업입니다. 이 상황이 장시간 지속되는 경우 유일한 완화 방법은 쿼리를 종료했다가 나중에 다시 실행하는 방법뿐입니다.

시스템이 갑자기 느리게 실행되는 이유를 어떻게 알 수 있나요?

다음은 시스템 속도가 느려지는 몇 가지 일반적인 이유입니다.

  • 동시 쿼리 간 과도한 리소스 경합

  • 시간이 지남에 따라 증가하는 활성 동시 쿼리 수

  • "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개가 있습니다.

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

하나 이상의 클러스터 인스턴스에서 높은 CPU 사용률의 원인을 어떻게 확인하나요?

다음 섹션은 인스턴스 CPU 사용률이 높은 원인을 식별하는 데 도움이 될 수 있습니다. 워크로드에 따라 결과가 달라질 수 있습니다.

높은 인스턴스 CPU 사용률의 이유에 따라 다음 중 하나 이상을 수행하면 도움이 될 수 있습니다.

  • 기본 인스턴스의 CPU 사용률이 높지만 복제본 인스턴스는 그렇지 않은 경우 클라이언트 읽기 기본 설정(예: secondaryPreferred)을 통해 복제본에 읽기 트래픽을 분산시키는 것을 고려하세요. 자세한 설명은 Amazon DocumentDB에 복제 세트로 연결 섹션을 참조하세요.

    읽기에 복제본을 사용하면 기본 인스턴스가 더 많은 쓰기 트래픽을 처리할 수 있게 하여 클러스터 리소스를 더 잘 활용할 수 있습니다. 복제본에서의 읽기는 최종적으로 일관됩니다.

  • 높은 CPU 사용률이 쓰기 워크로드의 결과인 경우 클러스터 인스턴스의 크기를 더 큰 인스턴스 유형으로 변경하면 워크로드를 처리하는 데 사용할 수 있는 CPU 코어 수가 증가합니다. 자세한 내용은 인스턴스인스턴스 클래스 사양 섹션을 참조하세요.

  • 모든 클러스터 인스턴스의 CPU 사용률이 높고 워크로드에서 읽기 전용 복제본을 사용하는 경우 클러스터에 복제본을 더 추가하면 읽기 트래픽에 사용할 수 있는 리소스가 늘어납니다. 자세한 설명은 클러스터에 Amazon DocumentDB 인스턴스 추가 섹션을 참조하세요.

인스턴스에서 열려 있는 커서를 어떻게 확인하나요?

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

db.runCommand("listCursors")

현재 Amazon DocumentDB 엔진 버전은 어떻게 확인하나요?

현재 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입니다.

인덱스 사용량을 분석하고 사용하지 않는 인덱스를 식별하려면 어떻게 해야 하나요?

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

db.collection.getIndexes()

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

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")

누락된 인덱스는 어떻게 식별하나요?

Amazon DocumentDB 프로파일러를 사용하여 느린 쿼리를 로깅할 수 있습니다. 느린 쿼리 로그에 반복적으로 나타나는 쿼리는 해당 쿼리의 성능을 향상하기 위해 추가 인덱스가 필요함을 나타낼 수 있습니다.

하나 이상의 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")

유용한 쿼리 요약

다음 쿼리는 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: {} });