Glueなし！Bedrock × Redshiftで大量データ（1億件）を集計してみた話

# 今回やりたいこと
生成AIに関するLTに参加していたとき、Geminiを使って「各新聞出版社の売上をグラフにして」と指示するだけで、即座にグラフ化されるデモを目にしました。
それを見たときにふと思いました。
「今、Glueを使って構築している集計基盤にも、同じような仕組みを適用できれば、わざわざETLを作らずにすむのでは？」
そんな仮説のもと、Glueを使わずにBedrockで集計を自動化できないかを検証してみた記事になります。
なお、Glueを使うケースでは基本的に大量データを扱うため、今回は1億件規模のデータを用いて動作検証も行っています。

## この記事で分かること
- Glueを使わず、Bedrockを用いて集計基盤を構築するアプローチ
- 1億件規模の大量データに対してBedrockが集計できるかの検証結果
- 生成AIによる集計と従来のETL基盤、それぞれの適用シーンの考察

# イメージ図

## Glueを用いた構成図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790709/b4d7a2e5-ed0b-48d5-a4eb-5d9867cba0f0.png)

## Bedrockを用いた構成図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790709/cc604c6e-205e-40a4-8a02-f037952e9ed4.png)

# データ準備

## Redshift Serverlessの作成

Redshift Serverlessの作成は、いつも参考にさせていただいているみのるんさんの記事を参考に進めました。
（※名前やリソース名は、必要に応じて適宜変更してください！）

https://qiita.com/minorun365/items/31b4a2835a6d0eca109a#redshift-serverless%E3%81%AE%E4%BD%9C%E6%88%90

## DBへのデータ投入

こちらも同じくみのるんさんの記事をベースにしつつ、今回は集計用データに合わせて少し加工しています。

https://qiita.com/minorun365/items/31b4a2835a6d0eca109a#db%E3%81%B8%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E6%8A%95%E5%85%A5

まず、以下のCREATE文で購入履歴テーブルを作成しました。

```
CREATE TABLE purchase_history (
  user_id       INT,
  purchase_date TIMESTAMP,
  product_id    INT,
  product_name  VARCHAR(255),
  product_price INT,
  quantity      INT
);
```

続いて、大量データで集計を試しやすいよう、RedshiftにCOPYコマンドで取り込める形式のCSVファイルを用意しました。

```purchase_history_yakitori.csv
user_id,purchase_date,product_id,product_name,product_price,quantity
101,2024-04-10 14:32:00,2001,とりかわ,120,3
101,2024-04-10 14:32:00,2001,とりかわ,120,3
101,2024-04-10 15:10:00,2002,ぼんじり,130,2
102,2024-04-11 09:15:00,2002,ぼんじり,130,5
102,2024-04-11 09:15:00,2002,ぼんじり,130,5
102,2024-04-11 10:20:00,2003,ねぎま,150,1
101,2024-04-12 18:45:00,2003,ねぎま,150,2
101,2024-04-12 18:45:00,2003,ねぎま,150,2
101,2024-04-12 19:00:00,2004,つくね,160,1
103,2024-04-13 11:05:00,2004,つくね,160,1
103,2024-04-13 11:05:00,2004,つくね,160,1
103,2024-04-13 11:30:00,2005,レバー,140,2
104,2024-04-14 16:20:00,2005,レバー,140,1
104,2024-04-14 16:20:00,2005,レバー,140,1
104,2024-04-14 17:15:00,2006,砂肝,110,3
105,2024-04-15 20:10:00,2006,砂肝,110,4
105,2024-04-15 20:10:00,2006,砂肝,110,4
105,2024-04-15 20:30:00,2007,はつ,100,2
106,2024-04-16 12:00:00,2007,はつ,100,3
106,2024-04-16 12:00:00,2007,はつ,100,3
```

次に、RedshiftからS3へのアクセス設定を行います。
使用しているIAMロールに、以下のポリシーを追加してください。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket",
                "arn:aws:s3:::your-bucket/*"
            ]
        }
    ]
}
```

最後に、S3に配置したCSVファイルをRedshiftに取り込みます。
Redshiftのクエリエディタなどから、以下のCOPYコマンドを実行してください。

```
COPY purchase_history
FROM 's3://your-bucket/data/purchase_history.csv'
IAM_ROLE 'arn:aws:iam::123456789012:role/YourRedshiftRole'
FORMAT AS CSV
IGNOREHEADER 1
TIMEFORMAT 'auto';
```

# RedshiftをデータソースとしたBedrockのナレッジベース基盤を構築

ここから、RedshiftをデータソースとするBedrockナレッジベース基盤の構築に進みます。

手順については、これもみのるんさんの記事をベースに進めています。
（※ みのるんさんの記事ほぼそのままでは？と思われるかもしれませんが…… 今回は大量データを用いた検証と独自の試行も含めているので、温かい目で見てもらえると嬉しいです🙏）

https://qiita.com/minorun365/items/31b4a2835a6d0eca109a#%E6%89%8B%E9%A0%862-bedrock%E3%81%AE%E8%A8%AD%E5%AE%9A

# Bedrockを用いてRedshiftを参照し、集計させてみる

ここでは、Bedrockを使ってRedshift内のデータを集計させた結果を紹介します。
試してみたところ、4月15日以降の購入履歴が抜けている点を除けば、Redshiftで直接集計した結果と一致していました！

## Bedrock結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790709/8b82c841-f0ce-474b-8f0e-0ce47785a1e4.png)

## Redshiftの結果

### 実行したSQL
実行したSQLはこちらです。
```
SELECT
  CAST(purchase_date AS DATE) AS purchase_day,
  product_name,
  SUM(product_price * quantity) AS total_amount
FROM
  "dev"."glue_bedrock"."purchase_history"
GROUP BY
  CAST(purchase_date AS DATE),
  product_name
ORDER BY
  purchase_day,
  product_name;
```
### SQL実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790709/d6f3c5d2-267d-4758-bd9d-5463e9d09c85.png)

# 大量データを用いた集計検証

簡単な集計ができることを確認できたので、次は大量データ（1億件規模）に対しても、Bedrockでズレなく集計できるかを検証していきます。

今回は、段階的にデータ件数を増やして確認しました。

| データ件数 |集計結果|
|:---:|:---:|
| 1万件       |〇|
| 10万件       |〇|
| 100万件       |〇|
| 1000万件       |〇|
| 1億件       |〇|

## Bedrockの回答サンプル(1万件)
すべての日付の集計結果が回答されるわけではなく、特徴的な日のデータが回答される形でしたが、その内容がRedshiftで集計した結果と一致していることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790709/38a69bc9-c1de-49c6-ba78-125a97b4cbe8.png)

# 結果

今回、1億件規模の大量データに対しても、Bedrockは簡単な集計であれば正確な数値を返してくれることを確認できました。
これにより、ETLを組まずに生成AIだけで集計できる場面があるとわかり、特にSQLに慣れていない非エンジニア層に対して有効なケースが考えられます。

一方で、集計結果をQuickSightなどの可視化ツールでグラフ化したい場合には、
やはり別途データ整形やパイプライン構築が必要となるため、従来のETL基盤のほうが適している場面もありそうです。

そのため、今後は、集計の内容や利用シーンに応じて、「生成AIによる集計」と「従来のETL基盤」を適切に使い分けていくことが重要だと感じました。

今後も、生成AIの活用シーンを広げられるように検証を続けていきたいと思います！