DynamoDB의 데이터 쿼리 및 스캔 모범 사례 - Amazon DynamoDB

DynamoDB의 데이터 쿼리 및 스캔 모범 사례

이 단원에서는 Amazon DynamoDB의 QueryScan 작업에 대한 몇 가지 모범 사례를 살펴봅니다.

스캔에 대한 성능 고려 사항

일반적으로 Scan 작업은 DynamoDB의 다른 작업보다 비효율적입니다. Scan 작업은 항상 전체 테이블이나 보조 인덱스를 스캔합니다. 그런 후 값을 필터링하여 원하는 결과를 얻기 때문에 결과 세트에서 데이터를 제거해야 하는 단계가 추가됩니다.

가능한 경우, 대용량 테이블 또는 인덱스에서 필터를 사용해 다수의 결과를 제거해야 하는 경우에는 Scan 작업을 최대한 피하는 것이 좋습니다. 여기에 테이블이나 인덱스 용량이 커질수록 Scan 작업 속도가 느려집니다. Scan 작업은 요청한 값을 찾기 위해 전체 항목을 검사하기 때문에 대용량 테이블이나 인덱스일 경우에는 단 한 번의 작업으로 프로비저닝된 처리량을 모두 사용할 수 있습니다. 이런 경우 응답 시간을 빠르게 하려면 애플리케이션이 Scan이 아닌 Query를 사용하도록 테이블과 인덱스를 설계해야 합니다. (테이블의 경우에는 GetItemBatchGetItem API 사용도 고려할 수 있습니다.)

그 밖에도 Scan 작업이 요청량에 미치는 영향을 최소화할 수 있도록 애플리케이션을 설계할 수 있습니다. 여기에는 Scan 작업 대신 글로벌 보조 인덱스를 사용하는 것이 더 효율적일 수 있는 경우의 모델링이 포함될 수 있습니다. 이 프로세스에 대한 자세한 내용은 다음 비디오에 나와 있습니다.

갑작스러운 읽기 활동 급증 방지

테이블을 생성할 때는 읽기 및 쓰기 용량 단위의 요건을 설정합니다. 읽기의 경우, 4KB 데이터의 초당 강력하게 일관된 읽기 요청 수로 용량 단위를 표현합니다. 최종적으로 일관된 읽기일 때는 읽기 용량 단위가 초당 4KB 읽기 요청 2개입니다. Scan 작업은 기본적으로 최종적으로 일관된 일기를 실행하며 최대 1MB(한 페이지)까지 데이터를 반환할 수 있습니다. 따라서 Scan 요청 한 번으로 (1MB 페이지 크기/4KB 항목 크기)/2(최종적으로 일관된 읽기 수)의 결과인 128개의 읽기 작업을 소비할 수 있습니다. 대신 강력하게 일관된 읽기를 요청하면 Scan 작업은 두 배 더 많은 프로비저닝된 처리량인 256개의 읽기 작업을 소비합니다.

이 현장은 테이블에 구성된 읽기 용량과 비교하여 갑작스러운 사용량 급증을 나타냅니다. 스캔 작업에서 이러한 용량 단위의 사용은 용량 단위의 부족으로 이어져 동일한 테이블에서 잠재적으로 더욱 중요한 요청을 실행하지 못하는 원인이 될 수 있습니다. 그 결과 더욱 중요한 요청을 실행하더라도 ProvisionedThroughputExceeded 예외가 발생할 가능성이 높습니다.

Scan이 사용하는 용량 단위의 갑작스러운 증가 외에도 문제는 또 있습니다. 스캔 요청 시 파티션에서 서로 인접한 항목을 읽어오다 보니 동일한 파티션의 용량 단위를 모두 소비할 가능성이 높습니다. 다시 말해서 여러 요청이 동일 파티션으로 몰리면서 용량 단위를 모두 소비하고 결국 해당 파티션에 대한 다른 요청은 병목 현상을 겪고 맙니다. 이 경우 데이터 읽기 요청을 여러 파티션으로 분산하였다면 작업으로 인한 특정 파티션의 병목 현상은 발생하지 않을 것입니다.

다음은 QueryScan 작업에 따른 용량 단위 사용량의 급증이 미치는 영향과, 동일한 테이블에 대한 다른 요청에 미치는 영향을 나타낸 다이어그램입니다.

프로비저닝된 처리량 간격, 요청, 테이블의 좋은/나쁜 결과에 대한 4가지 시나리오

여기에서 설명했듯, 사용량 급증은 몇몇 방식으로 테이블의 프로비저닝된 처리량에 영향을 초래할 수 있습니다.

  1. 좋음: 요청과 크기를 고르게 배포

  2. 중간: 버스트의 잦은 요청

  3. 나쁨: 소수의 임의 대량 요청

  4. 나쁨: 대형 스캔 작업

대용량의 Scan 작업 대신에 다음과 같은 기술을 사용하여 스캔이 테이블의 할당 처리량에 미치는 영향을 최소화할 수 있습니다.

  • 페이지 크기 축소

    스캔 작업은 전체 페이지(기본 1MB)를 읽어오기 때문에 페이지 크기를 축소하면 스캔 작업의 영향을 줄일 수 있습니다. Scan 작업의 Limit 파라미터는 페이지 크기를 요청에 맞게 설정하는 데 사용됩니다. 각 Query 또는 Scan 요청마다 페이지 크기를 축소하면 읽기 작업 수가 줄어들면서 각 요청 간 "멈춤"이 발생합니다. 예를 들어, 각 항목이 4KB이고, 페이지 크기를 항목 40개로 설정했다고 가정합니다. Query 요청은 20개의 최종적 일관된 읽기 작업이나 40개의 강력히 일관된 읽기 작업만 사용합니다. 페이지 크기를 축소한 Query 또는 Scan 작업은 그 수를 늘리더라도 병목 현상 없이 다른 중요한 요청까지 처리할 수 있습니다.

  • 스캔 작업 격리

    DynamoDB는 확장이 용이하도록 설계되었습니다. 그 결과 애플리케이션이 개별 목적으로 테이블을 생성할 뿐만 아니라 내용을 여러 테이블로 복제까지 할 수 있습니다. 예를 들어 "미션 크리티컬" 트래픽이 발생하지 않는 테이블을 스캔하려고 합니다. 일부 애플리케이션은 중요 트래픽용과 기록용의 두 테이블 간에 트래픽을 매시간 순환하여 이 부하를 처리합니다. 또 어떤 애플리케이션은 "미션 크리티컬" 테이블과 "섀도" 테이블, 두 개에서 모든 쓰기 작업을 실행하여 부하를 처리하기도 합니다.

애플리케이션은 할당 처리량을 초과했다는 응답 코드가 수신되는 요청은 모두 재시도하거나 작업으로 테이블의 프로비저닝된 처리량을 높일 수 있도록 구성합니다. 또는 UpdateTable 작업을 사용하여 테이블의 프로비저닝된 처리량을 증가시킵니다. 워크로드의 일시적인 급증으로 인해 처리량이 간혹 할당된 수준을 초과할 때는 지수 백오프로 요청을 재시도합니다. 지수 백오프의 구현에 대한 자세한 내용은 오류 재시도 횟수 및 지수 백오프 단원을 참조하십시오.

병렬 스캔 활용

다양한 애플리케이션이 순차식 스캔이 아닌 병렬식 Scan 작업의 이점을 이용할 수 있습니다. 예를 들어 대용량의 이력 데이터 테이블을 처리하는 애플리케이션의 경우 순차식보다는 병렬식 스캔이 훨씬 빠릅니다. 백그라운드 "스위퍼" 프로세스에서 다수의 작업자 스레드가 우선순위를 낮춰 테이블을 스캔하기 때문에 프로덕션 트래픽에 아무런 영향도 끼치지 않습니다. 이 두 가지 예에서 모두 병렬식 Scan은 다른 애플리케이션에 필요한 할당 처리량 리소스까지 소비하지는 않습니다.

이처럼 병렬식 스캔이 유용하기는 하지만 할당 처리량에 대한 수요가 지나치게 높아집니다. 병렬 스캔의 경우, 애플리케이션이 여러 작업자로 하여금 동시에 Scan 작업을 실행시킬 수 있습니다. 이렇게 하면 테이블의 프로비저닝된 읽기 용량이 빠르게 소비됩니다. 이 경우 동일한 테이블에 액세스해야 하는 다른 애플리케이션은 병목 현상이 발생하게 됩니다.

병렬식 스캔은 다음과 같은 조건만 충족된다면 올바른 선택이라고 할 수 있습니다.

  • 테이블 크기가 20GB 이상입니다.

  • 테이블에 프로비저닝된 읽기 처리량이 사용하고도 남습니다.

  • 순차식 Scan 작업이 너무 느립니다.

TotalSegments 선택

최적의 TotalSegments 설정 값은 특정 데이터, 테이블의 할당 처리량 설정 값, 그리고 성능 요건에 따라 결정됩니다. 올바른 설정을 위해서는 시험이 필요할 것입니다. 먼저 2GB 데이터당 한 세그먼트 같이 단순 비율부터 시작하는 것이 좋습니다. 예를 들어 테이블 크기가 30GB라면 TotalSegments를 15(30GB / 2GB)로 설정할 수 있습니다. 그러면 애플리케이션은 15명의 작업자를 사용하지만 각 작업자마다 다른 세그먼트를 스캔합니다.

그 밖에 클라이언트 리소스를 기준으로 TotalSegments 값을 선택하는 방법도 있습니다. TotalSegments를 1부터 1,000,000 중 한 숫자로 설정합니다. 그러면 DynamoDB에서 해당 개수의 세그먼트를 스캔할 수 있습니다. 예를 들어 클라이언트가 동시에 실행할 수 있는 스레드 수를 제한하는 경우 애플리케이션의 Scan 성능이 최적화될 때까지 TotalSegments를 일정하게 늘리면 됩니다.

프로비저닝된 처리량을 최적화하려면 병렬식 스캔을 모니터링해야 하지만 동시에 다른 애플리케이션에 필요한 리소스까지 소비해서는 안 됩니다. 프로비저닝된 처리량을 모두 소비하지 않는데도 여전히 Scan 요청에 병목 현상을 겪고 있다면 TotalSegments 값을 높여 설정하십시오. 그리고 Scan 요청 시 할당 처리량을 의도한 것보다 많이 소비한다면 TotalSegments 값을 내려 설정하십시오.