본문 바로가기

Previous (20-22)/Development

AWS DynamoDB in Python (Boto3) - #3. 항목 관리

이번 글에서는 Amazon Web Service(AWS) 에서 DynamoDB를 사용하는 방법을 Python을 이용해서 다루도록 하겠습니다.

처음에 AWS Python 카테고리에서 DynamoDB를 다루고자 했던 것은 아니였지만, 이번 회사에서 기술보고서를 작성하는 과정에 있어서 주제를 DynamoDB를 하다 보니까 블로그에도 같이 다루는 것이 좋을 것 같아서 올려봅니다.


2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #1. 소개

2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #2. 테이블 관리


이번 글은 지난 글에 이어서 AWS SDK for Python인 Boto3 를 사용한 DynamoDB의 항목(Items) 관리에 대해서 다루어보도록 하겠습니다.

모든 내용은 AWS의 Boto3 Documentation에 있는 내용이며, 번역자료가 없기 때문에 제가 직접 실습하면서 나타내도록 하겠습니다.


원본 문서: http://boto3.readthedocs.io/en/latest/guide/


영어 문서이므로 참고하시기 바랍니다.


먼저 항목(Items)이 무엇인지에 대해서 간단히 언급하겠습니다.

항목이란 쉽게 말해서, 데이터 값입니다.

RDBMS에서는 레코드(Record) 또는 행(Row)이라고도 하는데, DynamoDB는 NoSQL의 특성에 맞게 항목(Items)으로 나타납니다.

이 점을 참고하시면 될 것으로 생각됩니다.


이 게시물에 있는 모든 예제는 users Table에서 이루어집니다.

users Table의 기본 키(Primary Key)는 username(Partition Key)과 last_name(Sort Key)로 구성되어 있으니 이 점 반드시 참고 바랍니다.


1. 기본 데이터 처리 - CRUD

DB를 하시는 분은 CRUD가 무엇인지 정도는 다 알 것입니다. 

RDBMS에서는 SQL에서 Insert / Select / Update / Delete의 기능으로도 볼 수 있겠고요.


DynamoDB의 항목 생성/호출/갱신/삭제 또한 마찬가지입니다.


1) 생성

table.put_item(

   Item={

        'username': 'janedoe',

        'first_name': 'Jane',

        'last_name': 'Doe',

        'age': 25,

        'account_type': 'standard_user',

    }

)


생성은 put_item 을 사용하여 입력이 이루어집니다.

위에 언급했다 시피, username과 last_name 속성은 기본 키이므로, first_name, age, account_type은 추가 속성으로 자유롭게 입력된 것을 확인할 수 있습니다.

결과는 다음과 같습니다.


2) 호출

일반적으로 호출이라 함은 SQL에서 select에 해당되는 부분으로 볼 수 있습니다.

하지만 실제 자세한 호출은 아래에서 상세히 다룰 예정이며, 지금 예제는 하나의 값을 단순히 불러오는 예제로 보시면 되겠습니다.

response = table.get_item(

    Key={

        'username': 'janedoe',

        'last_name': 'Doe'

    }

)

item = response['Item']

print(item)

 

위 예제와 같이, 기본 키를 입력해서 해당 키의 값을 불러오는 과정으로, 커맨드 창에서 파이썬을 실행한 결과는 다음과 같습니다.


3) 갱신

갱신은 특정 값을 변경하는 것이므로, 변경 대상 항목과 변경될 값을 입력하면 됩니다.

table.update_item(

    Key={

        'username': 'janedoe',

        'last_name': 'Doe'

    },

    UpdateExpression='SET age = :val1',

    ExpressionAttributeValues={

        ':val1': 26

    }

)

예제에서와 같이, 변경 대상 항목 지정을 위한 Key를 입력하고, UpdateExpression을 통해서 대상 속성의 값을 지정합니다.

그리고 ExpressionAttributeValues를 통해서 특정 값에 대한 변수 값을 입력합니다.

AWS Console에서의 갱신 결과는 아래와 같습니다.


4) 삭제

삭제는 기본 키를 조건으로 지정하면 즉시 삭제가 가능합니다.

table.delete_item(
    Key={
        'username': 'janedoe',
        'last_name': 'Doe'
    }
)

결과는 아래와 같습니다.

AWS Console에서 아무 항목도 없는 것으로 확인될 것입니다.



사실 여기까지는 너무 기본적인 내용입니다.

이제 DynamoDB에서 활용하는 데이터 관리에 대해서 좀 더 알아보도록 하겠습니다.



2. Batch Writing

DynamoDB에서는 대용량의 데이터를 입력할 때, Batch Writing기능을 사용하여 속도를 향상시키고, 요청에 필요할 수를 줄일 수 있습니다. 이 기능은 항목(Item)을 Batch 순서에 의해서 자동으로 조절할 수 있으며, 데이터 전송이 이루어지지 않을 때에 재전송 기능도 수행하도록 되어 있습니다.다.

데이터 추가는 put_item 명령어를 사용하는 것을 기본으로 하며, 반대로 삭제는 delete_item 명령어를 사용하는 것을 기본 명령어로 수행합니다.


라고 제 요량대로 번역해본 것입니다. 원문은 아래와 같습니다.

출처: 맨 위의 Boto3 Documentation


If you are loading a lot of data at a time, you can make use of DynamoDB.Table.batch_writer() so you can both speed up the process and reduce the number of write requests made to the service.

This method returns a handle to a batch writer object that will automatically handle buffering and sending items in batches. In addition, the batch writer will also automatically handle any unprocessed items and resend them as needed. All you need to do is call put_item for any items you want to add, and delete_itemfor any items you want to delete:

 


위의 기본 데이터 처리는 하나의 값을 넣는 형태로 이루어지지만, 대용량으로 한꺼번에 입력이 필요할 때, 이에 대한 속도 처리를 위한 명령어를 Boto3에서 제공한다고 보시면 간단히 이해가 될 것입니다.

일단 Batch Writing을 사용하여 여러 개의 데이터를 입력하는 예제부터 보여드리겠습니다.


with table.batch_writer() as batch:

    batch.put_item(

        Item={

            'account_type': 'standard_user',

            'username': 'johndoe',

            'first_name': 'John',

            'last_name': 'Doe',

            'age': 25,

            'address': {

                'road': '1 Jefferson Street',

                'city': 'Los Angeles',

                'state': 'CA',

                'zipcode': 90001

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'super_user',

            'username': 'janedoering',

            'first_name': 'Jane',

            'last_name': 'Doering',

            'age': 40,

            'address': {

                'road': '2 Washington Avenue',

                'city': 'Seattle',

                'state': 'WA',

                'zipcode': 98109

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'standard_user',

            'username': 'bobsmith',

            'first_name': 'Bob',

            'last_name':  'Smith',

            'age': 18,

            'address': {

                'road': '3 Madison Lane',

                'city': 'Louisville',

                'state': 'KY',

                'zipcode': 40213

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'super_user',

            'username': 'alicedoe',

            'first_name': 'Alice',

            'last_name': 'Doe',

            'age': 27,

            'address': {

                'road': '1 Jefferson Street',

                'city': 'Los Angeles',

                'state': 'CA',

                'zipcode': 90001

            }

        }

    )

batch_writer를 사용하여 여러 개의 값을 입력하는 형태입니다.

4개의 값이 순차적으로 입력된 것을 확인할 수 있습니다.


다음은 for 반복문을 이용한 입력 결과입니다.

with table.batch_writer() as batch:

    for i in range(50):

        batch.put_item(

            Item={

                'account_type': 'anonymous',

                'username': 'user' + str(i),

                'first_name': 'unknown',

                'last_name': 'unknown'

            }

        )

순서는 좀 뒤죽박죽인 것 같습니다.


다음은 기본 키를 사용한 예제입니다.

with table.batch_writer(overwrite_by_pkeys=['username', 'last_name']) as batch:

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's1',

            'other': '111',

        }

    )

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's1',

            'other': '222',

        }

    )

    batch.delete_item(

        Key={

            'username': 'p1',

            'last_name': 's2'

        }

    )

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's2',

            'other': '444',

        }

    )

다른 예제와는 다르게, 상단에 overwrite by pkeys = [‘username’,’last_name’] 구문이 들어가 있는 것을 확인할 수 있을 것입니다.

여기에서의 pkeys는 기본키가 들어가며, 파티션 키, 정렬 키의 값이 들어갑니다.


위 예제에서는 [p1, s1, 111], [p1, s1, 222] 값을 입력한 후, [p1, s2] 키 값을 삭제하고 [p1, s2, 444] 값을 입력하는 순서로 되어 있습니다.

하지만 여기서 생각을 해야 할 것이 있습니다.


기본 키가 같을 경우, 세부 속성이 다르더라도 중복된 값이 들어가면 안됩니다.


그러므로 batch.put_item을 일반적으로 썼더라면 에러가 발생할 수 있습니다.

하지만 실제 결과는 다음과 같습니다.

[p1, s1, 222]와 [p1, s2, 444] 2개만 들어간 것을 확인할 수 있습니다.

어떻게 된 것일까요.


이는 batch_writer에서 overwrite by pkeys를 지정했기 때문에 오류가 발생하지 않는 것입니다.

만약에 같은 기본키에 값이 또 들어올 경우에는 overwrite를 해서 먼저 입력된 값을 덮어 씌우라는 뜻이였으므로,

[p1, s1, 111] 의 값이 이미 기본키로 들어가 있었지만, 그 후에 [p1, s1, 222]의 값으로 대체가 된 것으로 보시면 됩니다.


Batch Writer를 통한 입력/삭제는 위와 같이 활용하면 대용량 데이터 입력 시에도 원하는 형태로의 코드 작성이 가능할 것으로 생각됩니다.


다음은 마지막으로 실제 항목, 즉 데이터 호출을 위한 Query & Scan에 대해서 알아보도록 하겠습니다.