sklass의 s-class 프로그래밍 blog

[DynamoDB] AWS DynamoDB 기초 본문

dynamodb

[DynamoDB] AWS DynamoDB 기초

sklass 2021. 9. 20. 02:34

DynamoDB는 key value 형식의 NoSQL 데이터베이스로, simple primary key(partition key)와 composite primary key(partition key & sorting key) 라는 두가지 종류의 primary key를 갖습니다. DynamoDB를 schemaless 데이터베이스라고 하지만, partition key와 sorting key가 schema역할을 하기때문에 완전한 schemaless라고 할 수는 없습니다.

Partition Key & Sorting Key

Partition key는 물리적 공간인 partition을 특정하는 키로, 

  • 데이터를 저장하기 전, request router가 먼저 저장할 혹은 읽어올 데이터의 partition key와 metadata를 받고, partiton key를 dynamoDB에 내장된 hash function을 이용해서 어떤 파티션 주소로 데이터를 배정할지 결정합니다.
  • 스케일이 아무리 커져도 주소를 알고 있기 때문에 데이터를 빠르게 가져올 수 있습니다.
  • 아무리 partition의 개수가 늘어난다 하더라도, dynamoDB의 내장된 hash function으로 요청된 partition을 찾는데 소모되는 시간 복잡도는 O(1) 입니다.
  • partition key로는 일치하는 값만(eq) 가져올 수 있고, 조건문으로 작성할 수 없는 이유이기도 합니다.

Sorting key (range key)는 partition 내에서 정렬하는 기준 값입니다. (검색을 위한 최소의 조건입니다.)

  • Number, Binary, String 타입을 지원하며, String 이라면 utf-8 기준으로 정렬됩니다.
    • Sorting Key 는 보통 Number 타입을 가장 많이 사용합니다.
  • 단순정렬이기 때문에 partition의 사이즈가 커져도 빠르게 가져올 수 있습니다.
  • Sorting key 로는 eq, lt, gt 등의 비교조건과 between, begin_with 만 지원합니다.

Pricing

Oregon 서버의 DynamoDB 읽기, 쓰기 비용
Oregon 서버의 DynamoDB 스토리지 비용

Scan & Query

Scan 은 지정한 테이블의 모든 항목을 가져오는 작업으로, scan 을 하게 될 경우, 테이블의 전체 용량에 대한 RCU가 부과 됩니다. 다만, ConsistentRead가 False이면, (False가 default 입니다.) 8KB당 1 RCU가 부과됩니다.

다음은 113KB 크기의 table을 scan할 경우 사용되는 RCU를 측정해본 결과입니다.

Query 는 특정 partition key를 갖는 모든 항목을 가져오는 작업으로, scan과는 다르게 요청에 대한 sorting과 reversed sorting이 가능합니다. 

 

RCU(Read Capacity Units)WCU(Write Capacity Units)는 dynamoDB에 읽기와 쓰기 요청의 단위로, Eventually Consistent Read(그냥 scan이나 query를 하면 default로 Eventually Consistent Read입니다.) 는 8KB당 1RCU 를 소모하게 되고, Strongly Consistent Read 4KB당 1RCU 를 소모하게 됩니다.

 

Eventually Consistent Read의 경우 1-2초 정도의 update 딜레이가 있기 때문에 1-2초 정도 전에 write을 했다면, 그 값이 return되지 않을 확률이 있습니다. 반대로 Strongly Consistent Read를 쓰면 write한 값을 즉각적으로 받아와서 stale한 데이터를 얻지 않습니다. 다만 Strongly Consistent Read는 Eventually Consistent Read 보다 비용이 2배이며, Eventually Consistent Read보다 지연 시간이 더 길 수도 있고, 글로벌 보조 인덱스(Global Secondary Index)에는 적용되지 않습니다.

 

Scan과 Query 모두 호출 당 1MB로 크기 제한이 있으며, Response로 날라오는 Json형식의 데이터에서 LastEvaluatedKey를 사용하여 1MB 이상의 데이터를 계속해서 1MB씩 잘라서 가져올 수 있습니다.

 

KeyConditionExpression을 사용하면 해당 조건에 매치되는 아이템만 호출하기 때문에 호출을 효율적으로 할 수 있고, return된 아이템의 크기만큼만 과금되지만, FilterExpression의 경우, 해당 조건과 상관없이 KeyConditionExpression으로 return된 아이템들에 대해서 과금이 이미 된 상태에서 filtering이 후처리되기 때문에, 요금을 절약하는 방식이라고 할 수는 없습니다.

 

ProjectionExpression 또한 KeyConditionExpression 으로 받아온 뒤에 진행되는 과정으로, 과금을 줄이는 것과는 거리가 멉니다

GSI (Global Secondary Index)

  • 다른 속성들로 다양한 유형의 query를 수행해야하는데, 이를 수행하기 위해서 하나 이상의 GSI를 생성하여 처리합니다.
  • GSI을 추가하면 원본 테이블을 복제해 새로운 테이블을 만드는 방식입니다.
  • 복제한 원본 테이블의 아이템을
    • GSI의 파티션키(partition key)로 새로운 물리 공간을 할당해 저장하고,
    • GSI의 정렬키(sorting key)로 정렬해 저장해둔다.
    • 원본 테이블이 변경되면 GSI의 테이블도 동기화하는 구조다.
  • 테이블 별로 최대 20개의 GSI를 생성할 수 있다.
  • GSI는 기존 테이블을 복제해서 새로운 partition에 넣는것이기 때문에 최대 10GB per GSI의 용량을 가진다.

Item Size

  • String: (lengthof attribute name) + (number of UTF-8-econded bytes)
    • ex) {"mol_id": "mol_234"} → 13 bytes
  • Numbers: (length of attribute name) + (1 byte per two significant digits) + (1 byte)
    • ex) {"docking": 1.435} → 10 bytes
  • Boolean or Null: (length of attribute name) + 1 byte
    • ex) {"docking_done": True} → 13 bytes
  • Map or List: (length of attribute name) + sum(size of nested elements) + (3 bytes=overhead)
    • ex) {"rdkit_object": {"atom":{"z":6}} → 22 bytes
  • 현재(2021-07-27) 기준으로 nn_dti_done-index gsi에 500만 items가 있다고 가정한 item size 계산법
    • 각 item들은 mol_id, conformer_id. nn_dti, docking, timestamp, rdkit_object, min_NN_DTI_conformer_id, min_docking_conformer_id 를 attribute으로 갖고 있고, 한 item당 size는 아래와 같이 98 bytes 이다.
    • 500만개의 items의 총 size:
      • 5,000,000 * 98byte
      • = 14,830,000,000 bytes
      • = 467.3 MB (59,814.5RCU, 478,516WCU)

 

 

'dynamodb' 카테고리의 다른 글

[DynamoDB] Partitions  (0) 2021.10.03