입문4분 분량

DynamoDB 프로젝션 표현식

프로젝션 표현식은 DynamoDB의 SELECT col1, col2입니다. GetItem, Query 또는 Scan을 나타내는 쉼표로 구분된 이름 목록 전체 항목 대신 해당 속성만 반환합니다.

DynamoDB 프로젝션 표현식이 읽기 비용을 줄여줍니까?

아니요. ProjectionExpression는 청구되는 읽기 용량이 아닌 응답 페이로드를 줄입니다. DynamoDB는 스토리지에서 전체 항목을 읽고, 디스크에 있는 크기에서 를 측정한 다음, 도중에 이름을 지정하지 않은 속성을 삭제합니다. 실제로 읽기 비용을 줄이려면 커버 를 대신 사용하세요.

  • 읽기 비용이 아닌 페이로드를 줄입니다. DynamoDB는 저장소에서 전체 항목을 가져온 다음 도중에 이름을 지정하지 않은 속성을 삭제합니다. 밖으로. ProjectionExpression는 용량 최적화가 아닌 네트워크 최적화입니다.
  • 공개 하위 집합을 가져오는 방법입니다. 호출자의 몇 가지 속성 이름을 지정하세요. 볼 수 있게 허용됨; 나머지는 절대 테이블을 떠나지 않습니다.
  • 예약될 수 있는 항목에는 #name 자리 표시자를 사용하세요. 일반 표현식의 속성 이름이 DynamoDB의 ~570개 예약어와 충돌합니다. 요청이 실패합니다.
  • 실제 읽기 비용 절감을 위해 대신 커버링 인덱스를 사용하세요. 프로젝트하는 필요한 열만 자체(더 작은) 크기로 읽혀집니다.

실제로 저장되는 것

SQL에서 SELECT a, b 스캔이 SELECT *보다 작다고 가정합니다. 에서 직관이 틀렸다는 DynamoDB. 는 읽기에 대한 capacity unit는 다음과 같이 계산됩니다. 디스크에 있는 항목의 크기(다음 4KB로 반올림됨) — 투영이 적용됩니다. AWS는 명시적입니다. ProjectionExpression는 변경되지 않습니다. 요청이 소비하는 읽기 용량입니다.1

따라서 프로젝션을 사용하면 실제와 읽기의 다운스트림 두 가지를 절약할 수 있습니다.

  • 전송된 바이트 수. 두 개의 작은 속성으로 반환된 6KB 항목은 매우 작습니다. 응답. 수백 개의 항목을 반환하는 Query에서는 빠르게 합산됩니다.
  • 클라이언트 측 작업. 역직렬화할 일이 적고, 메모리에 보관할 일도 적고, 누수가 적습니다. 우연히 로그나 API 응답에 추가되었습니다.

저장하지 않는 것은 RCU입니다. 그것이 바로 풋건입니다. 사람들은 요금을 삭감하고 아무런 변화도 보이지 않아 DynamoDB가 손상되었다고 결론을 내릴 것으로 예상됩니다. 그것 그렇지 않습니다. 레버를 잘못 측정하셨습니다.

공개 사용자 프로필 투사

사용자 디렉터리를 실행한다고 가정해 보겠습니다. 각 프로필은 하나의 항목으로, 키가 입력되어 있어 사람별 핸들:

PK = "PROFILE#ada"      (partition key)
SK = "PROFILE#ada"      (sort key — single-item collection)

항목이 뚱뚱합니다. 그것은 계정의 공개적인 얼굴과 함께 많은 정보를 담고 있습니다. 개인 및 운영 속성:

{
  "PK": "PROFILE#ada",
  "SK": "PROFILE#ada",
  "displayName": "Ada L.",
  "avatarUrl": "https://cdn.example.com/u/ada.png",
  "bio": "Builds things.",
  "emailAddress": "ada@example.com",
  "passwordResetToken": "…",
  "billingCustomerId": "cus_…",
  "lastLoginIp": "…",
  "internalRiskScore": 0.02
}

공개 프로필 카드에는 세 개의 필드가 필요합니다. 전체 항목을 가져오는 것은 의미합니다. emailAddress, lastLoginIp, internalRiskScore는 다음과 같은 컨텍스트로 이동합니다. 절대로 봐서는 안 됩니다. 공개 하위 집합만 이름을 지정하세요.

GetItem  PK = "PROFILE#ada"  SK = "PROFILE#ada"
ProjectionExpression: displayName, avatarUrl, bio

응답에는 세 가지 속성이 있습니다. 개인적인 것들은 테이블에 남아 있습니다. 도착 후_앱에 의해 필터링되지만 응답에 직렬화되지는 않습니다. 전혀. 이것이 바로 보안상의 이점이며 한 번에 실행 취소하기 어려운 부분입니다. 비밀은 이미 경계를 넘었습니다.

이름, 자리 표시자, SDK 등 정확한 요청을 조합하고 복사할 수 있습니다. 전화 — DynamoDB Expression Builder, 방출하는 ProjectionExpressionExpressionAttributeNames 지도를 확인해 보세요.

ProjectionExpression를 보려면 아래 사전 설정에서 필드를 추가하거나 제거하세요. 변경 — 나열된 속성만 다시 나타납니다.

요청 만들기
생성된 코드
new QueryCommand({
  "TableName": "AuditLog",
  "KeyConditionExpression": "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)",
  "ProjectionExpression": "#proj0, #proj1, #proj2",
  "ExpressionAttributeNames": {
    "#hashKey": "pk",
    "#rangeKey": "sk",
    "#proj0": "action",
    "#proj1": "actor",
    "#proj2": "createdAt"
  },
  "ExpressionAttributeValues": {
    ":hashKeyValue": {
      "S": "TENANT#acme"
    },
    ":rangeKeyValue": {
      "S": "EVENT#"
    }
  }
})

# 자리 표시자를 사용하여 예약어를 탈출하세요

예약어에 대한 깨끗한 프로젝션이 폭발합니다. DynamoDB는 다음과 같은 긴 목록을 예약합니다. 단어 — name, status, comment, size, timestamp 외 수백 개.[^reserved] 프로젝션하는 속성이 그 중 하나인 경우 표현식의 원시 이름 거부됩니다.

프로파일에 status 속성("active", "suspended")도 있다고 가정합니다. 실패합니다.

ProjectionExpression   displayName, status

status은 예약되어 있습니다. 수정 사항은 표현식 속성 이름입니다. 접두사가 #입니다. 실명에 매핑된 자리 표시자:

ProjectionExpression       displayName, #s
ExpressionAttributeNames   { "#s": "status" }

동일한 메커니즘이 중첩된 속성에 도달합니다. 단일 필드를 꺼내려면 맵 또는 목록의 한 요소는 문서 경로 구문을 사용합니다. 세그먼트 중 하나라도 예약될 수 있으므로:

ProjectionExpression       #addr.#city, tags[0]
ExpressionAttributeNames   { "#addr": "address", "#city": "city" }

실용적인 규칙: 자리 표시자는 모든 것입니다. 당신은 다음 중 어느 것을 기억할 필요가 없습니다 당신이 서 있는 ~570개의 예약어, 표현은 동일하게 읽혀집니다. 방법. 어떤 이름이 실제로 문제인지 알고 싶다면 붙여넣으세요. reserved-words checker에 — 그것 충돌을 표시하고 ExpressionAttributeNames 앨리어스 맵을 내보냅니다.

커버링 지수가 예상 지수를 능가할 때

페이로드뿐만 아니라 읽기 비용을 정말로 절감해야 하는 경우 레버는 읽은 속성만 투영하는 Global Secondary Index. GSI는 데이터의 별도 사본; KEYS_ONLY, INCLUDE 또는 ALL를 선택합니다. 투영.3 KEYS_ONLY 또는 좁은 INCLUDE 지수는 물리적으로 품목당 더 작으므로 해당 품목에 대해 Query가 더 작은 크기로 측정됩니다.

이는 포괄 색인입니다. 쿼리는 전적으로 색인에서 응답됩니다. 기본 테이블로 돌아갑니다. 핫 읽기 패턴에 몇 가지만 필요할 때 사용하세요. 대형 항목의 속성.

ProjectionExpressionGSI 취재
페이로드 절감
읽기 비용 절감아니요 — 인덱스 크기로 읽기
추가 저장용량없음예상 필드의 두 번째 사본
추가 쓰기 비용없음쓰기가 인덱스에 전파됨
비공개 필드를 숨깁니다. 작은 승리큰 항목의 일부 필드에 대한 핫 읽기

균형은 정직합니다. 인덱스에는 저장 비용이 들고 저장하기 위해 쓰기 용량이 필요합니다. 읽기 용량. 무거운 물건의 얇은 조각을 자주 읽는 데는 가치가 있습니다. 일회성 GetItem을 면도할 가치가 없습니다. 참조 GSI vs LSI은 인덱스 유형을 선택하고, when a GSI read can be stale 이전 당신은 핫 패스에 하나를 넣었습니다.

함정과 다음 단계

  • 더 적은 비용을 기대하지 마십시오. 예측만으로는 RCU가 변경되지 않습니다. 만약 숫자가 움직이지 않았습니다. 이는 버그가 아니라 문서화된 동작입니다.
  • 자리 표시자 예약어. 표현식에 name 또는 status만 있음 요청이 실패합니다 — #-매핑합니다.
  • 항상 주요 속성을 포함 - 무시할 만한 페이로드를 추가하고 항목을 페이지로 이동하거나 다시 가져옵니다.
  • 핫 패턴이 몇 개의 필드를 읽을 때만 포함 인덱스에 도달 대형 품목; 먼저 쓰기/저장 비용을 측정해 보세요.

ProjectionExpression와 해당 속성 이름 맵을 Expression Builder, 및 try DynoTable 자신의 테이블에 대해 이러한 예측을 실행하고 응답이 줄어드는 것을 지켜보세요.


  1. AWS DynamoDB 개발자 안내서, DynamoDB에서 프로젝션 표현식 사용 — 읽기 용량은 ProjectionExpression가 적용되기 전의 항목 크기를 기준으로 합니다. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
  2. AWS DynamoDB 개발자 안내서, DynamoDB의 예약어. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
  3. AWS DynamoDB 개발자 안내서, 속성 예측(KEYS_ONLY / INCLUDE / ALL). https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html

업데이트됨