Aurora DSQL の書き込み・読み取り性能を AWS Lambda から検証してみた

Aurora DSQL の書き込み・読み取り性能を AWS Lambda から検証してみた

Lambda から Aurora DSQL に接続し、様々な構成で実測を行いました。並列実行やマルチリージョン構成でのレイテンシの差、100接続/秒の制限を回避する実践的なコネクション管理など、分散DBを本番投入する前に知っておきたい性能のトレードオフをまとめています。
2026.03.09

AWS の新しいサーバーレス分散データベースである Aurora DSQL。実際のワークロードでどのような性能特性を示すのかを把握するため、AWS Lambda を用いて書き込み・読み取り性能を計測しました。

本記事では、並列数やリージョン間の物理的距離(クロスリージョン)による影響や、DB コネクション再利用の有無による性能差を検証しています。さらに、シングルリージョンとマルチリージョン構成における書き込み性能のトレードオフの確認も試みました。

1. 検証環境

項目
Lambda ランタイム Node.js 22.x / ARM64 (Graviton)
Lambda メモリ 1,769MB(1 vCPU 相当)
Lambda リージョン ap-northeast-1(東京)
DSQL クラスタ ap-northeast-1(東京)/ us-west-2(オレゴン)各シングルリージョン、東京+ソウル マルチリージョン(witness: 大阪)
並列実行基盤 Step Functions Map ステート(MaxConcurrency で並列数制御)
コネクタ @aws/aurora-dsql-postgresjs-connector

テストテーブルは以下の定義です。

CREATE TABLE perf_test (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  data TEXT,
  created_at TIMESTAMPTZ DEFAULT now()
);

2. IAM ロールを用いた最小権限設計

Step Functions のロールは Lambda の呼び出し権限のみ、Lambda のロールは DSQL への接続権限のみを持ちます。

Lambda 実行ロールのポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "dsql:DbConnect",
      "Resource": [
        "arn:aws:dsql:ap-northeast-1:<account-id>:cluster/<cluster-id-tokyo>",
        "arn:aws:dsql:us-west-2:<account-id>:cluster/<cluster-id-oregon>"
      ]
    }
  ]
}

dsql:DbConnect は一般ユーザーとしての接続を許可するアクションです。Resource を特定クラスタの ARN に限定することで、他のクラスタへの接続も防ぎます。

DB ロールと IAM の紐付け

-- admin で接続して実行
CREATE ROLE bench_user WITH LOGIN;
AWS IAM GRANT bench_user TO 'arn:aws:iam::<account-id>:role/<lambda-role-name>';
GRANT USAGE ON SCHEMA public TO bench_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO bench_user;

AWS IAM GRANT は DSQL 固有の構文で、IAM ロール ARN と DB ロールを紐付けます。この設定はクラスタごとに必要です(マルチリージョン構成では自動伝播します)。GRANT ... ON ALL TABLES は実行時点で存在するテーブルにのみ有効です。DSQL は ALTER DEFAULT PRIVILEGES をサポートしていないため、テーブルを追加した場合は再度 GRANT が必要でした。

3. Lambda 関数の実装

import { auroraDSQLPostgres } from "@aws/aurora-dsql-postgresjs-connector";

const ENDPOINTS = {
  "ap-northeast-1": process.env.DSQL_ENDPOINT_TYO,
  "us-west-2": process.env.DSQL_ENDPOINT_PDX,
};

let cachedSql = null;
let cachedRegion = null;

function getSql(region) {
  if (cachedSql && cachedRegion === region) return cachedSql;
  cachedSql = auroraDSQLPostgres({
    host: ENDPOINTS[region],
    username: "bench_user",
  });
  cachedRegion = region;
  return cachedSql;
}

export const handler = async (event) => {
  const op = event.op || "insert";
  const region = event.region || "ap-northeast-1";
  const cache = event.cache !== false;

  const start = Date.now();
  const sql = cache
    ? getSql(region)
    : auroraDSQLPostgres({ host: ENDPOINTS[region], username: "bench_user" });

  try {
    if (op === "insert") {
      const id = crypto.randomUUID();
      await sql`INSERT INTO perf_test (id, data) VALUES (${id}, ${"bench"})`;
    } else if (op === "select") {
      await sql`SELECT id, data FROM perf_test LIMIT 1`;
    }
    const ms = Date.now() - start;
    if (!cache) await sql.end();
    return { ok: true, op, region, cache, ms };
  } catch (e) {
    const ms = Date.now() - start;
    if (!cache) try { await sql.end(); } catch {}
    return { ok: false, op, region, cache, ms, error: e.message?.slice(0, 200) };
  }
};

cachedSql をグローバル変数に保持し、ウォームスタート時にコネクションを再利用します。公式コネクタが IAM 認証トークンの生成・リフレッシュを透過的に行うため、コネクション再利用時のトークン期限管理は不要です。
比較のため、event.cachefalse を指定すると都度接続となる実装も用意しました。

4. コネクション再利用の効果

並列度 1

再利用なし(都度 DB 接続)と再利用あり(DB コネクション保持)の比較です。

パターン 再利用なし 再利用あり
東京→東京 INSERT 222ms 21ms
東京→東京 SELECT 6ms
東京→オレゴン INSERT 1,512ms 106ms
東京→オレゴン SELECT 102ms

再利用なしでは TCP/TLS ハンドシェイクと IAM トークン生成が毎回発生します。特にクロスリージョンでは RTT が大きいためハンドシェイクの往復回数分だけ影響が増幅され、東京→オレゴンの INSERT は 1,512ms かかっています。再利用ありでは東京→東京 INSERT が 21ms、オレゴンでも 102〜106ms まで短縮され、純粋な RTT とほぼ一致しています。

並列実行(再利用なし)

Step Functions の Map ステートで Lambda を並列実行し、各 Lambda が 1 回ずつ DSQL に接続・操作する構成です。

東京→東京

並列度 op med(ms) p95(ms) rps
50 INSERT 162 612 28.3
100 INSERT 105 518 44.7
200 INSERT 95 263 48.7
50 SELECT 88 118 53.8
100 SELECT 88 143 48.8
200 SELECT 90 133 53.4

再利用なしでは rps が 50 前後で頭打ちになります。

東京→オレゴン

並列度 op med(ms) p95(ms) rps
50 INSERT 1,338 1,473 21.9
100 INSERT 1,188 1,473 24.3
200 INSERT 1,165 1,408 27.3
50 SELECT 1,064 1,301 24.4
100 SELECT 1,062 1,302 27.8
200 SELECT 1,057 1,125 28.3

オレゴンでは東京〜オレゴン間の RTT(約 100ms)× ハンドシェイクの往復回数分が加算され、med が 1,000ms を超える値になっています。

並列実行(再利用あり)

続いてコネクション再利用ありの結果です。

東京→東京

並列度 op med(ms) p95(ms) rps
50 INSERT 10 12 48.4
100 INSERT 10 12 58.1
200 INSERT 9 11 63.3
50 SELECT 4 5 64.0
100 SELECT 4 5 63.9
200 SELECT 4 5 66.4

東京→オレゴン

並列度 op med(ms) p95(ms) rps
50 INSERT 106 1,487 36.4
100 INSERT 106 107 62.3
200 INSERT 105 107 60.0
50 SELECT 100 102 62.3
100 SELECT 100 102 74.5
200 SELECT 100 101 69.6

コネクション再利用により、東京→東京の INSERT は med 9〜10ms、SELECT は 4ms に改善しました。オレゴンも med 100〜106ms まで低下し、純粋な RTT のみになっています。

5. 書き込みスループット

1 つの Lambda が 1,000 件を逐次 INSERT し、それを並列度を変えて実行しました。コネクション再利用あり、東京→東京の構成です。各並列度はシーケンシャルに実行し、同時実行による干渉を排除しています。

並列度 合計件数 wall(s) 合計 rps Lambda 単体 rps
1 1,000 9.7 103 105
10 10,000 10.0 1,002 111
20 20,000 9.8 2,048 113
30 30,000 9.8 3,065 117
40 40,000 10.2 3,905 116
50 50,000 10.0 4,996 116
100 100,000 20.0 5,000 117

Lambda 単体の INSERT スループットは約 115 rps で安定しており、並列化でほぼ線形にスケールします。50 並列で約 5,000 rps に達しました。c=100 で合計 rps が伸びないのは Step Functions Map ステートの内部バッチ分割によるもので、DSQL 側の上限には到達していません。

6. シングル vs マルチリージョン

シングルリージョンとマルチリージョン(東京+ソウル、witness: 大阪)で INSERT / SELECT の性能差を確認しました。クラスタを 2 セット作成し、それぞれ計測して再現性を確認しています。Lambda は東京から東京エンドポイントに接続しています。

クラスタ作成所要時間

構成 所要時間
シングルリージョン 約 8 秒
マルチリージョン 約 100〜115 秒

マルチリージョンは 3 ステップ(各リージョンにクラスタ作成 + 相互ピアリング)が必要で、ACTIVE になるまで約 2 分かかります。

INSERT(再利用あり, 東京→東京)

並列度 シングル med(ms) マルチ med(ms) 倍率
50 10 65 6.5x
100 10 64 6.4x
200 9 64 7.1x

SELECT(再利用あり, 東京→東京)

並列度 シングル med(ms) マルチ med(ms) 倍率
50 4 4 1.0x
100 4 4 1.0x
200 4 4 1.0x

INSERT はマルチリージョンで約 6〜7 倍遅くなりました。マルチリージョンでは強い一貫性を保証するためコミット時にリージョン間の同期オーバーヘッドが発生するためです。一方 SELECT はローカルリージョンで完結するため差がありません。

7. まとめ

単一テーブルへの単純な INSERT / SELECT による小規模な検証ですが、DSQL の性能特性と、サーバーレス環境から利用する際の勘所を明確にできました。

最大のポイントは DB コネクションの再利用です。再利用により INSERT は 10ms 以下、SELECT は 4〜6ms となり、都度接続と比べて 10〜20 倍改善します。書き込みスループットも、Lambda 単体(約 115 rps)から 50 並列で 5,000 rps までほぼ線形にスケールすることを確認できました。

また、マルチリージョン構成では強い一貫性を保証する同期オーバーヘッドにより、INSERT が約 6〜7 倍遅くなります。一方、ローカル読み取りとなる SELECT 性能は変わりません。可用性と書き込み性能のトレードオフには注意が必要です。

重要な注意点は、DSQL の接続レート制限(100 接続/秒・緩和不可のハードリミット)です。Lambda から実戦投入する際はコネクションの再利用を大前提とし、スパイク時のコールドスタート集中を避けるため、Provisioned Concurrency の活用や同時実行数の制御が不可欠です。

マルチリージョンやクロスリージョンで高いスループットが要求されるケースでは、DSQL への直接アクセスを減らす工夫が重要になります。書き込みは SQS などでバッファリングする非同期バルク処理が有効です。一方、読み取りはリードレプリカに頼れないため、アプリケーション側のキャッシュや CloudFront によるページキャッシュの活用など、クラウドネイティブな全体設計をご検討ください。

参考リンク

この記事をシェアする

FacebookHatena blogX

関連記事