'Database/DynamoDB'에 해당하는 글 11건



DynamoDB SDK 는 대부분의 프로그래밍 언어를 제공하며, 이를 사용하여 프로젝트에 필요한 작업을 할 수 있다.

SDK 가 다음 기능을 제공하여 개발자의 코드 양을 엄청나게 줄여준다.


  • HTTP(S) 요청 서식 설정 및 요청 파라미터 직렬화.
  • 각 요청의 암호화 서명 생성.
  • 요청을 DynamoDB 엔드포인트에 전달하고 DynamoDB로부터 응답을 수신.
  • 이러한 응답에서 결과 추출.
  • 오류 발생 시 기본적 재시도 로직 구현.


AWS SDK는 DynamoDB 작업을 위한 3가지 프로그래밍 인터페이스를 제공한다.

사용 가능한 인터페이스는 사용하는 AWS SDK와 프로그래밍 언어에 따라 달라질 수 있다.



1. Low-Level Interfaces


SDK 는 Low-Level DynamoDB API 요청과 매우 비슷한 메서드를 사용하여, DynamoDB 용 Low-Level 인터페이스를 제공한다.

경우에 따라 문자열에 해당되는 S 또는 숫자에 해당되는 N 같은 Data Type Descriptors 를 사용하여 속성의 데이터 형식을 식별해야 한다.

DynamoDB Low-Level 인터페이스를 구현한 com.amazonaws.services.dynamodbv2.AmazonDynamoDB 클래스를 사용할 수 있다.



2. Document Interfaces


Java, .NET, Node.js, JavaScript 용 AWS SDK 는 Table 과 Index 에서 데이터 CRUD 를 수행할 수 있는 document 인터페이스를 제공한다.

document 인터페이스를 사용하면 Data Type Descriptors 를 사용할 필요가 없다.

이 document 인터페이스를 구현한 com.amazonaws.services.dynamodbv2.document.DynamoDB 클래스를 사용할 수 있다.

DynamoDB 는 Low-Level 클라이언트(AmazonDynamoDB) 의 래퍼 역할을 한다. (Low-Level 인터페이스를 사용하는 것보다 코드가 간결해진다.)


- Music Table 에서 특정 노래를 가져와 노래의 년도를 출력하는 예제)


package com.amazonaws.codesamples.gsg;
 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.GetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
 
public class MusicDocumentDemo {
 
    public static void main(String[] args) {
 
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
        DynamoDB docClient = new DynamoDB(client);
        
        Table table = docClient.getTable("Music");
        GetItemOutcome outcome = table.getItemOutcome(
                "Artist""No One You Know"
                "SongTitle""Call Me Today");
 
        int year = outcome.getItem().getInt("Year");
        System.out.println("The song was released in " + year);
       
    }
}
cs



3. Object Persistence Interfaces


DynamoDB Table 과 Index 의 Item 을 나타내는 객체를 생성해 이 객체들과만 상호 작용하여, 객체 중심 코드를 만들 수 있다.

이를 활용하면, DynamoDB 테이블로 클라이언트 측 클래스를 매핑할 수가 있다.

Object Persistence 인터페이스를 구현한 com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper 클래스를 사용할 수 있다.

DynamoDBMapper 도 Low-Level 클라이언트(AmazonDynamoDB) 의 래퍼 역할을 한다.

이 인터페이스는 Java, .NET 용 AWS SDK 만 제공한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



DynamoDB Low-Level API 는 실제 DynamoDB 에 요청하는 마지막 단계 인터페이스로, 이 HTTP(S) 요청은 올바른 형식이어야 한다.


  • HTTP(S) 요청은 POST 방식이어야 한다.
  • Authorization 헤더에는 DynamoDB 가 요청을 인증하는 데 필요한 정보가 포함되어야 한다.
  • X-Amz-Target 헤더에는 DynamoDB 작업의 이름(GetItem, PutItem 등...) 이 포함되어야 한다.
  • 요청 본문은 JSON 형식이어야 한다.


응답도 JSON 형식으로 반환된다.

DynamoDB 가 요청을 처리할 수 없는 경우, HTTP 오류 코드와 메시지를 반환하므로 오류 처리를 해주면 된다.

이런 요청과 응답 모두 AWS SDK 가 구성하므로 개발자는 어플리케이션 로직에만 집중하면 된다.



Pets Table 에서 특정 키의 Item 을 GetItem 으로 읽어오는 요청 예)


POST / HTTP/1.1
Host: dynamodb.<region>.<domain>;
Accept-Encoding: identity
Content-Length: <PayloadSizeBytes>     
User-Agent: <UserAgentString>
Content-Type: application/x-amz-json-1.0
Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>, Signature=<Signature>
X-Amz-Date: <Date
X-Amz-Target: DynamoDB_20120810.GetItem
 
{
    "TableName": "Pets",
    "Key": {
        "AnimalType": {"S": "Dog"},
        "Name": {"S": "Fido"}
    }
}
cs



Data Type Descriptors


요청/응답 JSON 데이터에는 각 Attribute 의 데이터 타입 서술자(Data Type Descriptors) 를 포함시켜야 한다.

String (S), Number (N), Binary (B), Boolean (BOOL), Null (NULL), Map (M), List (L), String Set (SS), Number Set (NS), Binary Set (BS)


특히, JSON 으로 요청할 때 int, long, double 같은 숫자 형식은 DynamoDB 의 데이터 타입에 정확히 매핑하기 위해 숫자값을 문자열로 변환해야 한다.

binary 데이터를 DynamoDB 로 보내려면 Base64 형식으로 인코딩해야 한다. (DynamoDB 는 요청을 받아 Base64 를 다시 binary 로 디코딩한다.)


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

데이터 쓰기


{
    TableName: "Music",
    Item: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today",
        "AlbumTitle":"Somewhat Famous",
        "Year"2015,
        "Price"2.14,
        "Genre""Country",
        "Tags": {
            "Composers": [
                  "Smith",
                  "Jones",
                  "Davis"
            ],
            "LengthInSeconds"214
        }
    }
}
cs


SQL 의 INSERT INTO 와 같은 역할이다.

Item 을 추가하려면 PutItem 작업에 위와 같은 파라미터를 전달한다.

복수의 데이터를 BatchWriteItem 작업으로 한번에 추가하는 것도 가능하다.


  • TableName – 데이터를 추가할 Table 이름.
  • Item - Primary Key 이외의 Attribute 는 데이터 타입과 함께 자동 생성된다.



데이터 읽기


{
    TableName: "Music",
    Key: {
        "Artist""No One You Know",
        "SongTitle""Call Me Today"
    },
    "ProjectionExpression""AlbumTitle, Year, Price"
}
cs


단일 Item 을 읽기 위해 GetItem 작업에 Table 이름과 Primary Key 를 전달한다.

기본적으로 해당 Item 의 모든 Attributes 를 가져오지만 ProjectionExpression 파라미터로 특정 Attributes 만 반환할 수 있다.


{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a and contains(SongTitle, :t)",
    FilterExpression: "price < :p",
    ExpressionAttributeValues: {
        ":a""No One You Know",
        ":t""Today",
        ":p"1.00
    }
}
cs


Query 작업으로 조건을 지정하여 여러 Item 을 읽을 수도 있다.

KeyConditionExpression 에 Primary key 를 지정하고 (sort key 에 범위 지정 가능),

ExpressionAttributeValues 는 Expression 파라미터들에 바인드 변수를 사용하여 값을 전달한다.

FilterExpression 으로 조건을 지정하여 일부 Items 을 결과에서 제거할 수 있다.


{
    TableName:  "Music",
    ProjectionExpression: "Artist, Title"
}
cs


Scan 작업으로 Table 의 전에 Item 을 읽거나 ProjectionExpression 에 Attribute 는 지정하여, 결과에서 제외시킬 수 있다.


Index 에 대하여 Query 나 Scan 을 할 경우에는 IndexName 파라미터만 추가하면 된다.



데이터 수정


{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ConditionExpression: "Price >= :p",
    ExpressionAttributeValues: { 
        ":label""Global Records",
        ":p"2.00
    }
}
cs


위와 같이 UpdateItem 작업에 파라미터를 전달하여 단일 Attribute 를 수정할 수 있다.

UpdateItem 은 개별 Attribute 를 교체하는 것이 아니라 Item 전체를 교체한다.

해당하는 Primary key 가 존재하면 Attribute 를 업데이트 하고, 존재하지 않으면 이 Item 을 추가한다.

ConditionExpression 에 조건을 설정하여 true 일 때만 수정을 수행하도록 할 수도 있다.


또 Number 데이터 타입의 Attribute 에서 숫자 증감도 지원한다.


{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = Plays + :incr",
    ExpressionAttributeValues: { 
        ":incr"1
    },
    ReturnValues: "UPDATED_NEW"
}
cs


위 예에서 ReturnValues 파라미터의 UPDATED_NEW 는 업데이트된 Attribute 의 새 값을 반환한다.



데이터 삭제


{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band"
        SongTitle: "Look Out, World"
    },
   ConditionExpression: "attribute_exists(RecordLabel)"
}
cs


DeleteItem 작업에 TableName 과 Primary key 를 지정하면 해당 데이터를 삭제한다.

ConditionExpression 에 조건을 설정하여 true 일 때만 삭제를 수행하도록 할 수도 있다.

복수의 Items 를 동시에 삭제하는 BatchWriteItem 작업을 지원한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Table 생성


{
    TableName : "Music",
    KeySchema: [       
        { 
            AttributeName: "Artist"
            KeyType: "HASH"//Partition key
        },
        { 
            AttributeName: "SongTitle"
            KeyType: "RANGE" //Sort key
        }
    ],
    AttributeDefinitions: [
        { 
            AttributeName: "Artist"
            AttributeType: "S" 
        },
        { 
            AttributeName: "SongTitle"
            AttributeType: "S" 
        }
    ],
    ProvisionedThroughput: {       
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
    }
}
cs



SQL 의 CREATE TABLE 과 같은 역할이다.

Table 을 생성하려면 다음 파라미터를 CreateTable 작업에 전달해야 한다.


  • TableName – Table 이름.
  • KeySchema – Primary Key 에 사용되는 Attribute.
  • AttributeDefinitions – Primary Key 의 데이터 형식.
  • ProvisionedThroughput – RCU / WCU 설정.



Table 읽기/삭제


DescribeTable 작업에 TableName 을 전달하여 위처럼 Table 정보를 읽어올 수 있다.

DeleteTable 작업에 TableName 을 전달하여 Table 을 삭제할 수 있다.



Table 수정


{
    TableName: "Music",
    AttributeDefinitions:[
        {AttributeName: "Genre", AttributeType: "S"},
        {AttributeName: "Price", AttributeType: "N"}
    ],
    GlobalSecondaryIndexUpdates: [
        {
            Create: {
                IndexName: "GenreAndPriceIndex",
                KeySchema: [
                    {AttributeName: "Genre", KeyType: "HASH"}, //Partition key
                    {AttributeName: "Price", KeyType: "RANGE"}, //Sort key
                ],
                Projection: {
                    "ProjectionType""ALL"
                },
                ProvisionedThroughput: {
                    "ReadCapacityUnits"1,"WriteCapacityUnits"1
                }
            }
        }
    ]
}
cs


UpdateTable 작업으로 Secondary Index 를 추가할 수도 있다.


  • TableName – Index 가 연동될 Table 이름.
  • AttributeDefinitions – Index 와 데이터 형식.
  • GlobalSecondaryIndexUpdates – 생성하려는 Index 의 세부 사항.
  • IndexName – Index 이름.
  • KeySchema – Index Primary Key 에 사용되는 Attribute.
  • Projection – Table 에서 Index 로 복사될 Attribute.
  • ProvisionedThroughput – Index 의 RCU / WCU 설정




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



DynamoDB 는 데이터를 파티션에 저장한다. 파티션은 SSD(Solid State Drive) 에 저장되는 테이블용 스토리지이다.

DynamoDB 는 기존 파티션이 한도를 초과하거나, Table 의 프로비저닝된 처리량 설정이 늘어나는 경우 자동으로 추가 파티션을 할당한다.

파티션 관리는 백그라운드에서 자동으로 이루어지므로 어플리케이션에는 표시되지 않는다.

DynamoDB 의 GSI(Global secondary index) 도 파티션으로 구성되며, 기본 테이블의 데이터와 별도로 저장된다.



Data Distribution 


  • Partition key
    Table 이 Primary Key 로 Partition key 만 가질 경우, Partition key 값을 기준으로 각 Item 을 저장하고 검색한다.
    DynamoDB 는 해시 함수로 이 Partiiton key 값을 처리하여 저장할 파티션을 결정한다.
    DynamoDB 는 파티션 수와 상관없이 Item 을 Table 의 파티션에 균일하게 분배하는 데 최적화되어 있다. 
    Table 의 Items 수에 비해 많은 수의 고유 값을 가질 수 있는 Attribute 를 Partition key 로 선택할 것을 권장한다.

  • Partition key & sort key
    Table 이 Partition key & sort key 를 가질 경우, Partition key 방식과 동일하게 파티션 키의 해시 값을 계산하지만, 
    Partition key 값이 동일한 모든 Items 를 sort key 값을 기준으로 정렬하여 물리적으로 인접하게 저장한다.
    Query 작업으로 Partition key 만 지정하면 해당하는 모든 Partition key 값을 가진 item 목록을 sort key 기준 오름차순으로 반환한다. (내림차순 요청 가능)
    sort key 에 조건을 적용하면 결과의 일부만 읽을 수도 있다.



Partition key 의 설정


다시 한번 얘기하는데, 설정한 처리량을 완전히 활용하려면 Item 이 파티션마다 골고루 분포되어야 하며, 그러려면 Partition key 는 무조건 유일해야 한다.

Partition key & sort key 로 Partition key 가 중복을 허용하는 경우라면, 이 Attributes 들을 Index 로 놓고 Table Partition key 를 유일한 Attributes 로 새로 생성해야 한다.

가장 흔히 사용하는 것이 Partition key 와 sort key 를 조합하는 것이다.

각각 userNo regDate 를 Index 로 생각했다면, userNo_regDate 를 유일한 Table Partition key 로 만들 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,