0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Redshift Data API の3つのアップデートを試してみた

0
Last updated at Posted at 2026-07-31

背景・目的

Amazon Redshift Data API は、ドライバ・接続・ネットワーク設定・認証情報を自前で管理せずに SQL を実行できる非同期 API です。永続接続を持たず、セキュアな HTTP エンドポイントと AWS SDK 経由で SQL を投げられるため、Lambda や Step Functions などの呼び出し元(サーバーレスの実行環境やワークフロー)から Redshift を叩く用途で広く使われています。
一方で、これまでの Data API には運用上のいくつかの面倒な点がありました。呼び出しが非同期のため「実行したあと、完了するまで DescribeStatement を何度もポーリングする」必要があり、API 呼び出し回数とレイテンシーが増えます。

またセッションを再利用する場合、各実行のレスポンスから SessionId を拾って自前で追跡・一覧管理する必要がありました(従来からセッション ID 自体は取得可能でしたが、アクティブなセッションを列挙する手段がありませんでした)。
さらにバッチ実行(BatchExecuteStatement)は既定で全体を単一トランザクションで扱うため、1 件でも失敗すると全体がロールバックされる、という制約がありました。

上記に関して、先日3つの機能がData APIに追加されましたので、本記事では実際に試してみます。

まとめ

項目 内容
これは何 Amazon Redshift Data API に追加された、ポーリング削減・セッション可視化・バッチのトランザクション制御という 3 つの運用改善機能
何ができる ①Long Polling で完了待ちの DescribeStatement 連打をなくす ②ListSessions で再利用セッションを列挙・フィルタする ③AUTO_COMMIT で「1 件失敗しても、成功済みの他の文はロールバックされない」バッチ実行と、バッチ全体でのパラメータ再利用ができる
使いどころ Step Functions・Lambda・Airflow 等から Data API を叩く ETL / 管理スクリプト。オーケストレータ側のポーリング用待機ステップ・状態管理・API 呼び出し回数を減らせる
重要な上限 WaitTimeSeconds は最大 30 秒待機。BatchExecuteStatement の SQL は配列順にシリアル実行。1 セッションで並列クエリ不可、セッション数は 1 クラスタ/ワークグループあたり最大 500
提供範囲 Provisioned と Serverless の両方。Data API 対応の全商用リージョンおよび GovCloud (US) で一般提供(GA)

概要

用語の整理

本記事で繰り返し出てくる用語を整理します。

用語 説明
Data API Redshift に対して、接続やドライバを管理せずに SQL を実行できる非同期 HTTP API。呼び出しはすべて非同期で、結果は後から取得する
ポーリング(polling) ここでのポーリングは「SQL が完了したかを繰り返し API で確認しにいく」こと。ネットワークのポーリングやイベントループのポーリングとは文脈が異なる
Long Polling 同期レスポンスを最大 30 秒まで待ってから返す方式。終わっていれば結果を、終わっていなければその時点の状態を返す。上記の繰り返しポーリングを減らすための機能
セッション 複数クエリで接続を再利用するための実行コンテキスト。ここでのセッションは Data API の実行セッションを指し、ログイン/ブラウザのセッションとは別物
compute target(コンピュートターゲット) SQL の実行先。Redshift の provisioned クラスタか、Redshift Serverless のワークグループのいずれかを指す
トランザクション 複数 SQL をまとめてコミット/ロールバックする単位。バッチ実行のふるまいを決める

何が追加されたか

Amazon Redshift Data API に、次の 3 つの機能が追加されました。公式の What's New には次のようにあります。

Amazon Redshift Data API introduces new capabilities that reduce the number of API calls to retrieve SQL statement metadata or results, provide visibility into sessions, and allow batch statements to execute on separate transactions.

(意訳)Amazon Redshift Data API に、SQL ステートメントのメタデータ・結果取得のための API 呼び出し回数を削減し、セッションの可視性を提供し、バッチステートメントを別々のトランザクションで実行できるようにする新機能が追加された。

利用者から見ると「①完了を待つための呼び出しが減る」「②今使っているセッションが見える」「③バッチの失敗の巻き込みを制御できる」という 3 点です。
以下に機能ごと、整理します。

① Long Polling(ロングポーリング)

SQL が terminal state(完了・失敗などの最終状態)に達するのを、クライアントが繰り返しポーリングして待つのではなく、同期レスポンスを最大 30 秒まで待ってから返す方式です。その間に SQL が終われば結果(または最終状態)を、終わらなければその時点の状態を返します。公式ドキュメントには次のようにあります。

The optional WaitTimeSeconds parameter has the Data API wait up to 30 seconds when the operation submits a new query or is against an in-progress query. This reduces the number of poll requests, resulting in fewer round trips and lower latency.

(意訳)オプションの WaitTimeSeconds パラメータを指定すると、新しいクエリの投入時や実行中のクエリに対して、Data API は最大 30 秒まで待機する。これによりポーリングのリクエスト回数が減り、ラウンドトリップの削減とレイテンシーの低下につながる。

使い方は、ExecuteStatement / BatchExecuteStatement / DescribeStatement / GetStatementResult / GetStatementResultV2 の各 API で WaitTimeSeconds パラメータを指定します。上限は 30 秒で、この時間内に SQL が終わればその結果(または最終状態)を待って返し、終わらなければタイムアウトして応答が返ります。完了確認のための DescribeStatement 連打が不要になり、API 呼び出し回数とアプリ側のポーリングロジックを減らせます。なお、SQL の実行時間そのものが短くなるわけではなく、削減されるのはポーリングの往復回数です。

② ListSessions(セッション列挙)

複数クエリでセッションを再利用するアプリケーションが、アクティブなセッションを列挙し、status・compute target・database でフィルタできるようになりました。公式の What's New には次のようにあります。

Applications that reuse sessions across multiple queries can now enumerate active sessions and filter by status, compute target, or database, eliminating the need to track session identifiers externally.

(意訳)複数クエリでセッションを再利用するアプリケーションは、アクティブなセッションを列挙し、ステータス・コンピュートターゲット・データベースでフィルタできるようになり、セッション識別子を外部で追跡する必要がなくなった。

補足すると、従来から SessionId 自体は ExecuteStatement/BatchExecuteStatement のレスポンスや DescribeStatement/ListStatements で取得できました。
今回の ListSessions が新たに提供したのは「アクティブなセッションを一覧で列挙し、条件でフィルタする」手段です。これにより、セッション ID を外部の KVS 等に自前で保持・一覧管理していた構成を、API 側の列挙・フィルタで置き換えられます。

ListSessions のフィルタ条件は API リファレンス上、次のように定義されています。

  • Status: AVAILABLE(SQL 実行可能)/ BUSY(SQL 実行中)/ CLOSED(クローズ済み)。未指定時は AVAILABLEBUSY を返す。
  • compute target: provisioned なら ClusterIdentifier、Serverless なら WorkgroupName で絞り込む(両方は同時指定不可)。
  • Database: 特定のデータベースに接続しているセッションのみ返す。
  • MaxResults: 1 レスポンスあたりの最大件数。最大値は 100 で、超過分は NextToken でページングする。

③ 柔軟なバッチ実行(Flexible batch execution)

BatchExecuteStatementExecutionMode パラメータが追加されました。前提として、バッチ内の SQL は配列順にシリアル実行され、前の文が完了するまで次の文は開始しません。公式ドキュメントには次のようにあります。

The SQL statements in the Sqls parameter of the BatchExecuteStatement API operation run serially in the order of the array. Subsequent SQL statements don't start until the previous statement completes. By default, all SQL statements are run as a single transaction. If any SQL statement fails, all work is rolled back. Use the ExecutionMode parameter to control transaction behavior:

  • TRANSACTION (default) — The service runs all SQL statements as a single transaction and commits or rolls back all of them together.
  • AUTO_COMMIT — Each SQL statement is committed individually. A failure of one statement does not affect the others.

(意訳)BatchExecuteStatementSqls パラメータ内の SQL は配列順にシリアル実行され、前の文が完了するまで次は開始しない。既定では全 SQL が単一トランザクションで実行され、いずれかが失敗すると全処理がロールバックされる。トランザクションのふるまいは ExecutionMode パラメータで制御する。TRANSACTION(既定)は全 SQL を単一トランザクションとして扱い一括でコミット/ロールバックする。AUTO_COMMIT は各 SQL を個別にコミットし、1 件の失敗が他に影響しない。

ExecutionMode の値は次の 2 つです。

ExecutionMode ふるまい 使いどころ
TRANSACTION(既定) 全 SQL を単一トランザクションで実行。1 件失敗で全体ロールバック 全件成功が前提の一括処理
AUTO_COMMIT 各 SQL を個別にコミット。1 件の失敗が、成功済みの他の文をロールバックしない ETL パイプライン・管理スクリプトなど部分完了を許容できる処理

BatchExecuteStatementSqlParameter の配列を受け取れるようになり、パラメータをバッチ全体で再利用できます。パラメータを一度定義すれば任意の文から参照でき、各クエリにリテラル値を埋め込む必要がなくなります。

In addition, BatchExecuteStatement now accepts an array of SqlParameter, enabling parameter reuse across all statements in a batch: define parameters once and reference them in any statement, eliminating the need to embed literal values in each query.

(意訳)加えて BatchExecuteStatementSqlParameter の配列を受け取れるようになり、バッチ内の全ステートメントでパラメータを再利用できる。パラメータを一度定義すれば任意の文から参照でき、各クエリにリテラル値を埋め込む必要がなくなる。

セッション再利用まわりの上限

ListSessions を検討する前提として、セッション再利用には次の上限があります。公式ドキュメントには次のようにあります。

The maximum value of SessionKeepAliveSeconds is 24 hours. The session can last for at most 24 hours. The maximum number of sessions per Amazon Redshift cluster or Redshift Serverless workgroup is 500. You can only run one query at a time in a session.

(意訳)SessionKeepAliveSeconds の最大値は 24 時間。セッションは最大 24 時間持続する。1 クラスタ/ワークグループあたりのセッション数は最大 500。1 セッションで同時に実行できるクエリは 1 つだけ。

特に「1 セッションで並列クエリ不可(前のクエリが終わるまで次を実行できない)」は、セッション再利用パターンを組む際に最初に踏む制約です。

提供範囲

3 機能とも、Amazon Redshift Provisioned と Amazon Redshift Serverless の両方で、Data API に対応する全商用リージョンおよび GovCloud (US) リージョンで一般提供(GA)されています。

実践

前提

本検証は下記の環境を利用しました。

  • Redshift Serverless(ワークグループ: skills-lab-wg / データベース: skillsdb)
  • AWS CLI 2.36.13

なお、--wait-time-seconds オプションは AWS CLI 2.36.x 以降で利用できます。2.35 系以前には存在しないため、古い場合はアップデートが必要です。

1. Long Polling で完了を待って結果を受け取る

  1. execute-statement--wait-time-seconds 30 を付けてクエリを実行します

    aws redshift-data execute-statement \
      --workgroup-name skills-lab-wg \
      --database skillsdb \
      --sql "SELECT 1 AS result;" \
      --wait-time-seconds 30 \
      --region ap-northeast-1
    
  2. レスポンスに "Status": "FINISHED" が含まれており、execute-statement 1 回の返り値だけで完了状態を確認できました。describe-statement を追加で呼ぶ必要がありませんでした

    {
        "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",
        "CreatedAt": "2026-08-01T00:07:45.571000+09:00",
        "DbUser": "XXXX:XXXX",
        "Database": "skillsdb",
        "WorkgroupName": "skills-lab-wg",
        "Status": "FINISHED",
        "RedshiftPid": 1073872995,
        "HasResultSet": true
    }
    

2. AUTO_COMMIT で「成功済みの文を巻き込まない」バッチを実行する

全件成功のパターン

  1. batch-execute-statement--execution-mode AUTO_COMMIT を付けて、テーブル作成と INSERT を 3 文まとめて実行します

    aws redshift-data batch-execute-statement \
      --workgroup-name skills-lab-wg \
      --database skillsdb \
      --execution-mode AUTO_COMMIT \
      --sqls "CREATE TABLE IF NOT EXISTS stg_test (id int);" \
             "INSERT INTO stg_test VALUES (1);" \
             "INSERT INTO stg_test VALUES (2);" \
      --region ap-northeast-1
    
  2. 返ってきた Id を使って完了を待ちます

    aws redshift-data describe-statement \
      --id "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" \
      --wait-time-seconds 30 \
      --region ap-northeast-1
    
  3. SubStatements に各文の結果が含まれ、全文 FINISHED、末尾に "ExecutionMode": "AUTO_COMMIT" が付いていることを確認しました

    {
        "Status": "FINISHED",
        "SubStatements": [
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:1",
                "Status": "FINISHED",
                "QueryString": "CREATE TABLE IF NOT EXISTS stg_test (id int);",
                "ResultRows": 0
            },
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:2",
                "Status": "FINISHED",
                "QueryString": "INSERT INTO stg_test VALUES (1);",
                "ResultRows": 1
            },
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:3",
                "Status": "FINISHED",
                "QueryString": "INSERT INTO stg_test VALUES (2);",
                "ResultRows": 1
            }
        ],
        "ExecutionMode": "AUTO_COMMIT"
    }
    

1文失敗しても成功済みはロールバックされないパターン

  1. 中間の 2 番目に意図的に型エラーになる値('invalid_value')を入れてバッチを実行します

    aws redshift-data batch-execute-statement \
      --workgroup-name skills-lab-wg \
      --database skillsdb \
      --execution-mode AUTO_COMMIT \
      --sqls "INSERT INTO stg_test VALUES (10);" \
             "INSERT INTO stg_test VALUES ('invalid_value');" \
             "INSERT INTO stg_test VALUES (20);" \
      --region ap-northeast-1
    
  2. describe-statement でバッチの結果を確認します。バッチ全体は FAILED、2 番目のサブステートメントに ERROR: invalid input syntax for integer: "invalid_value" が表示されました

    {
        "Error": "Queries failed in AUTO_COMMIT mode: [2]",
        "Status": "FAILED",
        "SubStatements": [
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:1",
                "Status": "FINISHED",
                "QueryString": "INSERT INTO stg_test VALUES (10);",
                "ResultRows": 1
            },
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:2",
                "Error": "ERROR: invalid input syntax for integer: \"invalid_value\"",
                "Status": "FAILED",
                "QueryString": "INSERT INTO stg_test VALUES ('invalid_value');",
                "ResultRows": -1
            },
            {
                "Id": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX:3",
                "Status": "FINISHED",
                "QueryString": "INSERT INTO stg_test VALUES (20);",
                "ResultRows": 1
            }
        ],
        "ExecutionMode": "AUTO_COMMIT"
    }
    
  3. テーブルの実データで確認します

    aws redshift-data execute-statement \
      --workgroup-name skills-lab-wg \
      --database skillsdb \
      --sql "SELECT id FROM stg_test ORDER BY id;" \
      --wait-time-seconds 30 \
      --region ap-northeast-1
    
    aws redshift-data get-statement-result \
      --id "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" \
      --region ap-northeast-1
    
    {
        "Records": [
            [{"longValue": 1}],
            [{"longValue": 2}],
            [{"longValue": 10}],
            [{"longValue": 20}]
        ],
        "TotalNumRows": 4
    }
    
  4. id=1・2(最初のバッチ)と id=10・20(今回のバッチ)の 4 件が残っていました。2 番目が失敗しても、1 番目(id=10)と 3 番目(id=20)はコミット済みのまま残ることを確認しました。また、失敗した文(2 番目)の後も 3 番目が実行を継続していることも確認できました

エラーメッセージ "Queries failed in AUTO_COMMIT mode: [2]"[2] は失敗したサブステートメントの番号(1始まり)を示しており、どの文が失敗したかをプログラムで特定しやすい形式になっています。

3. アクティブなセッションを列挙・フィルタする

セッションの作成と一覧表示

  1. --session-keep-alive-seconds を付けてセッションを 2 つ作成します。レスポンスに SessionId が含まれます

    aws redshift-data execute-statement \
      --workgroup-name skills-lab-wg \
      --database skillsdb \
      --sql "SELECT 1;" \
      --session-keep-alive-seconds 300 \
      --region ap-northeast-1
    
  2. list-sessions でアクティブなセッションを一覧表示します

    aws redshift-data list-sessions \
      --region ap-northeast-1
    
  3. 作成した 2 セッションが AVAILABLE 状態で表示されました。SessionTtl でいつ期限切れになるかも確認できます

    {
        "Sessions": [
            {
                "SessionId": "b3d65c55-XXXX-XXXX-XXXX-e8c01d2c99be",
                "Status": "AVAILABLE",
                "Database": "skillsdb",
                "WorkgroupName": "skills-lab-wg",
                "SessionAliveSeconds": 300,
                "SessionTtl": "2026-08-01T00:42:14+09:00"
            },
            {
                "SessionId": "b9ecaa84-XXXX-XXXX-XXXX-b4c16e349618",
                "Status": "AVAILABLE",
                "Database": "skillsdb",
                "WorkgroupName": "skills-lab-wg",
                "SessionAliveSeconds": 300,
                "SessionTtl": "2026-08-01T00:41:25+09:00"
            }
        ]
    }
    

BUSY/AVAILABLE フィルタ

  1. セッションを再利用して重いクエリを実行しながら、--status BUSY--status AVAILABLE でフィルタの動作を確認します。なお、セッションを再利用する際は --session-id を指定し、--database は指定しません(両方指定すると ValidationException になります)。

    # セッション再利用でクエリ投入(--database は不要)
    aws redshift-data execute-statement \
      --sql "SELECT a.table_name, b.table_name, c.table_name \
             FROM information_schema.tables a \
             CROSS JOIN information_schema.tables b \
             CROSS JOIN information_schema.tables c LIMIT 1000000;" \
      --session-id "b3d65c55-XXXX-XXXX-XXXX-e8c01d2c99be" \
      --region ap-northeast-1 &
    
    # クエリ実行中に status でフィルタ
    aws redshift-data list-sessions --status BUSY   --region ap-northeast-1
    aws redshift-data list-sessions --status AVAILABLE --region ap-northeast-1
    
  2. クエリ実行中は --status BUSY でそのセッションのみ返り、--status AVAILABLE には表示されませんでした

    === BUSY のみ ===
    +----------------------------------------+---------+
    |                   id                   | status  |
    +----------------------------------------+---------+
    |  b3d65c55-XXXX-XXXX-XXXX-e8c01d2c99be  |  BUSY   |
    +----------------------------------------+---------+
    
    === AVAILABLE のみ ===
    (0件)
    
  3. このフィルタを使うと「今クエリを受け付けられるセッションだけ取得して次のクエリを投入する」「詰まっているセッションを特定する」といった運用が、セッション ID の外部管理なしに実現できます。

考察

  • ① Long Polling は、Step Functions・Lambda・Airflow などから Data API を叩くパイプラインで効きます。SQL 自体が速くなるわけではありませんが、ポーリング用の待機ステップが減るため、Step Functions のように状態遷移数・実行時間で課金される構成ではコスト削減にもつながります
  • ③ AUTO_COMMIT は、複数 DDL/DML をまとめて流す初期化・メンテナンス処理で有効です。途中の 1 文が失敗しても成功済みの文はロールバックされず、後続文も継続実行されます(今回の検証で確認)。エラーレスポンスの "Queries failed in AUTO_COMMIT mode: [N]" で失敗した文番号を特定できます
  • ② ListSessions は、一時テーブルやトランザクションをまたぐ処理でセッションを複数管理・監視する用途に向いています。セッション ID の外部管理が不要になる一方、「1 セッションで並列クエリ不可」「最大 500 セッション」の上限は変わりません
  • 3 機能とも Provisioned・Serverless の両対応で全リージョン提供のため、環境を選ばず適用できます

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?