DynamoDB는 AWS의 대표적인 NoSQL 기반의 데이터 베이스로 , Key-Value 형태를 제공합니다.
스키마가 따로 정해져 있지 않으며, 확장성이 높은 고성능의 데이터베이스를 제공합니다. 또한, JSON 형태로 데이터를 저장하고, 온디멘드 형식으로 확장이 용이한 장점이 있습니다.
NoSQL 특징
DynamoDB 구성
다른 DB 시스템과 마찬가지로 데이터를 테이블에 저장한다.
🌿 프로비저닝이란?
- 서버의 CPU, Memory등의 자원을 할당 또는 적절하게 배치하여 운영할 수 있도록 준비해 놓은 것
- 이 모드에서 사용자는 애플리케이션에 필요한 읽기 용량 단위(RCU) 및 쓰기 용량 단위(WCU) 측면에서 프로비저닝된 용량을 완전히 활용하지 않더라도 Amazon DynamoDB 테이블에서 프로비저닝한 처리량 용량(읽기 및 쓰기)에 대해 요금이 부과됨
🌿 온디맨드:
용량 계획 없이 초당 수천 개의 요청을 처리할 수 있는 유연한 청구 옵션
DynamoDB 온디맨드는 읽기 및 쓰기 요청에 대해 요청당 지불 가격을 제공
🌿 온프레미스
기업이 자체적으로 IT인프라를 소유, 관리 및 운영
aws dynamodb create-table \
--table-name Music \
--attribute-definitions \
AttributeName=Artist,AttributeType=S \
AttributeName=SongTitle,AttributeType=S \
--key-schema \
AttributeName=Artist,KeyType=HASH \
AttributeName=SongTitle,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--table-class STANDARD
-----
#테이블 생성 (git bash 에서)
aws dynamodb create-table \
--table-name Music \ #테이블의 이름을 "Music"으로 설정
--attribute-definitions \ # 테이블의 속성(Attributes)을 정의
AttributeName=Artist,AttributeType=S \
AttributeName=SongTitle,AttributeType=S \
--key-schema \ # Primary Key(기본 키)를 정의하는 옵션
AttributeName=Artist,KeyType=HASH \ #속성을 Hash Key로 사용
AttributeName=SongTitle,KeyType=RANGE \ #속성을 Range Key로 사용
--provisioned-throughput \ # 테이블의 처리량(capacity)을 정의
ReadCapacityUnits=5,WriteCapacityUnits=5 \ # 읽기 , 쓰기 처리량을 초당 5개의 Capacity Unit으로 설정
--table-class STANDARD # 테이블 클래스를 "STANDARD"로 설정합니다. 이는 표준 스토리지 엔진을 사용한다는 것을 의미
# 데이터 쓰기
aws dynamodb put-item \
--table-name Music \
--item \
'{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}'
aws dynamodb put-item \
--table-name Music \
--item \
'{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Howdy"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "2"}}'
aws dynamodb put-item \
--table-name Music \
--item \
'{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}, "Awards": {"N": "10"}}'
aws dynamodb put-item \
--table-name Music \
--item \
'{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "PartiQL Rocks"}, "AlbumTitle": {"S": "Another Album Title"}, "Awards": {"N": "8"}}'
# 데이터 읽기
$aws dynamodb get-item --consistent-read \
--table-name Music \
--key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}'
{
"Item": {
"AlbumTitle": {
"S": "Songs About Life"
},
"Awards": {
"N": "10"
},
"Artist": {
"S": "Acme Band"
},
"SongTitle": {
"S": "Happy Day"
}
}
}
# 데이터 업데이트
$aws dynamodb update-item \
--table-name Music \
--key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}' \
--update-expression "SET AlbumTitle = :newval" \
--expression-attribute-values '{":newval":{"S":"Updated Album Title"}}' \
--return-values ALL_NEW
{
"Attributes": {
"AlbumTitle": {
"S": "Updated Album Title"
},
"Awards": {
"N": "10"
},
"Artist": {
"S": "Acme Band"
},
"SongTitle": {
"S": "Happy Day"
}
}
}
# 데이터 쿼리
$aws dynamodb query \
--table-name Music \
--key-condition-expression "Artist = :name" \
--expression-attribute-values '{":name":{"S":"Acme Band"}}'
{
"Items": [
{
"AlbumTitle": {
"S": "Updated Album Title"
},
"Awards": {
"N": "10"
},
"Artist": {
"S": "Acme Band"
},
"SongTitle": {
"S": "Happy Day"
}
},
{
"AlbumTitle": {
"S": "Another Album Title"
},
"Awards": {
"N": "8"
},
"Artist": {
"S": "Acme Band"
},
"SongTitle": {
"S": "PartiQL Rocks"
}
}
],
"Count": 2,
"ScannedCount": 2,
"ConsumedCapacity": null
}
# 글로벌 보조 인덱스 생성
$aws dynamodb update-table \
--table-name Music \
--attribute-definitions AttributeName=AlbumTitle,AttributeType=S \
--global-secondary-index-updates \
"[{\"Create\":{\"IndexName\": \"AlbumTitle-index\",\"KeySchema\":[{\"AttributeName\":\"AlbumTitle\",\"KeyType\":\"HASH\"}], \
\"ProvisionedThroughput\": {\"ReadCapacityUnits\": 10, \"WriteCapacityUnits\": 5 },\"Projection\":{\"ProjectionType\":\"ALL\"}}}]"
{
"TableDescription": {
"AttributeDefinitions": [
{
"AttributeName": "AlbumTitle",
"AttributeType": "S"
},
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"TableName": "Music",
"KeySchema": [
{
"AttributeName": "Artist",
"KeyType": "HASH"
},
{
"AttributeName": "SongTitle",
"KeyType": "RANGE"
}
],
"TableStatus": "UPDATING",
"CreationDateTime": "2024-02-26T09:23:08.217000+09:00",
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
},
"TableSizeBytes": 0,
"ItemCount": 0,
"TableArn": "arn:aws:dynamodb:ap-northeast-2:646580111040:table/Music",
"TableId": "25be7397-7f67-4b59-ad0c-2512ca62fa5a",
"GlobalSecondaryIndexes": [
{
"IndexName": "AlbumTitle-index",
"KeySchema": [
{
"AttributeName": "AlbumTitle",
"KeyType": "HASH"
}
],
"Projection": {
"ProjectionType": "ALL"
},
"IndexStatus": "CREATING",
"Backfilling": false,
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 5
},
"IndexSizeBytes": 0,
"ItemCount": 0,
"IndexArn": "arn:aws:dynamodb:ap-northeast-2:646580111040:table/Music/index/AlbumTitle-index"
}
],
"TableClassSummary": {
"TableClass": "STANDARD"
},
"DeletionProtectionEnabled": false
}
}
# 글로벌 보조 인덱스 쿼리
$aws dynamodb query \
--table-name Music \
--index-name AlbumTitle-index \
--key-condition-expression "AlbumTitle = :name" \
--expression-attribute-values '{":name":{"S":"Somewhat Famous"}}'
{
"Items": [
{
"AlbumTitle": {
"S": "Somewhat Famous"
},
"Awards": {
"N": "1"
},
"Artist": {
"S": "No One You Know"
},
"SongTitle": {
"S": "Call Me Today"
}
},
{
"AlbumTitle": {
"S": "Somewhat Famous" # S 는 string
},
"Awards": {
"N": "2" # N은 number
},
"Artist": {
"S": "No One You Know"
},
"SongTitle": {
"S": "Howdy"
}
}
],
"Count": 2,
"ScannedCount": 2,
"ConsumedCapacity": null
}
tip
: 표기가 있는 이름 선언시는 동적 변수로 간주
https://dynobase.dev/dynamodb-json-converter-tool/
{
"emp": [
{
"empno" : 7369,
"ename" : "SMITH",
"job" : "CLERK",
"mgr" : 7902,
"hiredate" : "1980-12-17",
"sal" : 800.00,
"comm" : null,
"deptno" : 20
},
{
"empno" : 7499,
"ename" : "ALLEN",
"job" : "SALESMAN",
"mgr" : 7698,
"hiredate" : "1981-02-20",
"sal" : 1600.00,
"comm" : 300.00,
"deptno" : 30
},
{
"empno" : 7521,
"ename" : "WARD",
"job" : "SALESMAN",
"mgr" : 7698,
"hiredate" : "1981-02-22",
"sal" : 1250.00,
"comm" : 500.00,
"deptno" : 30
},
{
"empno" : 7566,
"ename" : "JONES",
"job" : "MANAGER",
"mgr" : 7839,
"hiredate" : "1981-04-02",
"sal" : 2975.00,
"comm" : null,
"deptno" : 20
},
{
"empno" : 7654,
"ename" : "MARTIN",
"job" : "SALESMAN",
"mgr" : 7698,
"hiredate" : "1981-09-28",
"sal" : 1250.00,
"comm" : 1400.00,
"deptno" : 30
},
{
"empno" : 7698,
"ename" : "BLAKE",
"job" : "MANAGER",
"mgr" : 7839,
"hiredate" : "1981-05-01",
"sal" : 2850.00,
"comm" : null,
"deptno" : 30
},
{
"empno" : 7782,
"ename" : "CLARK",
"job" : "MANAGER",
"mgr" : 7839,
"hiredate" : "1981-06-09",
"sal" : 2450.00,
"comm" : null,
"deptno" : 10
},
{
"empno" : 7788,
"ename" : "SCOTT",
"job" : "ANALYST",
"mgr" : 7566,
"hiredate" : "1987-04-19",
"sal" : 3000.00,
"comm" : null,
"deptno" : 20
},
{
"empno" : 7839,
"ename" : "KING",
"job" : "PRESIDENT",
"mgr" : null,
"hiredate" : "1981-11-17",
"sal" : 5000.00,
"comm" : null,
"deptno" : 10
},
{
"empno" : 7844,
"ename" : "TURNER",
"job" : "SALESMAN",
"mgr" : 7698,
"hiredate" : "1981-09-08",
"sal" : 1500.00,
"comm" : 0.00,
"deptno" : 30
},
{
"empno" : 7876,
"ename" : "ADAMS",
"job" : "CLERK",
"mgr" : 7788,
"hiredate" : "1987-05-23",
"sal" : 1100.00,
"comm" : null,
"deptno" : 20
},
{
"empno" : 7900,
"ename" : "JAMES",
"job" : "CLERK",
"mgr" : 7698,
"hiredate" : "1981-12-03",
"sal" : 950.00,
"comm" : null,
"deptno" : 30
},
{
"empno" : 7902,
"ename" : "FORD",
"job" : "ANALYST",
"mgr" : 7566,
"hiredate" : "1981-12-03",
"sal" : 3000.00,
"comm" : null,
"deptno" : 20
},
{
"empno" : 7934,
"ename" : "MILLER",
"job" : "CLERK",
"mgr" : 7782,
"hiredate" : "1982-01-23",
"sal" : 1300.00,
"comm" : null,
"deptno" : 10
}
]}
--- 변환 ---
{
"emp": {
"L": [
{
"M": {
"empno": {
"N": "7369"
},
"ename": {
"S": "SMITH"
},
"job": {
"S": "CLERK"
},
"mgr": {
"N": "7902"
},
"hiredate": {
"S": "1980-12-17"
},
"sal": {
"N": "800"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "20"
}
}
},
{
"M": {
"empno": {
"N": "7499"
},
"ename": {
"S": "ALLEN"
},
"job": {
"S": "SALESMAN"
},
"mgr": {
"N": "7698"
},
"hiredate": {
"S": "1981-02-20"
},
"sal": {
"N": "1600"
},
"comm": {
"N": "300"
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7521"
},
"ename": {
"S": "WARD"
},
"job": {
"S": "SALESMAN"
},
"mgr": {
"N": "7698"
},
"hiredate": {
"S": "1981-02-22"
},
"sal": {
"N": "1250"
},
"comm": {
"N": "500"
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7566"
},
"ename": {
"S": "JONES"
},
"job": {
"S": "MANAGER"
},
"mgr": {
"N": "7839"
},
"hiredate": {
"S": "1981-04-02"
},
"sal": {
"N": "2975"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "20"
}
}
},
{
"M": {
"empno": {
"N": "7654"
},
"ename": {
"S": "MARTIN"
},
"job": {
"S": "SALESMAN"
},
"mgr": {
"N": "7698"
},
"hiredate": {
"S": "1981-09-28"
},
"sal": {
"N": "1250"
},
"comm": {
"N": "1400"
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7698"
},
"ename": {
"S": "BLAKE"
},
"job": {
"S": "MANAGER"
},
"mgr": {
"N": "7839"
},
"hiredate": {
"S": "1981-05-01"
},
"sal": {
"N": "2850"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7782"
},
"ename": {
"S": "CLARK"
},
"job": {
"S": "MANAGER"
},
"mgr": {
"N": "7839"
},
"hiredate": {
"S": "1981-06-09"
},
"sal": {
"N": "2450"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "10"
}
}
},
{
"M": {
"empno": {
"N": "7788"
},
"ename": {
"S": "SCOTT"
},
"job": {
"S": "ANALYST"
},
"mgr": {
"N": "7566"
},
"hiredate": {
"S": "1987-04-19"
},
"sal": {
"N": "3000"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "20"
}
}
},
{
"M": {
"empno": {
"N": "7839"
},
"ename": {
"S": "KING"
},
"job": {
"S": "PRESIDENT"
},
"mgr": {
"NULL": true
},
"hiredate": {
"S": "1981-11-17"
},
"sal": {
"N": "5000"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "10"
}
}
},
{
"M": {
"empno": {
"N": "7844"
},
"ename": {
"S": "TURNER"
},
"job": {
"S": "SALESMAN"
},
"mgr": {
"N": "7698"
},
"hiredate": {
"S": "1981-09-08"
},
"sal": {
"N": "1500"
},
"comm": {
"N": "0"
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7876"
},
"ename": {
"S": "ADAMS"
},
"job": {
"S": "CLERK"
},
"mgr": {
"N": "7788"
},
"hiredate": {
"S": "1987-05-23"
},
"sal": {
"N": "1100"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "20"
}
}
},
{
"M": {
"empno": {
"N": "7900"
},
"ename": {
"S": "JAMES"
},
"job": {
"S": "CLERK"
},
"mgr": {
"N": "7698"
},
"hiredate": {
"S": "1981-12-03"
},
"sal": {
"N": "950"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "30"
}
}
},
{
"M": {
"empno": {
"N": "7902"
},
"ename": {
"S": "FORD"
},
"job": {
"S": "ANALYST"
},
"mgr": {
"N": "7566"
},
"hiredate": {
"S": "1981-12-03"
},
"sal": {
"N": "3000"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "20"
}
}
},
{
"M": {
"empno": {
"N": "7934"
},
"ename": {
"S": "MILLER"
},
"job": {
"S": "CLERK"
},
"mgr": {
"N": "7782"
},
"hiredate": {
"S": "1982-01-23"
},
"sal": {
"N": "1300"
},
"comm": {
"NULL": true
},
"deptno": {
"N": "10"
}
}
}
]
}
}
테이블 생성 메뉴얼
https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html
$aws dynamodb create-table \
--table-name anime12 \
--attribute-definitions AttributeName=title,AttributeType=S AttributeName=year,AttributeType=N \
--key-schema AttributeName=title,KeyType=HASH AttributeName=year,KeyType=RANGE \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
{
"TableDescription": {
"AttributeDefinitions": [
{
"AttributeName": "title",
"AttributeType": "S"
},
{
"AttributeName": "year",
"AttributeType": "N"
}
],
"TableName": "anime12",
"KeySchema": [
{
"AttributeName": "title",
"KeyType": "HASH"
},
{
"AttributeName": "year",
"KeyType": "RANGE"
}
],
"TableStatus": "CREATING",
"CreationDateTime": "2024-02-26T11:16:10.231000+09:00",
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 1,
"WriteCapacityUnits": 1
},
"TableSizeBytes": 0,
"ItemCount": 0,
"TableArn": "arn:aws:dynamodb:ap-northeast-2:646580111040:table/anime12",
"TableId": "07f41aff-21b8-4f6a-810d-750c1254907c",
"DeletionProtectionEnabled": false
}
}
- json 파일로 table 생성
$aws dynamodb create-table --cli-input-json file://create_table.json
# add_items.json
{
"anime12": [
{
"PutRequest": {
"Item": {
"title": {
"S": "initial d"
},
"year": {
"N": "1998"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "one punch man"
},
"year": {
"N": "2015"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "world trigger"
},
"year": {
"N": "2014"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "my hero academia"
},
"year": {
"N": "2016"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "naruto"
},
"year": {
"N": "2002"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "death note"
},
"year": {
"N": "2006"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "demon slayer"
},
"year": {
"N": "2019"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "kenshin"
},
"year": {
"N": "1996"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "black clover"
},
"year": {
"N": "2017"
}
}
}
},
{
"PutRequest": {
"Item": {
"title": {
"S": "hunter x hunter"
},
"year": {
"N": "2011"
}
}
}
}
]
}
$aws dynamodb batch-write-item --request-items file://add_items.json
batch-write-item을 통해 여러 아이템을 한 번에 쓸 수 있게 함.
여기서 중요한 점은 DynamoDB의 BatchWriteItem 작업은 최대 25개의 아이템까지만 지원한다는 것!!
따라서 넣을 아이템의 개수가 더 많은 경우에는 여러 번 호출하거나 다른 방법을 사용해야 한다
$aws dynamodb create-table \
--table-name emp12 \
--attribute-definitions AttributeName=empno,AttributeType=N \
--key-schema AttributeName=empno,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
emp12_put.json
{
"emp12": [
{
"PutRequest": {
"Item": {
"empno" : {"N" : "7369"},
"ename" : {"S": "SMITH"},
"job" : {"S": "CLERK"},
"mgr" : {"N": "7902"},
"hiredate" : {"S": "1980-12-17"},
"sal" : {"N": "800.00"},
"deptno" : {"N": "20"}
}
}
},
{
"PutRequest": {
"Item": {
"empno" : {"N": "7499"},
"ename" : {"S": "ALLEN"},
"job" : {"S": "SALESMAN"},
"mgr" : {"N": "7698"},
"hiredate" : {"S": "1981-02-20"},
"sal" : {"N": "1600.00"},
"comm" : {"N": "300.00"},
"deptno" : {"N": "30"}
}
}
}
]}
$aws dynamodb batch-write-item --request-items file://emp12_put.json
$aws dynamodb scan --table-name emp12
DynamoDB에서 테이블을 생성할 때는 두 가지 요소: 기본 키와 속성 정의.
-> AttributeDefinitions와 KeySchema에서 정의한 속성의 수가 일치해야함.
해시 키 (Hash Key)와 범위 키 (Range Key)는 테이블의 기본 키를 구성하는 두 가지 요소
해시 키 (Hash Key):
해시 키는 DynamoDB 테이블에서 각 항목을 식별하는 데 사용되는 기본 키의 첫 번째 요소입니다.
해시 키는 유일한 값을 생성하기 위해 해시 함수에 의해 계산됩니다.
DynamoDB 테이블은 해시 키만을 가지는 경우 단일 항목 테이블로 간주됩니다.
예를 들어, 테이블에 사용자 정보가 있다면 사용자의 고유 ID를 해시 키로 사용할 수 있습니다.
범위 키 (Range Key):
범위 키는 DynamoDB 테이블에서 각 항목을 더욱 세분화하여 식별하는 데 사용되는 기본 키의 두 번째 요소입니다.
범위 키는 해시 키와 결합하여 각 항목을 유일하게 식별합니다.
하나의 해시 키에 여러 범위 키 값을 가질 수 있습니다.
예를 들어, 사용자의 ID를 해시 키로 사용하고 해당 사용자의 주문 날짜를 범위 키로 사용하여 사용자의 주문을 저장할 수 있습니다.
-> 필요한 속성만을 정의하고 나머지 속성은 동적으로 추가