AWS Redshiftで集計クエリを投げてみた

Redshiftで集計のクエリを投げるために、環境構築から取り組んだ。
いろいろ苦労したので、まとめてみる

利用環境はMacです。

## 【背景】
- Redshiftって集計に使えそうだけど、Athenaと比較して性能ってどんなもんなの？
- Redshiftってデータ蓄積するのはS3じゃないんだよね？実際にどうやったら動かせるんだろう
- ただ、やったことないしわからないな〜

今回はこんな課題感で手を動かし始めました。

## 【実際にやったこと】
1. Redshiftでクエリを投げてみた
    - Redshiftの環境構築
    - Redshiftにテーブルを作成する
    - S3からデータをコピーする
    - クエリを投げる

これらをどのようにしていったかをまとめます。（いろんな記事を参考にさせていただきました）

## 【Redshiftでクエリを投げてみた】
実際にやっていった手順に沿って書いていこうと思います。

### Redshiftの環境構築, テーブルの作成, S3からデータをコピーする

Redshiftの[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/redshift/latest/gsg/getting-started.html)に沿って、環境構築を行った。
クラスターを作成し、そのクラスターにデータベースを作成しました。
ストレージは160GBで、ノードの種類はdc2.largeで数は一つです。
ドキュメントの通り進めていって、テーブルの作成まで行うことができた（公式ドキュメントのstep 6の途中）

このままデータをS3からコピーしようと以下のクエリを叩くとその下のエラーが出てきました。（<>でマスキングしています）

```sql:Redshift
copy users 
from 'S3 URI' 
IAM_ROLE 'arn:aws:iam::<aws_user_id>:role/<role_name>'
;
```
```:error
ERROR: User arn:aws:redshift:<リージョン>:<aws_user_id>:<dbuser:クラスター名/DBユーザー名> is not authorized to assume IAM Role arn:aws:iam::<aws_user_id>:role/<role_name>. Detail: ----------------------------------------------- error: User arn:aws:redshift:<リージョン>:<aws_user_id>:<dbuser:クラスター名/DBユーザー名> is not authorized to assume IAM Role arn:aws:iam::<aws_user_id>:role/<role_name>. code: 8001 context: IAM Role=arn:aws:iam::<aws_user_id>:role/<role_name> （略）
```

なんかAuthorize系のエラーが出てるから、とりあえずS3、Redshiftのフルアクセス付けたらいけるだろうと思ってましたが、実際にはどうにもうまくいきませんでした

そこでこの記事を参考に。[[Amazon Redshift] RedshiftのIAM Roles利用が可能となりました。](https://dev.classmethod.jp/articles/amazon-redshift-iam-role/)

今回問題だったのは、S3からRedshiftへデータをcopyする際にエラーが出ていたということ。
具体的に行ったことは

- amazon Redshiftのサービスロールを新たに作成した
- そのサービスロールの信頼されたエンティティが"redshift.amazon.com"であること
- その作成したサービスロールをRedshiftのクラスターでアタッチする

以上の三項目を行うとエラーが出なくなりました:)
つまり、"role_name"を変更した。ということですね！
この辺りのロール、サービスロール周りは[IAM公式ドキュメント](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html)を読んで、理解を深めました。

これによって権限系のエラーは出なくなったのですが、、、S3からcsvfileをコピーしようとすると、こんなエラーが、

```:error
ERROR: Load into table 'file_name' failed. Check 'stl_load_errors' system table for details.
```

これは'stl_load_errors'をチェックしろということなので、以下のクエリで確認したところ、エラーコードが表示されました！！！

```sql:stl_load_errors
SELECT *
FROM stl_load_errors
ORDER BY starttime DESC LIMIT 2;
```

[公式ドキュメント（ロードエラーコード）](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_Load_Error_Reference.html)によると'1214'は'区切り記号が見つかりません'とのことでした。
エラーの内容もしっかり見ていると、'raw_filed_value'にカラム名が入っていることでエラーが起きてそうでした。
そこでS3にアップロードしているデータのカラム名（header）を削除してアップロードし直すと、次はまた別のエラーが、、
今度は区切りの文字が違うとのことだったので、[こちら](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/copy-parameters-data-format.html#copy-delimiter)を参考に、'delimiter'を指定しました。（Redshiftのデフォルトの区切り文字は'|'だそうですね、、、知りませんでした）

そうしたらようやく、、！！
S3から、データをコピーすることができました！！

### クエリを投げる
ここまで来れたらあとはもうクエリを投げるだけ。もちろん集計関数も使えます。

```sql
SELECT *
FROM テーブル名
;
```
なんでも好きなクエリで、計算することができました！！もちろん複数テーブルを作成してのjoinもできました。

### まとめ
今回出たエラーと対応を順番にまとめます。

- 権限系のエラー → サービスロールを作成（信頼されたエンティティを指定）
- csvfileの区切りがおかしいその① → 元データのヘッダーを削除
- csvfileの区切りがおかしいその② → copy時の区切り文字を指定

このような手順でエラーを乗り越えて行きました。色々と苦労しましたが、公式のドキュメントと向き合うことが大切だと学びました。
Redshiftはクラスターを最初に作成して、ノード数を決めて、クエリを投げるので、パフォーマンスは安定してるとのことです。
（Athenaはリクエスト時に、AWS側でリソースを確保するらしい）

引き続き学びがあれば更新していきたいと思います〜