Amazon Aurora DSQL がGAされたので料金について調べてみた
お疲れさまです。とーちです。
Amazon Aurora DSQLが一般公開されたので、気になる料金について詳しく調べてみました。
Aurora DSQLは分散型のサーバーレスSQLデータベースで、今回のGA(一般公開)に伴い周辺AWSサービスとの統合など、できることが大幅に増えています。
GAに伴う変更点については以下の記事に詳しく書かれていますので、こちらをご参照ください。
また、DSQLの基本や注意点等については先人がまとめた記事があるので、こちらも併せてご参照ください。
料金について
GAに伴い気になるのは料金ではないでしょうか?私は一番気になります。
最新かつ正確な情報は以下の公式ページをご参照いただきたいのですが、なかなか料金ページを読んでも具体的な料金感のイメージがつかなかったので、私なりに調べたことを記載します。
以下、東京リージョンで使う場合の料金を記載していきます。
基本的な料金構成
Amazon Aurora DSQLの主要な料金は以下の2つです。このほかにデータ転送コストやバックアップコストもかかります。
- DPU:100万ユニットあたり10.00ドル
- ストレージ:1GBあたり月額0.40ドル
DPUとは何なのか
DPUというのが聞き慣れない概念なので少し調べてみました。結論からいうと、詳細な計算式などは2025年5月28日現在では公開されていないようです。DynamoDBのように「1書き込みあたり何DPUを消費する」といったような情報は、私が確認した限りでは見つけられませんでした。
唯一具体例として見つけられたのが、料金ページの以下の記載です。
Your results may vary, but to establish a reference for what can be accomplished with 100K DPUs, we executed a small benchmark with a 95/5 read/write mix using transactions derived from the TPC-C benchmark. Based on this benchmark, 100K DPUs were equivalent to ~700,000 TPC-C transactions.
(日本語訳:結果には個人差がありますが、100K DPUsで達成可能なパフォーマンスの基準を確立するため、TPC-Cベンチマークから導出したトランザクションを使用し、95/5の読み取り/書き込み比率で小さなベンチマークを実施しました。このベンチマーク結果に基づき、100K DPUsは~700,000 TPC-Cトランザクションに相当します。)
TPC-C benchmarkとはオンライン取引処理(OLTP)の性能を測定するためのベンチマークだそうです。(参考:https://www.tpc.org/TPC_Documents_Current_Versions/pdf/tpc-c_v5.11.0.pdf)
上記の文章は、このベンチマークを元にしたトランザクションを使い、それを読み取り95%、書き込み5%の比率で700,000回のトランザクションを実行したとき、100K DPUs(10万DPU)を消費するというふうに読み取れます。
TPC-C benchmarkでは、New-Order(新規注文)やPayment(支払い)などの複数種類のトランザクションが決められた比率で実行されると私は理解しているので、それに従うと、読み取り95%、書き込み5%の比率にはならないような気がします。このあたりの矛盾はよく分かりませんが、ざっくり読み取り95%、書き込み5%比率のトランザクションを700,000回行うと、100K DPUs消費すると考えておくのがいいかもしれません。
CloudWatchメトリクスでDPU使用量を確認する
また最終的には、動かしたいワークロードを実際に動かしてみて、CloudWatchメトリクスで実際に使用されたDPUを計測するのが最も確実です。
CloudWatchメトリクスでは、以下のDPUを測定することができます。(参考)
- ReadDPU: 読み取りアクティブ使用コンポーネントの近似値
- WriteDPU: 書き込みアクティブ使用コンポーネントの近似値
- ComputeDPU: 計算アクティブ使用コンポーネントの近似値
- MultiRegionWriteDPU: マルチリージョン書き込みアクティブ使用コンポーネントの近似値
- TotalDPU: 総アクティブ使用コンポーネントの近似値
ComputeDPUはJOINやソート等の際に使われるのでしょうか?上記以上の説明がないので分かりませんが、これらのメトリクスで一日あたり、一ヶ月あたりのDPU量を計測するようにしましょう。
ストレージ料金について
またストレージ料金についてですが、こちらはDPUと比べると比較的わかりやすいかとは思います。
ストレージはデータベースの合計サイズに基づいて、GB/月単位で測定されます。
また、ポイントとしては、マルチリージョンクラスターの場合、各リージョンのクラスターごとストレージ課金が発生するのは覚えておきましょう。
Storage is based on the total size of your database and measured in GB-months. You are only charged for one logical copy of your data per single-Region cluster or multi-Region peered cluster.(Amazon Aurora DSQL, the fastest serverless distributed SQL database is now generally available | AWS News Blogより)
(日本語訳:ストレージは、データベースの総サイズに基づいて計算され、GB-月単位で測定されます。単一リージョン クラスターまたはマルチリージョン ピアード クラスターごとに、データの論理コピー 1 つ分の料金が課金されます。)
実際のDPU消費量を測定してみた
実際にどのような処理でどのくらいのDPUが消費されるのかを確認してみました。
接続環境の準備
まず準備です。Aurora DSQLではAWS認証情報も利用してアクセスするようになっています。そこで以下のようなDockerfileでコンテナイメージを作りました。
FROM postgres:15
# システム情報を確認
RUN uname -m
# AWS CLI v2をアーキテクチャに応じてインストール
RUN apt-get update && apt-get install -y curl unzip \
&& ARCH=$(uname -m) \
&& if [ "$ARCH" = "aarch64" ]; then \
curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"; \
else \
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"; \
fi \
&& unzip awscliv2.zip \
&& ./aws/install \
&& rm -rf awscliv2.zip aws \
&& apt-get clean
WORKDIR /app
postgresのイメージにAWS CLIを追加しただけのものです。そして、このイメージを docker build -t postgre-in-aws-cred .
でビルドしたあと以下のコマンドで起動します。
docker run --rm -it \
-v ${HOME}/.aws:/root/.aws:ro \
-e AWS_PROFILE=container \
postgre-in-aws-cred:latest \
bash
ポイントは${HOME}/.aws
をコンテナ上の /root/.aws
にマウントしているところです。これで普段使っているクレデンシャル情報をコンテナ上でも使用できるようにしました。
また -e
で環境変数 AWS_PROFILE
を設定することで指定したプロファイルをデフォルトで使用するようにしています。
Aurora DSQLへの接続
この状態でコンテナ上で以下のコマンドを実行するとAurora DSQLに接続できます。(パスワードが聞かれるのでマネージメントコンソール上で確認した認証トークンを入れてください)
psql --dbname postgres --username admin --host <エンドポイント名>
エンドポイント名の箇所にはマネージメントコンソールの以下の部分を入力するようにしてください。
接続できると以下のようにSQLコマンドを実行できるはずです。(クライアントとサーバでバージョンが違うというメッセージが出ちゃってますね)
root@f061078ce848:/app# psql --dbname postgres --username admin --host ***.dsql.ap-northeast-1.on.aws
Password for user admin:
psql (15.13 (Debian 15.13-1.pgdg120+1), server 16.9)
WARNING: psql major version 15, server major version 16.
Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off)
Type "help" for help.
postgres=> SELECT version();
version
---------------
PostgreSQL 16
(1 row)
CloudWatchメトリクスの設定
続いて、CloudWatchメトリクスですが、以下の設定で確認しました。
統計を合計にすることで対象の時間帯に合計でDPUをどれだけ消費したかを計測します。(1分間に計測されたDPU消費数の合計を確認)
それでは実際にSQLを流してそれぞれのDPU消費量を見ていきましょう。
テスト1:INSERT処理のDPU消費
下記のようなSQLで3,000件インサートします(5,000件インサートしようとしたらERROR: transaction row limit exceeded
となったため3,000件で実施)
postgres=> SELECT 'INSERT Test Start: ' || NOW() as test_start;
test_start
--------------------------------------------------
INSERT Test Start: 2025-05-27 23:58:43.012188+00
(1 row)
postgres=> CREATE TABLE dpu_test_insert (
id INTEGER PRIMARY KEY,
name VARCHAR(50),
value INTEGER
);
CREATE TABLE
-- 3,000件INSERT
postgres=> INSERT INTO dpu_test_insert (id, name, value)
SELECT
generate_series,
'name_' || generate_series,
(random() * 1000)::INTEGER
FROM generate_series(1, 3000);
INSERT 0 3000
postgres=> SELECT 'INSERT Test End: ' || NOW() as test_end;
test_end
-----------------------------------------------
INSERT Test End: 2025-05-27 23:58:57.40972+00
(1 row)
-- 結果確認
postgres=> SELECT COUNT(*) as inserted_count FROM dpu_test_insert;
inserted_count
----------------
3000
(1 row)
2025-05-27 23:58(UTC)時点のメトリクスは以下でした。
INSERT(3,000件)なので、WriteDPUが一番多くかかってますが、その他のDPUも多少消費されてますね。
テスト2:SELECT処理のDPU消費
続いてSELECT処理です。
postgres=> SELECT 'SELECT Test Start: ' || NOW() as test_start;
test_start
--------------------------------------------------
SELECT Test Start: 2025-05-28 00:01:18.075355+00
(1 row)
-- 全件検索
postgres=> SELECT COUNT(*) FROM dpu_test_insert;
count
-------
3000
(1 row)
-- 条件付き検索
postgres=> SELECT COUNT(*) FROM dpu_test_insert WHERE value > 500;
count
-------
1546
(1 row)
-- 範囲検索
postgres=> SELECT * FROM dpu_test_insert WHERE id BETWEEN 500 AND 1000;
-- ソート処理
postgres=> SELECT * FROM dpu_test_insert ORDER BY value DESC LIMIT 100;
-- 文字列検索
postgres=> SELECT COUNT(*) FROM dpu_test_insert WHERE name LIKE 'name_1%';
count
-------
1111
(1 row)
postgres=> SELECT 'SELECT Test End: ' || NOW() as test_end;
test_end
------------------------------------------------
SELECT Test End: 2025-05-28 00:01:58.554174+00
(1 row)
2025-05-28 00:01(UTC)時点のメトリクスは以下でした。
今度はWriteは消費なしですね。
テスト3:集計処理のDPU消費
続いて集計処理のテストをしてみます。
postgres=> SELECT 'AGGREGATION Test Start: ' || NOW() as test_start;
test_start
-------------------------------------------------------
AGGREGATION Test Start: 2025-05-28 00:04:36.413594+00
(1 row)
-- 基本統計
postgres=> SELECT
COUNT(*) as total_count,
AVG(value) as avg_value,
MIN(value) as min_value,
MAX(value) as max_value,
STDDEV(value) as std_dev
FROM dpu_test_insert;
total_count | avg_value | min_value | max_value | std_dev
-------------+----------------------+-----------+-----------+------------------
3000 | 504.9780000000000000 | 0 | 1000 | 290.600985018114
(1 row)
-- グループ集計
postgres=> SELECT
CASE
WHEN value < 250 THEN 'low'
WHEN value < 500 THEN 'medium_low'
WHEN value < 750 THEN 'medium_high'
ELSE 'high'
END as category,
COUNT(*) as count,
AVG(value) as avg_value,
MIN(value) as min_value,
MAX(value) as max_value
FROM dpu_test_insert
GROUP BY
CASE
WHEN value < 250 THEN 'low'
WHEN value < 500 THEN 'medium_low'
WHEN value < 750 THEN 'medium_high'
ELSE 'high'
END
ORDER BY category;
category | count | avg_value | min_value | max_value
-------------+-------+----------------------+-----------+-----------
high | 772 | 871.6619170984455959 | 750 | 1000
low | 751 | 122.7616511318242344 | 0 | 249
medium_high | 776 | 628.7152061855670103 | 500 | 749
medium_low | 701 | 373.6576319543509272 | 250 | 499
(4 rows)
-- 複雑な集計(パーセンタイル)
postgres=> SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY value) as q1,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY value) as median,
PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY value) as q3,
PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY value) as p90
FROM dpu_test_insert;
q1 | median | q3 | p90
-----+--------+-----+-----
249 | 514 | 755 | 901
(1 row)
postgres=> SELECT 'AGGREGATION Test End: ' || NOW() as test_end;
test_end
-----------------------------------------------------
AGGREGATION Test End: 2025-05-28 00:05:02.683022+00
(1 row)
2025-05-28 00:04(UTC)時点のメトリクスは以下でした。
00:05にちょっとだけはみ出てしまいましたが、00:05時点の値としては0.001以下の消費でしたので、上記の00:04の値に主たる消費量は含まれています。
意外とComputeDPUの消費量は先程のSELECTのテストと同じくらいでした。
テスト4:UPDATE処理のDPU消費
続いてUPDATEをしてみます。
-- 事前に新しいテーブル作成してデータ挿入
postgres=> CREATE TABLE dpu_test_update_fresh (
id INTEGER PRIMARY KEY,
name VARCHAR(50),
value INTEGER
);
CREATE TABLE
postgres=> INSERT INTO dpu_test_update_fresh (id, name, value)
SELECT
generate_series,
'name_' || generate_series,
(random() * 1000)::INTEGER
FROM generate_series(1, 3000);
INSERT 0 3000
postgres=> SELECT 'UPDATE Test New Table Start: ' || NOW() as test_start;
test_start
------------------------------------------------------------
UPDATE Test New Table Start: 2025-05-28 00:19:09.880252+00
(1 row)
-- 小規模UPDATE(500件)
postgres=> UPDATE dpu_test_update_fresh
SET name = 'updated_' || id
WHERE id <= 500;
UPDATE 500
-- 中規模UPDATE(1,500件)
postgres=> UPDATE dpu_test_update_fresh
SET value = value + 100
WHERE id BETWEEN 501 AND 2000;
UPDATE 1500
-- 大規模UPDATE(残り1,000件)
postgres=> UPDATE dpu_test_update_fresh
SET name = 'final_update_' || id
WHERE id > 2000;
UPDATE 1000
postgres=> SELECT 'UPDATE Test End: ' || NOW() as test_end;
test_end
------------------------------------------------
UPDATE Test End: 2025-05-28 00:19:32.841752+00
(1 row)
-- 更新結果確認
postgres=> SELECT COUNT(*) as updated_small FROM dpu_test_update_fresh WHERE name LIKE 'updated_%';
updated_small
---------------
500
(1 row)
2025-05-28 00:19(UTC)時点のメトリクスは以下でした。
WriteDPUは当然消費されるものと思ってましたが、意外とComputeDPUもそこそこ消費されてます。
テスト5:DROP処理のDPU消費
最後にDROPをテストしてみました。
postgres=> SELECT 'DROP Test Start: ' || NOW() as test_start;
test_start
------------------------------------------------
DROP Test Start: 2025-05-28 00:25:05.686845+00
(1 row)
postgres=> DROP TABLE dpu_test_insert;
DROP TABLE
postgres=> DROP TABLE dpu_test_update_fresh;
DROP TABLE
postgres=> SELECT 'DROP Test End: ' || NOW() as test_end;
test_end
----------------------------------------------
DROP Test End: 2025-05-28 00:25:42.439273+00
(1 row)
2025-05-28 00:25(UTC)時点のメトリクスは以下でした。
DROP処理でもWriteDPUとComputeDPUの両方が消費されていますね。
まとめ
以上、Amazon Aurora DSQLの料金について調べてみました。
今回の検証で分かったことをまとめると以下のようになります。
DPU消費の特徴
実際の測定結果から、各処理のDPU消費パターンが見えてきました。
-
INSERT処理(3,000件):ReadDPU:ComputeDPU:WriteDPU=0.04:0.49:4.04
- 書き込み処理が中心のため、WriteDPUが最も多く消費される
- データ生成処理でComputeDPUも相応に消費される
-
SELECT処理(複数の検索クエリ):ReadDPU:ComputeDPU:WriteDPU=0.59:0.38:0
- 読み取り処理のためWriteDPUは消費されない
-
集計処理(統計・グループ集計・パーセンタイル):ReadDPU:ComputeDPU:WriteDPU=0.43:0.36:0
- SELECT処理と似た傾向だが、複雑な計算処理の割にComputeDPUの消費は抑えられている
-
UPDATE処理(3,000件の段階的更新):ReadDPU:ComputeDPU:WriteDPU=1.14:0.82:4.66
- WriteDPUが最も多く消費されるのは当然として、ReadDPUも相応に消費される
- 更新対象の特定や条件評価などでComputeDPUも使用されている模様
-
DROP処理(テーブル削除):ReadDPU:ComputeDPU:WriteDPU=0.30:0.71:1.04
- WriteDPUが多く消費される
- DROPに伴うテーブル構造の処理なのか、ComputeDPUも意外と消費されている
料金感について
具体的な料金感については、実際のワークロードによって大きく異なるため一概には言えませんが、今回のテストでは3,000件程度のデータに対する基本的な操作で、それぞれ数DPU程度の消費でした。
例えば、今回のテストで最もDPU消費が多かったUPDATE処理でも合計約6.6DPUの消費でした。100万DPUあたり10.00ドルという料金体系を考えると、小規模なアプリケーションであれば月額数ドル程度から利用できそうです。ただし、大量のトランザクションを処理するアプリケーションでは、事前にしっかりとした検証が必要でしょう。
以上、とーちでした。