Kinesis Data Streams の 10 MiB レコードを Amazon Redshift のストリーミングインジェストで取り込んでみた

Kinesis Data Streams の 10 MiB レコードを Amazon Redshift のストリーミングインジェストで取り込んでみた

Amazon Kinesis Data Streams では、最大レコードサイズを 10 MiB まで引き上げられます。10 MiB に設定したストリームへ 100 KiB から 10 MiB を超えるサイズまでのダミー JSON を投入し、Amazon Redshift のストリーミングインジェストでどこまで取り込めるか、取り込んだレコードを Redshift の SQL でどう扱えるかを確認しました。
2026.08.30

はじめに

Amazon Redshift のストリーミングインジェストが、2026年8月27日のアップデートで Amazon Kinesis Data Streams の 10 MiB レコードに対応しました。

https://aws.amazon.com/about-aws/whats-new/2026/08/redshift-streaming-supports-kds-10mib-records

Kinesis Data Streams 側の最大レコードサイズの引き上げは、次の記事で紹介しています。

https://dev.classmethod.jp/articles/amazon-kinesis-data-streams-10x-larger-record-sizes/

本記事では、最大レコードサイズを 10 MiB に設定したストリームへ、100 KiB から 10 MiB + 1,000 B までのダミー JSON を投入しました。取り込めたサイズと、Redshift の SQL で参照するときの制約を確認します。

検証内容

ストリームへの投入と、Redshift 側での取り込み・参照の2段階に分けて進めました。

検証環境

Kinesis の大規模レコード(large records)を使えるリージョンは限られています。今回使用した us-east-1 は、Handle large records の Regions where large records are supported に含まれています。東京(ap-northeast-1)と大阪(ap-northeast-3)も対応リージョンです。

Redshift にはプロビジョニングされたクラスターを使用しました。ノードタイプ rg.xlarge の2ノード構成で、バージョンは 1.0.416217 です。

https://dev.classmethod.jp/articles/amazon-redshift-rg-instances-graviton/

大規模レコードの投入

最大レコードサイズを 10 MiB(CLI の指定は KiB 単位)に指定してストリームを作成しました。

aws kinesis create-stream \
  --stream-name devio-large-record-stream \
  --stream-mode-details StreamMode=ON_DEMAND \
  --max-record-size-in-ki-b 10240 \
  --region us-east-1

Handle large records に記載のとおり、--max-record-size-in-ki-b を指定しない場合の最大レコードサイズは既定の 1 MiB です。

DescribeStreamSummary の出力
{
    "StreamDescriptionSummary": {
        "StreamName": "devio-large-record-stream",
        "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/devio-large-record-stream",
        "StreamStatus": "ACTIVE",
        "StreamModeDetails": {
            "StreamMode": "ON_DEMAND"
        },
        "RetentionPeriodHours": 24,
        "OpenShardCount": 4,
        "ConsumerCount": 0,
        "MaxRecordSizeInKiB": 10240
    }
}

レコードは PutRecord を使用して1件ずつ投入しました。

aws kinesis put-record \
  --stream-name devio-large-record-stream \
  --partition-key 13 \
  --data fileb://records/r13.json \
  --region us-east-1

サイズごとに用意したファイルを --data fileb:// で渡しています。2 MiB 以上のレコードでは投入間隔を30秒空け、スロットリングされた場合は指数バックオフでリトライするようにしました。

サイズを 100 KiB から 10 MiB + 1,000 B まで段階的に変えて、計20回投入しました。

サイズ バイト数 件数 結果
100 KiB 102,400 2 成功
1 MiB 1,048,576 2 成功
1 MiB + 100 B 1,048,676 2 成功
2 MiB 2,097,152 1 成功
5 MiB 5,242,880 1 成功
9 MiB 9,437,184 1 成功
10 MiB − 1,000 B 10,484,760 1 成功
10 MiB − 100 B 10,485,660 2 成功
10 MiB 10,485,760 4 成功
10 MiB + 100 B 10,485,860 3 ValidationException
10 MiB + 1,000 B 10,486,760 1 ValidationException

成功が16件、失敗が4件でした。ダミー JSON は {"id":..,"label":..,"bytes":..,"payload":"<パディング>"} の形式で、パディング長を調整して目標バイト数に厳密に一致させています。

上限を超えたレコードでは、次のエラーが返りました。

An error occurred (ValidationException) when calling the PutRecord operation: 1 validation error detected: Value at 'data' failed to satisfy constraint: Member must have length less than or equal to 10485760

今回の検証では、データ部分が 10 MiB ちょうどの場合は成功し、100 バイト超過すると拒否されました。AWS の PutRecord API リファレンス では、base64 エンコード前のデータとパーティションキーの合計が最大レコードサイズ以下である必要があると説明されています。一方、今回使用したパーティションキーは1〜2バイトでしたが、10 MiB ちょうどのデータ4件はいずれも成功しました。公開仕様の記載とは異なる結果になったため、本記事では実測結果として記載します。ProvisionedThroughputExceededException によるリトライは、20件のいずれでも発生しませんでした。

ここまでのサイズは、いずれも生バイト長です。Quotas and limits の Data payload size にあるとおり、Kinesis の上限は base64 エンコード前のデータペイロードに対して定義されています。AWS CLI にファイルで渡したデータは base64 エンコードされて送信されますが、10,485,760 バイトのファイルが成功していることから、判定は生バイト長だと分かります。なお、ダミー JSON は hex 文字列と ASCII 記号だけで構成したので、文字数とバイト数が一致しています。

取り込みと参照

投入したストリームに対してストリーミングインジェスト用のマテリアライズドビューを作成し、列定義を確認しました。

作成手順は Getting started with streaming ingestion from Amazon Kinesis Data Streams のとおりです。ドキュメントの手順に今回のオブジェクト名を当てはめると、次の SQL になります。

CREATE EXTERNAL SCHEMA kds
FROM KINESIS
IAM_ROLE 'arn:aws:iam::123456789012:role/devio-redshift-streaming-role';

CREATE MATERIALIZED VIEW mv_large_record AS
SELECT approximate_arrival_timestamp,
       partition_key,
       sequence_number,
       kinesis_data
FROM kds."devio-large-record-stream";

REFRESH MATERIALIZED VIEW mv_large_record;

IAM ロールには、ストリームを読み取る権限(kinesis:GetRecords など)を付与しています。AUTO REFRESH YES を指定しない場合、リフレッシュは手動です。ストリーミングインジェストで参照できる列のうち、次の4列を選択しました。

approximate_arrival_timestamp timestamp without time zone
partition_key character varying(256)
sequence_number character varying(128)
kinesis_data binary varying(16777216)

ペイロードを受け取る kinesis_data の幅は 16,777,216 バイト、つまり 16 MiB です。Kinesis の上限である 10 MiB を上回っているため、Kinesis に投入可能なレコードは列幅の範囲内に収まります。

取り込まれたレコードをバイト数別に数えました。

バイト数 件数
102,400 2
1,048,576 2
1,048,676 2
2,097,152 1
5,242,880 1
9,437,184 1
10,484,760 1
10,485,660 2
10,485,760 4

合計は16件、94,575,640 バイトです。投入に成功したレコードと、取り込まれたレコードの件数・バイト数は完全に一致しており、切り詰めはありませんでした。sys_stream_scan_errors は0件でした。

Redshift Data API を使って SQL で参照しました。先頭64バイトを切り出して JSON 先頭の項目を取り出し、末尾14バイトも取り出しています。

SELECT octet_length(kinesis_data) AS bytes,
       regexp_substr(from_varbyte(substring(kinesis_data,1,64),'utf8'),'"id":"[^"]+"')    AS id_field,
       regexp_substr(from_varbyte(substring(kinesis_data,1,64),'utf8'),'"label":"[^"]+"') AS label_field,
       regexp_substr(from_varbyte(substring(kinesis_data,1,64),'utf8'),'"bytes":[0-9]+')  AS bytes_field,
       from_varbyte(substring(kinesis_data, octet_length(kinesis_data)-13, 14),'utf8')    AS tail
FROM mv_large_record
ORDER BY bytes DESC, id_field

16行の結果から、10,485,760 バイトの4行のうち2行と、10,485,660 バイトの1行を抜粋しました。

bytes id_field label_field bytes_field tail
10485760 "id":"r13" "label":"10MiB" "bytes":10485760 231e71767334"}
10485760 "id":"r14" "label":"10MiB" "bytes":10485760 6523963b106e"}
10485660 "id":"r11" "label":"10MiB-100B" "bytes":10485660 ec344bcccf94"}

バイト数が一致していることに加えて、末尾にも JSON の閉じ記号 "} が残っていました。10 MiB のペイロードも、元のバイト数のまま格納されていました。

一方で、65,535 バイトを超えるレコードでは、列の値全体を文字列に変換しようとすると失敗します。試したクエリは json_extract_path_text(from_varbyte(kinesis_data,'utf8'),'label') です。10 MiB のレコードに対して実行すると、次のエラーになりました。クエリIDとプロセスIDの行は省略しています。

ERROR: Invalid input
  Detail:
  -----------------------------------------------
  error:  Invalid input
  code:      8001
  context:   result size 10485760 is too long for type VARCHAR
  location:  varbyte.cpp:87
  -----------------------------------------------

同じクエリを 100 KiB のレコードに対して実行しても失敗しました。

  context:   result size 102400 is too long for type VARCHAR

今回は内容を確認する簡易テストとして、VARBYTE の一部を VARCHAR に変換しました。

実行した式 結果
from_varbyte(substring(kinesis_data,1,65535),'utf8') 成功
from_varbyte(substring(kinesis_data,1,65536),'utf8') エラー

Redshift の VARCHAR 値として扱えるのは最大 65,535 バイトです。これを超える kinesis_data 全体は VARCHAR に変換できないため、今回は VARBYTE のまま先頭64バイトを切り出し、JSON の先頭に配置した項目を取得しました。

今回は検証していませんが、Streaming ingestion の「Data parsing best practices」には別の方法が案内されています。JSON_PARSE(kinesis_data) で JSON ペイロードを SUPER 型に変換し、PartiQL で参照する方法です。SUPER 型は1オブジェクトあたり最大 16 MB を保持できるため、10 MiB のレコードはサイズ上限の範囲内です。

まとめ

Amazon Kinesis Data Streams では、ストリームの最大レコードサイズを、既定の 1 MiB から最大 10 MiB まで引き上げられるようになりました。Amazon Redshift のストリーミングインジェストも 10 MiB レコードに対応しました。今回の検証では、10 MiB ちょうどのレコードを Kinesis に投入し、Redshift が 16 MiB 幅の VARBYTE 列へ、切り詰めることなく取り込めることを確認しました。

これまで、1 MiB のレコードサイズ上限を理由に Amazon MSK を選択したり、Amazon S3 を中継したりしていたワークロードもあります。そうした構成では、Kinesis から Redshift へ直接取り込む形も選択肢になります。要件によっては、中継用ストレージや事前の変換処理を減らし、変換を Redshift 上の SQL に寄せる、よりシンプルな ELT パイプラインを構成できます。

また、パッチ P203 以降の Redshift では、Kinesis Data Streams に接続したストリーミングマテリアライズドビューの更新が、並行スケーリングの対象になっています。

https://dev.classmethod.jp/articles/20260825-redshift-cs-for-kds-streams/

10 MiB への大容量化に加えて、取り込み処理をスケールさせる選択肢もそろいました。Kinesis Data Streams と Redshift を中心としたニアリアルタイム分析基盤を、これまでより幅広いワークロードで検討できそうです。

参考リンク

https://docs.aws.amazon.com/streams/latest/dev/large-records.html

https://docs.aws.amazon.com/redshift/latest/dg/materialized-view-streaming-ingestion.html

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事