「本番のRDSに分析用のクエリを投げたいけど、重い集計で本番が遅くなったら怖い……」——そんな悩みはありませんか?サービスが成長すると、売上の集計やユーザー行動の分析をしたくなりますが、本番DBに直接アナリティクス系のクエリを打つのは事故のもとです。
そこで定番になるのが、RDSのスナップショットをS3経由でBigQueryに連携し、分析はBigQuery側で完結させるという構成です。本番DBには一切負荷をかけず、分析チームはSQLで自由にデータを触れます。この記事では、その連携手順を2026年時点の仕様に合わせて、コマンド付きで解説します。
なぜスナップショット経由なのか(結論)
RDSからBigQueryへデータを運ぶ方法はいくつかありますが、「RDSのスナップショットをS3にエクスポート → BigQueryが読み込む」という流れには次のメリットがあります。
- 本番DBに負荷をかけない:スナップショットはバックアップのコピーなので、エクスポート処理が本番のパフォーマンスに影響しません
- フルダンプ不要:
mysqldumpやpg_dumpのように自前でダンプ・転送を書かなくても、AWSのマネージド機能だけで完結します - Parquetで効率的:エクスポートされるのは列指向で圧縮されたParquet形式なので、BigQueryへの取り込みと相性が良く、容量も小さくなります
全体の流れは次の7ステップです。前半(1〜4)がAWS側、後半(5〜7)がGCP側の作業になります。
- エクスポート先のS3バケットと、暗号化用のKMSキーを用意する
- RDSがS3に書き込むためのIAMロールを作成する
- スナップショットをS3にエクスポートする(Parquetで出力される)
- BigQueryがS3を読むためのIAMユーザー(アクセスキー)を作成する
- GCPでBigQuery APIとBigQuery Data Transfer Serviceを有効にする
- BigQueryに受け皿のデータセット・テーブルを作る
- Amazon S3転送(Data Transfer)を設定して取り込み、連携を確認する
ポイントは、AWS側とGCP側でIAMの役割が違うこと。RDSのエクスポートには「ロール」を、BigQueryからの読み取りには「ユーザー(アクセスキー)」を使います。ここを混同しないのが最大のコツです。
手順1:S3バケットとKMSキーを用意する
まず、エクスポート先のS3バケットを用意します。スナップショットと同じリージョンに作るのが鉄則です(リージョンが違うとエクスポートに失敗します)。
# スナップショットと同じリージョン(例: ap-northeast-1)にバケットを作る
aws s3 mb s3://my-rds-export-bucket --region ap-northeast-1次に、エクスポート時のサーバーサイド暗号化に使うKMSキーを作成します。RDSのスナップショットエクスポートは、S3への書き込み時にKMSで暗号化する仕様になっています。
# 対称鍵のKMSキーを作成し、KeyId を控えておく
aws kms create-key --description "rds-snapshot-export" --region ap-northeast-1出力される KeyId(または Arn)を手順3で使います。マネジメントコンソールから作る場合は「対称(Symmetric)」「暗号化および復号(Encrypt and decrypt)」を選べばOKです。
手順2:RDSがS3に書き込むIAMロールを作る
スナップショットのエクスポート処理(export.rds.amazonaws.com)が、S3バケットに書き込むためのIAMロールを作成します。ここはユーザーではなくロールである点に注意してください。まず、バケットへの読み書きを許可するポリシーを用意します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::my-rds-export-bucket",
"arn:aws:s3:::my-rds-export-bucket/*"
]
}
]
}このポリシーを付けたロールを作り、信頼関係(Trust relationship)で export.rds.amazonaws.com がこのロールを引き受けられるようにします。信頼ポリシーは次のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "export.rds.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}加えて、手順1で作ったKMSキーのキーポリシーに、このロールからの kms:CreateGrant と kms:DescribeKey を許可しておく必要があります。これが抜けていると、エクスポート開始時に権限エラーで止まります(後述の「つまずきどころ」参照)。
手順3:スナップショットをS3にエクスポートする
準備ができたら、対象のスナップショットをS3にエクスポートします。マネジメントコンソールなら「RDS → スナップショット → 対象を選択 → Amazon S3にエクスポート」から、CLIなら次のように実行します。
aws rds start-export-task \
--export-task-identifier my-db-export-20260101 \
--source-arn arn:aws:rds:ap-northeast-1:123456789012:snapshot:my-db-snapshot \
--s3-bucket-name my-rds-export-bucket \
--s3-prefix exports \
--iam-role-arn arn:aws:iam::123456789012:role/rds-s3-export-role \
--kms-key-id arn:aws:kms:ap-northeast-1:123456789012:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxエクスポートが完了すると、S3には次のような階層でParquetファイルが出力されます。データベース名・スキーマ名・テーブル名ごとにフォルダが分かれるのがポイントです。
s3://my-rds-export-bucket/exports/my-db-export-20260101/
└─ mydb/
├─ mydb.users/ ← usersテーブルのParquet
│ └─ part-00000-xxxx.gz.parquet
└─ mydb.orders/ ← ordersテーブルのParquet
└─ part-00000-xxxx.gz.parquetこのフォルダ構造が、あとでBigQueryの転送設定でS3 URIを指定するときに効いてきます。「どのテーブルのParquetがどこにあるか」を把握しておきましょう。データ量にもよりますが、エクスポートには数分〜数十分かかります。
手順4:BigQuery用のIAMユーザー(アクセスキー)を作る
ここからGCP側の準備に入りますが、その前にBigQueryがS3を読み取るためのAWS認証情報を用意します。BigQuery Data Transfer ServiceのS3転送は、アクセスキーIDとシークレットアクセスキーで認証するため、読み取り専用のIAMユーザーを作ります(ロールではなくユーザーです)。
- S3転送専用のIAMユーザーを新規作成する
- AWSマネージドポリシー
AmazonS3ReadOnlyAccessを付与する(最小権限にしたい場合は対象バケットだけに絞ったポリシーでも可) - アクセスキーを発行し、アクセスキーIDとシークレットを控える
アクセスキーは長期有効な資格情報なので、この転送専用に発行し、他の用途と使い回さないのがセキュリティ上のベストプラクティスです。シークレットは発行時にしか表示されないので、安全な場所に保管してください。
手順5:GCP側でAPIを有効にする
GCPのプロジェクトで、次の2つのAPIを有効にします。コンソールの「APIとサービス」から検索して有効化するか、CLI(gcloud)で一括有効化できます。
gcloud services enable bigquery.googleapis.com
gcloud services enable bigquerydatatransfer.googleapis.comBigQuery Data Transfer Serviceが、S3からBigQueryへ定期的にデータを取り込む(ロードジョブを管理する)仕組みです。これを有効にしておかないと、次の手順で転送設定の画面が出てきません。
手順6:BigQueryに受け皿のテーブルを作る
BigQueryにデータセットを作り、取り込み先のテーブルを用意します。
# データセットを作成(ロケーションはS3と近いリージョンを推奨)
bq --location=asia-northeast1 mk --dataset my_project:rds_importParquetはスキーマ情報を自身に持っているため、転送時にBigQueryがスキーマを自動検出してくれます。そのため、空のテーブルをあらかじめ作らなくても、転送設定で指定したテーブル名で自動的に作成・ロードされます(明示的にスキーマを固定したい場合は、先にテーブルを作っておいてもOKです)。
なお、1回の転送設定で取り込めるのは基本的に1テーブル分です。users と orders を両方取り込みたいなら、テーブルの数だけ転送設定を作ります。手順3で見たフォルダ構造(テーブルごとにパスが分かれる)が、ここで効いてくるわけです。
手順7:Amazon S3転送を設定して取り込む
いよいよ連携の設定です。BigQueryコンソールの「データ転送」→「転送を作成」から、次のように設定します。
- ソース:Amazon S3
- 送信先データセット:手順6で作った
rds_import - 送信先テーブル:例
users - Amazon S3 URI:取り込みたいテーブルのParquetを指すパス。例
s3://my-rds-export-bucket/exports/my-db-export-20260101/mydb/mydb.users/* - アクセスキーID/シークレット:手順4で発行したもの
- ファイル形式:PARQUET
保存すると、スケジュールに従って(または「今すぐ実行」で)取り込みが始まります。完了したら、BigQueryでテーブルを確認してみましょう。
SELECT COUNT(*) FROM `my_project.rds_import.users`;件数がRDS側と一致していれば連携成功です。あとは分析用のクエリをBigQueryに対して自由に投げられます。本番DBには一切触れていないので、重い集計を回しても安心ですね。
よくあるつまずきどころ
エクスポートが権限エラーで止まる(KMS)
一番多いのがこれです。KMSキーのキーポリシーに、エクスポート用IAMロールからの kms:CreateGrant と kms:DescribeKey を許可していないと、start-export-task が失敗します。KMSキーの「キーユーザー」にエクスポートロールを追加するか、キーポリシーに明示的に許可を書きましょう。
リージョンが食い違っている
スナップショットとS3バケットのリージョンが違うとエクスポートできません。また、BigQueryのデータセットのロケーションとS3のリージョンが遠いと転送が遅くなったり、転送がサポートされないロケーションの組み合わせもあります。「同じ(または近い)リージョンで揃える」を基本にしてください。
ロールとユーザーを混同する
繰り返しになりますが、RDSのエクスポートはIAMロール、BigQueryからの読み取りはIAMユーザー(アクセスキー)です。「エクスポート用ロールのアクセスキーをBigQueryに入れようとして動かない」というのが典型的なハマりです。役割が別物だと意識しておきましょう。
複数テーブルを1つの転送でまとめようとする
S3 URIをデータベース直下(.../mydb/*)にすると、スキーマの違うテーブルが混ざってエラーになります。テーブル単位でパスを指定し、テーブルごとに転送を作るのが基本です。
まとめ
RDSのスナップショットをBigQueryに連携する流れを、2026年の仕様に合わせて整理しました。ポイントをおさらいします。
- スナップショット経由なら本番DBに負荷をかけずに分析基盤へデータを運べる
- AWS側はIAMロール+KMSでParquetをS3にエクスポート
- GCP側はIAMユーザー(アクセスキー)+Data Transfer ServiceでParquetを取り込む
- 転送はテーブル単位。フォルダ構造を意識して設定する
一度仕組みを作れば、定期的にスナップショットをエクスポートして転送をスケジュール実行することで、分析用のデータを自動で最新化できます。本番とアナリティクスをきれいに分離したい方は、ぜひ試してみてください。
AWS周りの運用については、こちらの記事もあわせてどうぞ。
- EC2の監視でつまずいたら 監視対象としたいEC2のCloudWatchメトリクスが選択できない場合の解決方法
- RailsアプリをAWSにデプロイするなら Rails 8 × Kamal 2でAWS(EC2+RDS)にデプロイする手順
- Rails 8のDB設定を見直すなら Rails8に入るsolid_queueなどのgemを使った時のdatabase.ymlの書き方
スポンサーリンク
