DynamoDB의 구성 요소
DynamoDB는 AWS에서 제공하는 NoSql database 서비스이다.
- 테이블 : 데이터의 집합
- 항목 : 테이블이 갖는 row들
- 속성 : 각 항목은 하나 이상의 속성들로 구성된다.
People이라는 테이블을 보면 PersonID라는 파티션 키 기준으로 항목들이 구성되어있다. 또한 각 항목들은 하나 이상의 속성들을 갖는다(PersonID, LastName, FirstName..).
DynamoDB는 Json 파일로 저장된다. key-value형식이기 때문에 READ가 빠르다. 또한 NoSql답게 속성에 대한 확장성이 좋다. 다만 단점은 relation이 없기 때문에 update작업을 해야할 경우 여러 컬렉션에 중복되어 들어가 있을 칼럼들을 모두 작업해주어야 한다는 점과 ㅜNoSql 특성상 Transaction이 없기 때문에 전략적인 사용이 요구된다는 점이다.
기본 키(Hash Key, Sort Key)
- dynamoDB에서는 테이블마다 기본키를 가지고 있으며 기본키는 파티션 키와 정렬 키로 구성된다.
- 파티션키는 rdbms에 빗대어 설명하자면 일종의 PK와 같은 키이다. 파티션 키에 따라 데이터 항목을 고르게 분산하기 위해 dynamoDB 내부의 해시함수를 사용하기 때문에 Hash Key라고도 한다.
- 정렬 키는 DynamoDB의 파티션 키가 정렬 키 값을 기준으로 물리적으로 가깝게 저장한다.
- 기본 키의 데이터 형식은 문자열, 숫자, 이진수만 가질 수 있다. 그 외의 키에는 형식 제한 없다.
보조 인덱스(GSI, LSI)
- 테이블 당 하나 이상의 보조인덱스를 가질 수 있다.
- Global Secondary Index : 인덱스의 키 스키마가 기본 테이블의 기본키와 다를 수 있다.
- Local Secondary Index : 기본 테이블과 파티션 키가 동일하지만 정렬 키가 다름
- 테이블당 GSI는 20개, LSI는 5개의 기본 할당량을 가진다.
- 기본 테이블에서 조회하고자 하는 조건으로 보조인덱스가 설계되어있는 것이 좋다.
- LSI는 테이블이 생성될때가 아니면 추가로 생성할 수 없다.
- GSI는 테이블이 생성되고 난 뒤에도 얼마든지 추가할 수 있다.
- GSI는 새로운 테이블이 추가되는 개념이다. 때문에 LSI와는 달리 기본 테이블과는 별도로 과금된다.
DynamoDB Query vs Scan
dynamoDBdml Read 연산은 scan, query 두 가지로 나뉜다.
Scan
- 전체 테이블 or 인덱스 풀스캔 → 당연히 읽어올 데이터가 클수록 작업 속도가 느려진다.
- 가능하면 Scan을 피할 수 있도록 어플리케이션을 설계하는 것이 좋다.
- 참고로 소수의 결과만 반환하더라도 scan에 대한 요금이 청구된다.
- Scan은 기본적으로 순차적으로 작업된다. 허나 빠른 성능을 위해서 병렬 스캔을 활용하면 빠르게 조회할 수 있다.
- FilterExpression을 사용해 필터링한 항목을 반환할 수 있다. (하나 풀 스캔인 것은 변함이 없다.)
Example for Java) DisplayYN = Y 인 항목 조회
// 디스플레이된 음반 목록 조회
public ScanResultPage<ItemHome> getMusicListByDisplayYn(Map<String, AttributeValue> lastEvaluatedKey, int limit) {
String indexName = "musicId-createdAt-index";
HashMap<String, AttributeValue> attributeValues = new HashMap<>();
attributeValues.put(":displayYN", new AttributeValue().withS("Y"));
DynamoDBScanExpression scanExpression =
new DynamoDBScanExpression()
.withIndexName(indexName)
.withFilterExpression("displayYN = :displayYn")
.withExpressionAttributeValues(attributeValues)
.withLimit(limit)
.withExclusiveStartKey(lastEvaluatedKey);
ScanResultPage<ItemHome> results = mapper.scanPage(Music.class, scanExpression);
return results;
}
Query
- 파티션 키가 있는 항목을 모두 가져와서 키 정렬. 파티션 키로 조회하기 때문에 빠르고 효율적이다.
- 파티션 키의 조건은 EQ만 걸 수 있다.
- KeyConditionExpression 파라미터가 꼭 있어야 한다.
- Query할 때 기본 키 외의 옵셔널 하게 조건을 걸 때는 FilterExpression 파라미터를 사용한다.
- 항상 정렬 키 값으로 정렬되며 기본적으로 오름차순 정렬이다. 정렬 키 순서를 변경하고 싶으면 ScanIndexFoward 파라미터를 사용하면 된다.
Example for Java) DispalyYN = Y, version = v1인 항목을 조회한다.
위의 scan 예제와는 다르게 조회하려는 displayYN값으로 파티션 키가 존재한다.
public QueryResultPage<Music> getMusicListByDisplayYn(Map<String, AttributeValue> lastEvaluatedKey, int limit) {
String indexName = "displayYn-createdAt-index";
HashMap<String, AttributeValue> eav = new HashMap<>();
eav.put(":displayYn", new AttributeValue().withS("Y"));
eav.put(":version", new AttributeValue().withS("v1"));
String keyConditionExpression = "displayYn = :displayYn";
String filterConditionExpression = "version = :version";
// hash key, 다른 필드로 조회하기 때문에 query +filterExpression 사용
DynamoDBQueryExpression<Music> queryExpression =
new DynamoDBQueryExpression<Music>()
.withKeyConditionExpression(keyConditionExpression)
.withFilterExpression(filterConditionExpression)
.withIndexName(indexName)
.withExpressionAttributeValues(eav)
.withConsistentRead(false)
.withScanIndexForward(false)
.withLimit(limit)
.withExclusiveStartKey(lastEvaluatedKey);
QueryResultPage<Music> results = mapper.queryPage(Music.class, queryExpression);
return results;
}
Common
- 기본적으로 데이터를 조회한 후에 filtering이 된다는 것을 염두에 두자.
- 데이터가 조회되면 가장 마지막 데이터의 키 스키마가 LastEvaluatedKey에 저장되고 이를 기준으로 다음 페이지가 조회된다.
- FilterExpression에는 파티션 키와 정렬키로 조건을 걸 수 없다. KeyConditionsExpression으로만 넘겨야 함.
- LastEvaluatedKey가 null값이라면 다음에 조회할 데이터 항목들이 없다는 것을 의미한다.
느낀 점
- RDB처럼 다양한 조회 조건을 날릴 수가 없다. 때문에 애초부터 테이블 설계를 잘해야 함.
- 아무리 처음부터 설계를 잘한다고 하더라도 기능이 추가되거나 변경될 경우 추가적으로 복잡해지기 마련인데 이러한 점을 고려할 때 조금 머리 아파진다. 전략적 사용이 요구됨.
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#query-property
'Dev > AWS' 카테고리의 다른 글
ECS(Elastic Container Service) 기본 개념 (0) | 2022.08.28 |
---|---|
Travis CI,CodeDeploy,S3,Nginx로 EC2에 무중단 배포하기(3) - Nginx로 무중단 배포 하기 (0) | 2022.04.11 |
Travis CI,CodeDeploy,S3,Nginx로 EC2에 무중단 배포하기(2) - Travis CI,S3,CodeDeploy 연동 (0) | 2022.04.06 |
Travis CI,CodeDeploy,S3,Nginx로 EC2에 무중단 배포하기(1) - Travis CI,S3 연동 (0) | 2022.04.05 |
[AWS] CloudWatch를 활용한 docker 이미지 로그 관리하기 (1) | 2022.03.06 |
댓글