중급6분 분량

DynamoDB의 다대다 관계

학생은 많은 과정에 등록합니다. 한 코스에는 많은 학생이 있습니다. SQL에서는 다음과 같은 결과를 얻을 수 있습니다. 조인 테이블과 3개의 테이블 JOIN의 경우.

DynamoDB에는 조인이 없으므로 관계는 에 있어야 합니다. 비결은 양쪽이 Query할 수 있는 모양으로 각 등록 가장자리를 저장하는 것입니다. 직접.

이 가이드는 학생 ← 코스 문제를 처음부터 끝까지 안내합니다. 액세스 패턴, 이를 해결하는 10가지 패턴, 복사할 수 있는 원본 키 스키마, 방법 테이블을 스캔하지 않고도 양방향으로 다시 읽을 수 있습니다.

DynamoDB에서 다대다 관계를 어떻게 모델링합니까?

DynamoDB에는 조인이 없으므로 패턴을 사용하여 다대다 관계를 모델링합니다. 각 링크를 한쪽으로 키가 지정된 자체 엣지 항목으로 저장한 다음 키를 교환하는 반전된 GSI를 추가합니다. 한 번 작성된 단일 에지는 양방향 쿼리에 저렴하게 응답합니다.

  • 각 등록을 양쪽의 목록 속성이 아닌 자체 엣지 항목으로 저장합니다.
  • 학생이 가장자리를 입력(PK = STU#…, SK = ENROLL#CRS#…)하여 하나의 Query 학생의 전체 코스 목록을 반환합니다.
  • 역할(GSI1PK = CRS#…)을 바꾸는 반전된 를 추가하여 동일한 가장자리를 만듭니다. "이 강좌에는 누가 있나요?"라고 대답합니다.
  • 한 번 작성된 한쪽 가장자리는 양방향으로 쉽게 읽혀집니다 — 이것이 전체 게임입니다.

먼저 액세스 패턴을 구성하세요.

DynamoDB 모델링은 액세스 패턴 우선입니다. 즉, 읽기를 선택하기 전에 결정합니다. 단일 속성 이름. 다대다 관계는 거의 항상 2 대칭을 갖습니다. 읽기와 엔터티 조회:

  • 학생의 프로필을 가져오고 학생이 등록한 모든 과정을 나열합니다.
  • 강좌의 메타데이터를 가져오고 해당 강좌에 등록한 모든 학생을 나열합니다.
  • 단일 등록 에지를 조회하여 성적을 업데이트하거나 강좌를 삭제합니다.

문제점: 두 개의 목록 읽기가 동일한 세트에서 반대 방향을 가리킵니다. 가장자리. 순진한 설계는 한 사람에게는 값싼 서비스를 제공하고 다른 사람에게는 Scan를 강요합니다. — 정확한 Query vs Scan로 덮인 풋건.

작업은 양쪽 방향을 단일 Query로 만드는 것입니다.

인접 목록 패턴을 사용하세요

관계에 대한 DynamoDB의 자체 지침은 인접 목록입니다. 파티션 키가 하나의 엔드포인트이고 정렬 키가 하나의 항목인 관계 기타.

AWS는 이를 문서에 기록합니다. Best Practices for Managing Many-to-Many Relationships DynamoDB 개발자 안내서 페이지.

왜 두 번째 테이블이 아닌 키가 있습니까? 기본 DynamoDB가 제공하는 것은 Query입니다. 단일 파티션에 대해.

A Query는 하나의 파티션 키 아래에 있는 연속된 정렬 키 값 범위를 하나씩 읽습니다. 청구된 작업 - 엔진이 제공하는 유일한 "조인"입니다.

양쪽 측면에서 쉽게 읽을 수 있는 관계를 얻으려면 가장자리를 복제합니다. 학생이 키를 입력한 다음 보조 색인을 사용하여 동일한 가장자리를 투영합니다. 코스에 따라 키가 지정됩니다.

이것이 바로 오버로드된 키 사고입니다. Single-Table Design, 대신 관계에 적용됨 부모-자식 계층 구조.

모양은 동일한 가장자리의 두 개의 스택 뷰입니다. 기본 테이블은 학생이 키를 입력하고 코스별로 키가 지정된 반전된 GSI:

같은 엣지, 교환같은 엣지, 교환반전 GSI1 코스로GSI1PK CRS#math204GSI1SK STU#a91GSI1PK CRS#cs101GSI1SK STU#a91베이스 테이블 학생으로PK STU#a91SK ENROLL#CRS#math204PK STU#a91SK ENROLL#CRS#cs101

각 에지는 기본 테이블에 한 번 기록되고 해당 키와 함께 GSI에 프로젝션됩니다. 교체되었으므로 두 파티션 중 하나에 대해 Query를 사용하면 관계를 쉽게 읽을 수 있습니다.

그 계보는 2007년 아마존으로 거슬러 올라갑니다. Dynamo paper: 파티션 키는 배포 단위이고 단일 키 액세스는 빠른 경로입니다.

DynamoDB의 관계는 다대다 읽기를 빠르게 변환하는 연습입니다. 경로.

예시를 들어보세요: 학생 ⇔ 강좌

일반 키 PKSK가 있는 하나의 테이블을 사용하고 엔터티 유형을 가치. 등록 에지는 그 핵심입니다.

PKSKattributes
STU#a91PROFILEname, year, major
STU#a91ENROLL#CRS#math204 enrolledOn, grade
STU#a91ENROLL#CRS#cs101enrolledOn, grade
CRS#math204METADATAtitle, credits, term
CRS#cs101METADATAtitle, credits, term

단일 Query PK = "STU#a91"은 학생의 프로필 모든 등록을 반환합니다. 한 번에 읽어요. 코스 가장자리만 얻으려면 SK begins_with "ENROLL#"로 범위를 좁힙니다. 그것은 "학생의 코스 목록"을 해결합니다.

그러나 "과정의 학생 목록"은 다른 방향을 가리키며 기본 테이블은 이에 답할 수 없습니다. 학생 ID가 정렬 키가 아닌 파티션 키에 있기 때문입니다.

역할을 교환하는 반전된 글로벌 보조 인덱스를 추가합니다. 가장자리 항목에 일반 GSI1PK/GSI1SK 쌍은 칸막이 쪽 코스와 학생을 잡고 있습니다. 정렬 측면에서:

PKSKGSI1PKGSI1SK
STU#a91ENROLL#CRS#math204CRS#math204STU#a91
STU#b30ENROLL#CRS#math204CRS#math204STU#b30
STU#a91ENROLL#CRS#cs101CRS#cs101STU#a91

이제 Query GSI1 WHERE GSI1PK = "CRS#math204"에는 해당 강좌의 모든 학생이 나열됩니다. 기본 테이블을 읽을 수 없습니다. 한 번 작성된 하나의 엣지 항목은 두 가지 모두에 답합니다. 방향.

LSI가 아닌 GSI여야 합니다. 코스 파티션은 코스 파티션과 완전히 다릅니다. 학생 파티션 및 LSI는 기본 테이블의 파티션 키를 공유합니다.

인덱스는 여러 파티션에 걸쳐 있으므로 글로벌이어야 합니다. GSI vs LSI.

DynamoDB의 GSI는 비동기식으로 채워집니다. 새로운 등록에는 시간이 걸릴 수 있습니다. CRS#… 방향으로 나타나는 순간.

개발자 가이드에서 호출하는 로 읽은 강좌 명단을 처리합니다. 글로벌 보조 인덱스에 대해 명시적으로 출력됩니다.

DynoTable에서 쓰고 읽습니다.

등록을 작성한다는 것은 네 가지 주요 속성과 엣지의 자체 데이터를 설정하는 것을 의미합니다. 는 학생이 동일한 코스에 두 번 등록하는 것을 막는 조건은 attribute_not_exists(PK) 복합 키의 가드.

이것이 바로 시각적으로 조합할 수 있는 종류의 조건입니다. DynamoDB Expression Builder 대신 ExpressionAttributeNames 및 자리 표시자 값을 직접 작성합니다.

DynoTable에서 QueryGSI1로 지정하고 GSI1PK = "CRS#math204"를 설정하면 명단은 그 자리에서 읽고, 정렬하고, 편집할 수 있는 테이블로 돌아옵니다. 하나의 스키마에서 찾아볼 수 있는 관계.

한 강좌에 등록한 모든 학생을 나열하려고 DynoTable에서 반전 GSI를 쿼리하는 모습.
한 강좌에 등록한 모든 학생을 나열하려고 DynoTable에서 반전 GSI를 쿼리하는 모습.

함정과 다음 단계

  • 한 쪽을 목록 속성으로 저장하지 마세요. 학생 항목에 courseIds 배열이 있습니다. 코스에 명단이 필요할 때까지, 배열이 400KB 항목 한도에 도달할 때까지 깔끔한 느낌을 받거나 두 등록이 서로 경쟁하고 두들겨 패고 있습니다. 개별 엣지 항목의 크기 조정 및 업데이트 독립적으로.
  • 에지 데이터를 에지에 유지합니다. 등록의 gradeenrolledOn는 다음에 속합니다. 학생이나 코스에 복제되지 않은 가장자리 항목 — 각 항목당 정확히 하나의 행이 있습니다. (학생, 코스) 쌍을 업데이트합니다.
  • GSI 전파를 염두에 두세요. 반전된 인덱스 방향은 결국 일관됩니다. 등록 직후에는 읽기가 몇 초 정도 지연될 수 있습니다.
  • 명단에 필요한 것만 투영합니다. KEYS_ONLY 또는 좁은 투영으로 명단 보기에 ID만 필요한 경우 GSI는 작습니다.

주변 패턴에 대해 더 자세히 알아보려면 다음을 읽어보세요. 과부하된 키의 경우 Single-Table DesignGSI vs LSI은 반전된 인덱스가 글로벌이어야 하는 경우입니다. 그리고 자신의 관계에서 시작하려면 무료입니다. Single-Table Design tool은 "학생의 강좌 목록 / 강좌의 학생 목록"과 같은 액세스 패턴 목록 예시 항목이 포함된 PK/SK/GSI 계획에 포함됩니다.

그런 다음 DynoTable 다운로드해서 학생 ↔ 강좌 스키마를 실제로 모델링해 보세요 — 엣지를 쓰고, Expression Builder로 조건을 만들고, 스캔 한 번 없이 관계의 양쪽 방향을 모두 쿼리할 수 있습니다. 그래도 고전적인 3테이블 JOIN 뷰가 보고 싶다면, DynoTable의 SQL Workbench가 여러분의 라이브 테이블 위에서 그것을 실행해 줍니다.

업데이트됨

이 디자인을 인터랙티브하게 사용해 보세요

무료 DynamoDB 싱글 테이블 디자인 도구에서 엔터티와 액세스 패턴을 스케치해 보세요 — PK/SK 키 템플릿을 제안하고, 항목 컬렉션을 미리 보여주며, 어떤 패턴이 GSI를 필요로 하는지 보여줍니다.

싱글 테이블 디자인 도구 열기