[こんなデータも簡単にコピーできるの?!]Amazon DynamoDBテーブル作成してRedshiftにCOPYしてみた

もう私!! AmazonDynamoDBにテーブル作成してRedshiftにCOPYできない人生なんて考えられない!!
2020.12.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

DA事業本部での研修として最後のプレゼンを終えました、新卒エンジニアのたいがーです?

AWS LambdaでDynamoDBにデータを入れたけど、データウェアハウスとしてAmazon Redshiftにデータを置きたい!Amazon DynamoDBに入れたデータに対して複雑なSQL関数を使いまくりたい!という時ありますよね!そんな時、RedshiftでCOPYコマンドを実行することで解決できます。

データウェアハウスってなんだ?という方は、是非こちらの動画をご覧ください!

今回は初めにDevelopers.IOのRSSフィードを使用して、DynamoDBのテーブルを作成します。次にCOPYコマンドを使って、DynamoDBテーブルからRedshiftにデータをロードしてみたいと思います。

開発環境

  • boto3 v1.16.37
  • Python v3.8.2

事前準備

DynamoDBテーブルの作成

まず初めにDynamoDBテーブルを作成します。

  • Title
    • パーティションキー
  • Author
    • ソートキー
  • URL
  • Tags

DynamoDBテーブルの作成

import boto3
import feedparser

client = boto3.client('dynamodb')


def put_tag():
    create_table()
    waiter = client.get_waiter('table_exists')
    waiter.wait(TableName='cm-tiger-DevIO')
    put_items()


def put_items():
    dev_io = feedparser.parse('https://dev.classmethod.jp/feed/')
    entries = dev_io['entries']
    try:
        resource = boto3.resource('dynamodb')
        table = resource.Table('cm-tiger-DevIO')
        with table.batch_writer() as batch:
            for entry in entries:
                batch.put_item(
                    Item={
                        'Title': entry['title'],
                        'Author': entry['author'],
                        'URL': entry['link'],
                        'Tags': entry['tags'][-1]['term'] if 'tags' in entry else ''
                    }
                )
    except Exception as error:
        print(error)


def create_table():
    client.create_table(
        TableName='cm-tiger-DevIO',
        AttributeDefinitions=[
            {
                'AttributeName': 'Title',
                'AttributeType': 'S'
            },
            {
                'AttributeName': 'Author',
                'AttributeType': 'S'
            }
        ],
        BillingMode='PAY_PER_REQUEST',
        KeySchema=[
            {
                'AttributeName': 'Title',
                'KeyType': 'HASH'
            },
            {
                'AttributeName': 'Author',
                'KeyType': 'RANGE'
            },
        ]
    )


put_tag()

実行結果

続いてCOPYコマンドで使用するIAMロールを作成していきます。

IAMロールの作成

IAMロール(cm-tiger-copy-redshift)を作成し、IAMポリシーはこちらの2つを付与します。

  • AmazonRedshiftQueryEditor
  • AmazonDynamoDBReadOnlyAccess

作成したIAMロールをRedshiftクラスターのプロパティからアクセス許可します。

RedshiftのクラスターにIAMロールのアクセスを許可する

Redshiftのクラスターのプロパティ設定からIAMロールの管理を選択し、IAMロールを追加します。実際にCOPYコマンドを実行していきたいと思います。状態がin-syncになっていることを確認してください。

クエリエディタを使用してDynamoDBからRedshiftにロードする

今回は、クエリエディタを使用してクエリを実行していきたいと思います。

テーブルを作成する

まず、Redshift内のデータベースにテーブルを作成します。このとき、Redshiftのデータベース内に作成するテーブルのカラム名はDynamoDBテーブルの属性名と同じにする必要があります。

テーブルの作成(1)

create table public.cm_tiger_DevIO_Title (Title varchar(max), Author varchar(max), URL varchar(max), Tags varchar(max));

次に、 Dynamo DBとIAM ロールを指定し、Redshiftのテーブルにコピーします。

DynamoDBテーブルからRedshiftにCOPYする

copy public.cm_tiger_DevIO_list
from 'dynamodb://cm-tiger-DevIO-List'
iam_role 'arn:aws:iam::XXXXXXXXXXX:role/cm-tiger-copy-redshift'
readratio 50;

テーブルの表示(1)

select * from public.cm_tiger_DevIO_list

COPYコマンドを使用する時、DynamoDBのテーブルの一部のみをロードすることも可能です。

テーブル作成時にカラム名を変えると一部だけ取り出すことができる

テーブル作成時でDynamoDBで作成した属性の一部を指定すると、COPY時にそのカラムのみをコピーすることが可能です。

テーブルの作成(2)

create table public.cm_tiger_DevIO_Title (Title varchar(max), Author varchar(max), URL varchar(max), Tags varchar(max));

DynamoDBテーブルからRedshiftにCOPYする

copy public.cm_tiger_DevIO_list
from 'dynamodb://cm-tiger-DevIO-Title'
iam_role 'arn:aws:iam::XXXXXXXXXXX:role/cm-tiger-copy-redshift'
readratio 50;

テーブルの表示(2)

select * from public.cm_tiger_DevIO_Title

このように、テーブル作成時にRedshiftに格納するデータを指定することが可能です。

COPY実行時のDynamoDBの読み込みCapacity

今回クエリで返された値は22件で、このようなCapacityになりました。

とても便利なCOPYコマンド

テーブル作成時にカラムを指定するだけで指定した属性をコピーしてくれるのはとても便利ですよね!是非みなさんも試してみて下さい。

以上、たいがーでした?

参考資料