【初心者向け】EMR Studioでお手軽にデータ処理をする（EMR Studio, Amazon EMR Serverless, Notebook）

# はじめに

じゅんじゅんです。
私は以前EMRを使ってETL処理を行っていたデータエンジニアの1人だったのですが、最近またEMRを手軽に使ってみたいと考えるようになり、この検証をしようと考えた次第です。

当時はEC2を選定してその上でEMRを起動させる方法を使っていたのですが、最近だと手軽に始められるEMR StudioやEMR Serverlessのアップデートがあったため、そちらを検証できればと思います。

これからEMRを利用する方々のご助力になれば幸いです。

# EMR Studioの初期設定

[こちら](https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-studio-set-up.html) を参考にEMR Studioの初期設定を行ないます。

まず、AWSコンソールからEMRのサービスページにアクセスし、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/3d3df081-143d-4eed-ac2c-63a7812879ec.png)

EMR Studioの"Studios"から"Studioを作成"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/57ae11fd-bbc4-44b7-9d5c-f0d9294c48ec.png)


設定オプションをインタラクティブワークロード、その他のリソース名を任意でつけて、作成します。（リソース名はデフォルトのままで問題ありません）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/debc2461-d54c-49ac-b8b9-ff6b1caba3ca.png)

これでStudioの作成ができました。

Studiosに先ほど命名したStudioが生成されたことを確認できます。
そしてこのStudio名をクリックするとEMR Studioの画面に遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/aca3f4ad-5972-4fd1-9648-bf34b7b4f355.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/687f93d2-d555-4213-9f17-aad982558c17.png)

WorkSpacesから先ほど作成したWorkSpaceをクリックすると見慣れたJupyterの画面に遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/999544b8-9a93-47a2-bd16-28f72a416a28.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/a874ebc2-4b94-4bda-99ae-1703eedd95b5.png)


こちらでデータ処理の作業を行なっていきます。

# Notebook上での作業

今回はPySparkのNotebookを開いて作業します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/7381c9a9-ff2c-4fd3-9837-5d6bbbe8d2da.png)

このタイミングでEMR StudioのServeless→Applicationsを確認するとServerless_Interactive_App_junjun（初期設定で命名した名前）が起動されていることがわかります。
こちらがNotebookの裏で動いているサーバーの設定となります。logやlimitの制限など多数の設定項目が確認できます。今回は検証なので何もいじらずに進めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/0811e030-646b-41fe-bb22-1c233a53a73d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/f807c0b9-1454-447c-951b-ac091da41f75.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/3723691d-6a26-4a1e-89a0-43a1423a6a1e.png)


## データの変換およびSQL

`s3://inu-is-dog/japan_population_tsv/` 配下に以下の日本人口の推移を記録したtsvファイルが配置されています。
このtsvファイルをS3から読み取って男性比率のカラムを追加し、parquetに変換して`s3://inu-is-dog/japan_population_parquet/`に出力する をやってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/2c094668-a7b2-4b02-ae23-b0bacffd38bc.png)

コードを書く前にEMR StudioがS3に対して読み書きをする権限が必要なので、IAMにて、初期設定でアタッチしたEMR StudioのロールにS3へのアクセスの権限を付与します。
今回はインラインポリシーで対応しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/5db597a9-da61-4042-996c-8bfd935c17be.png)


Jupyterの画面に戻りまして、まずS3のデータを読み取るコードを実行します。
```python
# データの読み取り先のS3パス（ファイル指定でも、フォルダ指定で複数ファイルでもOK）
input_s3_path = "s3://inu-is-dog/japan_population_tsv/"

# S3からtsvファイルを読み取ってデータフレーム(df)に格納する
df = spark.read.csv(input_s3_path, sep=r'\t', header=True)

# データフレームの中身の確認のため標準出力する（デフォルト20行）
df.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/01323179-5782-476a-87c6-d3eb2dd2c5c7.png)


では、男性比率のカラム`man_ratio`を追加するコードを実行しましょう
今回はSpark SQLを使ってみます。

```python
# データフレームをSpark SQLで使えるように登録する
df.createOrReplaceTempView("population_tbl")

# SQLの実行、および実行結果をoutput_dfに格納する
output_df = spark.sql("""
SELECT 
  *,
  man_population / all_population as man_ratio
FROM 
  population_tbl
""")

# データフレームの中身の確認のため標準出力する
output_df.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/b92e1ecd-3806-49d8-a330-9644ffc33a16.png)

無事、man_ratioのカラムを追加できました。

では次にこのデータをparquet形式で出力します。
せっかくなので`year`ごとにパーティション分割した形で出力してみます

```python
output_s3_path = "s3://inu-is-dog/japan_population_parquet/"
output_df.write.mode("overwrite").partitionBy("year").parquet(output_s3_path)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/fe10544d-b2ac-4a68-85a5-20e4b0a365ae.png)


S3の方を見てみましょう。
綺麗にパーティション分割されていますね。素晴らしいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/fc591b81-82d1-439f-9b8a-a38ac3380b1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/b4379e8a-83bc-448f-9a21-ccf06419ef91.png)

これにて検証は以上になります。

## 終了処理

検証が終わったのでリソースを終了させます。
WorkSpacesから使用していたWorkSpaceを選択し"Stop"の状態にします。
（リソースがもう必要ないということであればDeleteを選択してください）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/6069a16b-98e8-4b23-a378-08fa85b97e99.png)

またApplicationsから使用していたApplicationをStop Applicationします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451269/51bc8f97-37f7-499a-a6dd-05f10af6d486.png)


# EMR Studioの料金

[こちら](https://aws.amazon.com/jp/emr/pricing/)より、
EMR StudioはEMR Serverlessの料金だけを気にすれば良さそうです。
EMR Serverlssの料金は使用するvCPU、メモリ、およびストレージリソースに基づいた従量課金制です。

※2025/02/25時点 東京リージョンの場合
■Linux/x86
1 時間あたりのvCPU 単位：USD 0.065728
1 時間あたりのGB単位：USD 0.007189

■Linux/ARM
1 時間あたりのvCPU 単位：USD 0.052585
1 時間あたりのGB単位：USD 0.005746


# 所感・まとめ

以前はデータ処理の負荷に応じてEC2を選定してデータ処理を行うというのがルーチン化してしていたのですが、それがないだけでかなりストレスフリーだと感じました。また、Notebookでインタラクティブに結果がわかるのもかなり好感触でした。
今回は、検証ということでEMR StudioのVPCや権限やセキュリティはかなり緩めに設定していたのですが、本格的に使うときにはその設定も必要そうです。それでもEMRは敷居が高いというイメージを払拭できる可能性を感じられました。