【AWS】redshift,S3とglueのETL

# はじめに
KaggleやNishikaといったサービスでは整った形のデータセットがダウンロード可能でPythonですぐに読み込む事ができますが、本来こういった大規模なデータはどういった構造で蓄積されると良いのか興味がありました。

※過去にNishikaでデータ分析に入門してみたQiita記事

https://qiita.com/naitoyuma/items/70c8c42040603fa25d9b


今回は色々な方の記事を参考にAWSのサービスを学びながら実践的な構成を目指したいと思います。
初心者ですので間違ってたらすいません。

## データ分析基盤の構成
サイト情報を元にデータ分析に必要な基盤について教えて頂きました。

下記YOUTUBE動画で概要が分かりやすく説明されており、対応するAWSサービスも紹介されていました。

https://youtu.be/mgG3da6PRFM?si=eLAujR1ndDFsxQNP

またこちらのサイトではデータレイク、データウェアハウス、データマートの各種特徴について分かりやすくまとめて頂いています。

https://dx.lakeel.com/column/dwh_merit_demerit/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/98f64be6-4e35-b077-eba5-12ce86628dba.png)

>lakeel.com：クラウド型アプリケーション開発・運用基盤より

## 今回の内容
今後サイトを参考に難易度を段階的に上げながらAWSの各種サービスを試していこうかと思います。
今回は各種AWSサービスの基本的な連携方法について以下を作成しながら勉強しようと思います。

**1.  S3に対するGlueのETL実行**

![S3アーキテクチャ.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/3288816c-fb4f-06d3-2670-f3305a740425.png)

**2. S3に対するRedshiftからの接続**

![S3-Redshift.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/1f146142-d02e-1ffa-ff3d-9bf0871fd33e.png)

## 1．S3に対するGlueのETL
S3間のETLをGlueで作成し簡単なデータ処理を設定しようと思います。

- [x] S3でデータレイク、データウェアハウス2つのバケットを作成しデータを設置
- [x] GlueでETLに見立てたPython関数の定期実行を設定する
- [x] データレイクのCSVから抽出したデータをデータウェアハウスにCSV形式で出力する

![S3アーキテクチャ.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/3288816c-fb4f-06d3-2670-f3305a740425.png)

## 実施手順
データレイクに設置したCSV形式のタイタニック号の乗員、乗客データから、乗組員ID、生存情報(生存でTrue)、クラス、性別、年齢のカラムのみ抽出したデータをCSV形式でデータウェアハウスに出力する処理をGlue jobとして作成していきます。

### S3にバケットを作成しデータを設置

Kaggleでダウンロードしたタイタニック号の乗員名簿データがCSV形式でDatalakeに置いてあるような状態を想定しています。

https://www.kaggle.com/competitions/titanic/overview

上記をデータレイク側のS3にタイタニック号データを設置します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/8fe75c0a-d580-3368-6d1b-4050a95e06ab.png)

### GlueにPythonスクリプトを設定

Gluejobを作成しスクリプトタブで以下の関数を設定します。
```py:glue:script
import pandas
import s3fs
# s3などのAWSストレージに設置したライブラリファイルをjob detailタブで読み込むことも可能

source_s3_file = "s3://データレイクのバケット名/titanic/test.csv"
dest_s3_file ="s3://データウェアハウスのバケット名/test-etl.csv"

titanic_df = pandas.read_csv(source_s3_file)

# 乗組員ID、生存情報、クラス、性別、年齢のみ取り出す
titanic_df = titanic_df[['PassengerId', 'Survived', "Pclass", "Sex", "Age"]]

titanic_df.to_csv(dest_s3_file)
```
Runでスクリプトをテスト実行すると指定したS3バケットに特定のカラムのみ抽出されたCSVが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/e405f2b6-fad4-3d80-4753-dfb066164cb3.png)


定期実行を行う際はScheduleタブで実行頻度や時間を設定します。

実行結果はRunsタブのCloudwatch logsから実行したGlueスクリプトに対応するロググループが作成され閲覧できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/8bdc0951-a5e5-6415-539e-92971040a420.png)

※作成したGlue JobのIAM Roleには「S3へのアクセス」、「Cloud Watchへの書き込み」権限が必要でした。

データウェアハウス側にCSVが出力されればPythonによるETL処理の実行を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/19fc0390-b0fd-2974-6355-6013fabb5357.png)

## 2. S3に対するRedshiftからの接続
下記のハンズオン記事を参考に実施しました。

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Analytics-2022-reg-event.html?trk=aws_introduction_page

動画ではQuickSightを使いデータの集計結果の視覚化を行っていましたがそこまではやらなかったです。

- [x] S3にデータレイクを作成しtxt型データを設置する
- [x] Redshiftにデータ構造に対応したテーブルを作成する 
- [x] クエリ―の実行によりS3のデータをReadshiftに挿入する

![S3-Redshift.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/1f146142-d02e-1ffa-ff3d-9bf0871fd33e.png)


## 実施手順
Redshiftにデータベース、各種テーブルを作成しS3に設置したレコード情報を含むテキストファイルからQuery Editorを使用しレコードを作成していきたいと思います。

### S3にテキストデータを設置
先ほど利用したS3データレイクに各種Redshiftのレコードとなる元のテキストデータを設置しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/4a2dc77f-70f5-dc0f-6fce-ada648e2f371.png)

テキストデータは以下のデータ構造に対応するレコードが含まれています。

>手を動かしなら学ぶ Analytics サービス入門より

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/5e81498f-1f01-a427-18fd-17a3e4ec49e3.png)

### Redshiftでデータベース作成

ワークグループに関する各種設定はデフォルトのものを使用し、VPC、サブネット、セキュリティグループ等の設定も一旦デフォルトで作成しました。

ネットワーク関連の設定も自分なりにカスタマイズして勉強したかったのですが今回は行いませんでした。

https://zenn.dev/tomoshimizu/articles/6945b7ac472ca0

作成したリソースは名前空間で構造化されるようです。

下記の記事ではRedshiftに関する構造や操作方法を参考にさせて頂きました。

https://qiita.com/hashimoto_mana/items/24cc25c5f9e2e44618bc

### クエリの実行
RedshiftメニューからRedshift query editor v2にアクセスし作成したDBに対しクエリの実行を行う事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/fe2aa453-7c23-47df-3ba8-a943183d8ea0.png)

ハンズオンで配布された資料をもとにテーブル構造を定義します。
```sql:CreateUser
create table users(
  userid integer not null,
  username char(8),
  firstname varchar(30),
  lastname varchar(30),
  city varchar(30),
  state char(2),
  email varchar(100),
  ...省略
  ) 
```
```sql:CreateDate
create table date(
  dateid smallint not null,
  caldate date not null,
  day character(3) not null,
  week smallint not null,
  month character(5) not null,
  qtr character(5) not null,
  year smallint not null,
  holiday boolean default('N'));
```

```sql:CreateSale
create table sales(
  salesid integer not null,
  listid integer not null,
  sellerid integer not null,
  buyerid integer not null,
  eventid integer not null,
  dateid smallint not null,
  qtysold smallint not null,
  pricepaid decimal(8,2),
  commission decimal(8,2),
  saletime timestamp);
```
Runで各クエリを実行するとテーブルが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/c30ccf11-e3da-462f-a5d4-ec1df0ab71f8.png)


同様にS3に接続しデータ内容からレコードを作成するクエリが実行できます。

COPY句はRedshift固有のクエリでS3からCSVやtxt形式のデータをレコードとして読み込み可能との事です。

各テキストファイルのフィールドの区切りは"|"、もしくは"\t(タブ)"で、
時間のフォーマットは"MM/DD/YYYY HH:MI:SS"となっています。
```sql:user ETL
COPY users from 's3://S3データレイクの名前/data-analysis-handson/allusers_pipe.txt' iam_role 'IAMロールのARN' delimiter '|' ;
```
```sql:date ETL
COPY date from 's3://S3データレイクの名前/data-analysis-handson/date2008_pipe.txt' iam_role 'IAMロールのARN' delimiter '|' ;
```
```sql:sale ETL
COPY sales from 's3://S3データレイクの名前/data-analysis-handson/sales_tab.txt' iam_role 'IAMロールのARN' delimiter '\t'  timeformat 'MM/DD/YYYY HH:MI:SS';
```
※IAMロールにはあらかじめ作成されたRedshiftFullAccessを持つロールを設定しました。

Runでクエリを実行すればレコードが作成されます。

usersテーブルの内容を見るとレコードが作成されているのが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/c673bc70-def5-78e0-babf-0496937fac27.png)

# まとめ
S3,Glue,Redshiftを使用したデータのやり取りを少しだけ実践してみました。
次は実戦的な構成を目指して勉強してみたいと思います。

**S3に対するGlueのETL**
- [x] S3でデータレイク、データウェアハウス2つのバケットを作成しデータを設置
- [x] GlueでETLに見立てたPython関数の定期実行を設定する
- [x] データレイクのCSVから抽出したデータをデータウェアハウスにCSV形式で出力する

**S3に対するRedshiftからの接続**
- [x] S3にデータレイクを作成しtxt型データを設置する
- [x] Redshiftにデータ構造に対応したテーブルを作成する 
- [x] クエリ―の実行によりS3のデータをReadshiftに挿入する