Amazon Redshiftではじめるビッグデータ処理入門

第4回 Amazon Redshiftにデータをロードしてみよう

この記事を読むのに必要な時間:およそ 4 分

前回は,Amazon Redshiftの起動から,ローカルマシンでAmazon Redshiftクラスタへ接続するまでの説明を行いました。今回は,Amazon Redshiftを実際に運用する上で重要となるデータのロードを中心に,例を交えて説明していきます。なお,チュートリアルの中で利用するデータはAmazon Redshift Getting Started Guideで紹介されているデータを利用しています。

本連載のチュートリアルは,AWSアカウント,起動中のAmazon Redshiftクラスタ,また接続するクライアントツールがすでに準備されていることを前提としています)⁠実際に試される方は,前回の記事を参考に環境準備をしておいてください。

※)
Hapyrusでは,RedshiftとFlyDataをお試しいただけるSandbox環境を無料で提供しています。また,ブラウザ上からRedshiftに対してSQLが実行できる機能もありますので,無料のRedshift環境にご興味のある方はぜひこちらからのご登録をおすすめします。

テーブルの作成

データのロードの前に,まずテーブルを作成する必要があります。Amazon Redshift Getting Started Guide - Step5に記載されているCREATE文(users, venue, category, date)全てをコピーし,SQLをRedshiftクラスタ上で実行してみましょう図1)⁠

図1 テーブルの作成

図1 テーブルの作成

これらのCREATE文は,MySQLやPostgreSQL上での実行するものと特段変わりませんが,distkey, sortkeyといった見慣れないキーワードがあることに気づくでしょう。これらは,設定したカラムのデータをどのようにRedshiftクラスタ上に配置するか,その配置方法について示すもので,データをロードした後のSELECTクエリを発行する際のパフォーマンスに大きく影響します。

デフォルトでは,Redshiftはクラスタの全ノードに均等にデータが分散されるようにデータを保存しますが,distkeyを指定したカラムは同じ値の場合に同じノードに保存されるようになり,そのカラムを含むテーブルをJOINで結合するSQLの高速化が期待できます。sortkeyは,指定したカラムの値がソートされてノードに保存されるようになり,たとえばタイムスタンプをsortkeyと指定することで,タイムスタンプをWHERE句で範囲指定したSELECTクエリのパフォーマンスの向上が期待できます。このためPostgreSQLやOracleなどのテーブルのパーティショニングは,Redshiftでは必要ありません。

その他,PostgreSQLと異なり,以下のような点に注意する必要があります。

ALTER COLUMNは利用不可
テーブルのカラムを変更する場合は,カラムの追加と削除で対応します。
Constraintsによる制約は設定できない
primary keyのようなキー制約はクエリのオプティマイズにのみ利用され,一意制約としてデータロード時にエラーを返すといったようなことは無く,重複データをチェックする機構を持ち合わせていません。このような制御はアプリ側で行う必要があります。
サポートされているデータ型がPostgreSQLに比べて限られている
INTEGER,BIGINT,DECIMAL,REAL,DOUBLE PRECISION,BOOLEAN,CHAR,VARCHAR,DATE,TIMESTAMPをサポート。文字コードはUTF-8をサポートしています。データタイプの詳細はAmazon Redshift Developer Guide(Data Type)を参照してください。

テーブル設計に関しては,クラスタ型というアーキテクチャのため,上記以外にも通常のPostgreSQLとは異なる点があります。ここでは,これ以上深くは掘り下げませんが,テーブルをデザインやクエリの速度チューニングを行う際にはAmazon Redshift Developer Guide(Designing Table)を見直すと良いでしょう。

Redshiftへのデータのロード

Amazon Redshiftへのデータのロード方法は,以下の3通りがサポートされています。

  • COPYコマンドによるAmazon S3バケットからの一括ロード
  • COPYコマンドによるAmazon DynamoDBのテーブルからのインポート
  • INSERTクエリによるレコード単位の追加

Amazon RedshiftのAmazon Redshift Developer Guide(Loading Data)によると,大容量のデータをロードする場合には,この中でもCOPYコマンドによるS3,DynamoDBからの一括ロードを推奨しています。これは,AWS上でデータを並列に処理してRedshiftクラスタに取り込め,ロードの効率が良いためです。これに比べ,INSERTクエリによるレコードの追加はパフォーマンスが非常に悪く,限定的な使い方になるでしょう。なお,今回はS3バケットからのロード方法について説明します。

データの作成

S3バケットからデータをロードする場合,まずCSVやTSVといったように特定文字をセパレータとしたフォーマットでファイルを作成し,S3のバケットにアップロードします。Amazonが提供しているサンプルデータでは,以下のようにパイプを区切り文字としたデータとなっています。

categoryテーブルのサンプルデータ(例)

1|Sports|MLB|Major League Baseball
2|Sports|NHL|National Hockey League
3|Sports|NFL|National Football League

今回はAmazon提供のデータをそのまま利用するため,データの作成およびアップロードの必要はありません。

データのロード

S3にアップロードされたデータをロードするには,Redshiftクラスタへ接続したクライアントツールからCOPYコマンドを発行します。このCOPYコマンドはRedshift用に拡張されたもので,以下の通りS3のファイルのパスやAWSのアクセスキーを指定するようになっています。AWSのアクセスキーはS3バケットへアクセスするために使われます。

COPYコマンドのフォーマット

COPY <Redshiftクラスタ上のテーブル名> FROM 's3://<バケット名>/<ファイルパス>' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID(Access-Key-ID)>;aws_secret_access_key=<あなたのAWSシークレットキー(Secret-Access-Key)>' <オプション>;

さっそく以下を修正し,Redshiftに接続したクライアントツールから実行してみましょう。今回利用するS3はパブリックに公開されているものですので,AWSキーは任意のもので構いません。

サンプルデータロード用のCOPYコマンドAmazon Redshift Getting Start Guideより)

copy users from 's3://awssampledb/tickit/allusers_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|';
copy venue from 's3://awssampledb/tickit/venue_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|';
copy category from 's3://awssampledb/tickit/category_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|';
copy date from 's3://awssampledb/tickit/date2008_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|';
copy event from 's3://awssampledb/tickit/allevents_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|' timeformat 'YYYY-MM-DD HH:MI:SS';
copy listing from 's3://awssampledb/tickit/listings_pipe.txt' CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '|';
copy sales from 's3://awssampledb/tickit/sales_tab.txt'CREDENTIALS 'aws_access_key_id=<あなたのAWSのアクセスキーID>;aws_secret_access_key=<あなたのAWSシークレットキー>' delimiter '\t' timeformat 'MM/DD/YYYY HH:MI:SS';

注意点として,S3バケットはコピー先のRedshiftクラスタと同じリージョンである必要があります。上記はUS East(Northern Virginia)のリージョンを想定したもので,RedshiftクラスタのリージョンがUS West(Oregon)リージョンの場合はawssampledbuswest2に,EU(Ireland)リージョンの場合はawssampledbeuwest1と,それぞれCOPYコマンドの中のバケット名を指定してください。

著者プロフィール

宮崎真(みやざきまさし)

HapyrusのソフトウェアエンジニアとしてAmazon Redshift向けプロダクトを開発中。

学生時代にIPA未踏ユースの経験を経て,卒業後ITコンサルティング会社に入社。この会社では基幹システムを対象としたミドルウェアの開発やiOSアプリ開発を経験。

その後米国グリーンカードの抽選に当選したのを機に,2012年にカリフォルニアベイエリアに移住しHapyrusに参画。

Twitter:@sockspaw


藤川幸一(ふじかわこういち)

学生時代からStartup (電脳隊・PIM)に関わり,PIMがYahoo! JAPANに買収された後は,エンジニアとしてYahoo!モバイルを開発。アジャイル開発コンサルやデリバティブ取引システムなどの開発経験を経て,シリウステクノロジーズでテクニカルマネージャ&夜はIPA未踏人材育成事業でHadoopのミドルウェア開発プロジェクト。日本JRubyユーザグループ発起人。

シリウスがYahoo! JAPANに買収されたのを機に,2010年FlyData Inc.(旧社名Hapyrus)をUSにて起業。カリフォルニアSunnyvale在住。

Twitter:@fujibee

コメント

  • Re: S3からうまくロードできない・・・

    早速のご回答ありがとうございます。
    なるほど、ログインとは別でアクセスキーを発行して取得せねばならないのですね。
    お陰様で無事データロードができました。

    AWS初心者のためくだらない基本的な質問をして申し訳ありませんでした。

    Commented : #3  Taka (2013/08/14, 22:14)

  • Re: S3からうまくロードできない・・・

    ログインに使用されているものとは、メールアカウントとパスワードの組み合わせでしょうか?
    ロード(copyコマンド)で必要となるのは、ログイン時のアカウントとは異なり、アクセスキーID、シークレットアクセスキーと呼ばれるものになります。
    これらのキーは、以下のリンク先に記載されていますので、こちらを入力してみて下さい。

    https://portal.aws.amazon.com/gp/aws/securityCredentials

    # AWSにログインしていない場合は、ログイン画面にリダイレクトされますので、ログインしてください。
    # ページ中央にアクセスキーID、シークレットアクセスキー が記載されている表が表示されます。

    Commented : #2  Masashi Miyazaki (2013/08/13, 14:12)

  • S3からうまくロードできない・・・

    テーブルはうまく作れましたがS3からロードする際にエラーになります。
    「AWSキーは任意のもので構いません」とのことですが、念のためログインに使用しているものを使いました。
    リージョンはN.Virginaです。
    -----------------------------------------------
    error: S3ServiceException:The AWS Access Key Id you provided does not exist in our records.,Status 403,Error InvalidAccessKeyId,Rid 5B4BA57273421351,ExtRid V7z2BmAFwHwMSg/Kw5V+VmqeUtyf0in1Epo5iG/uT8zoYC45J32usxYPM1ZX7uuo,CanRetry 1
    code: 8001
    context: Listing bucket=awssampledb prefix=tickit/allusers_pipe.txt
    query: 153
    location: table_s3_scanner.cpp:453
    process: query0_s1_25 [pid=3784]
    -----------------------------------------------

    Commented : #1  Taka (2013/08/12, 22:19)

コメントの記入