Amazon Web Services ブログ

Amazon Redshift の Apache Iceberg 書き込みサポート入門 – Part 1

本記事は 2025 年 11 月 26 日 に公開された「Getting started with Apache Iceberg write support in Amazon Redshift – Part 1」を翻訳したものです。

多くの企業は、分析用の構造化データをデータウェアハウスに保存し、多様なデータセットは柔軟に処理できるようデータレイクに置いています。これまでは、両者の一貫性を保つために複雑な ETL 処理が必要で、データ同期の問題が起きるおそれもありました。

新しく登場した Amazon Redshift の Apache Iceberg 書き込みサポートでは、Amazon Simple Storage Service (Amazon S3) と S3 Tables に保存された Apache Iceberg テーブルに直接書き込めるため、こうした複雑さがなくなります。ネイティブな統合により、中間の ETL ステップを挟まずに Redshift のクエリからデータレイクへ直接データを書き込めます。また、ACID に準拠したトランザクションでデータの一貫性を保ちながら、柔軟なパーティショニング戦略でクエリのパフォーマンスを最適化できます。Apache Iceberg テーブルへの書き込みも、使い慣れた Redshift の SQL インターフェイスで行えます。たとえば、Redshift で複雑な変換を実行し、その結果を Apache Iceberg テーブルに直接書き込めば、Amazon EMR や Amazon Athena などの他の分析エンジンからすぐにクエリできます。この方法なら、データをコピーせずに、Redshift と他の分析ツールの両方から同じデータセットをクエリできます。

本記事では、Amazon Redshift から Amazon S3 と S3 Tables に保存された Apache Iceberg テーブルにデータを直接書き込み、ACID 準拠を保ったままデータウェアハウスとデータレイクをシームレスに統合する方法を紹介します。

「Verisk は Amazon Redshift と Apache Iceberg を使って、巨大災害リスクのモデリングで扱う数十億件のレコードを処理しています。クエリの集計は 30% 高速化し、ストレージコストも大幅に削減できました」

— Verisk、Associate Vice President、Karthick Shanmugam 氏

ソリューションの概要

Amazon Redshift の使い慣れた SQL コマンドで、Amazon S3 と S3 Tables に保存された Apache Iceberg テーブルを作成し、直接書き込めるようになりました。ここでは、AWS Lake Formation を使って S3 テーブルバケットの権限を設定する手順を説明します。最後に、Redshift ネイティブ形式と Apache Iceberg 形式にまたがる顧客と注文のデータセットを分析し、インサイトを引き出します。ワークフローは次の図のとおりです。

手順は次のとおりです。

  1. Amazon Redshift の SQL を使って、AWS Glue Data Catalog に customer_db という名前の外部データベースを作成します。
  2. Amazon Redshift の SQL を使って、Glue データベースに customer という名前の外部テーブルを作成し、顧客データを書き込みます。
  3. 注文データを書き込むため、Amazon S3 Tables に orders という名前のテーブルバケットを作成します。
  4. AWS Lake Formation で、orders テーブルの読み書きに必要な権限を IAM ロールに付与します。
  5. Amazon S3 のテーブルバケット orders に注文データを書き込みます。

本ソリューションでは、次の AWS サービスを使います。

前提条件

  • Amazon Redshift のデータウェアハウス (プロビジョニング型または Serverless) を作成します。
  • Redshift から AWS Glue Data Catalog にデータベースを作成する権限を用意します。
  • Redshift クラスターと同じ AWS リージョンに、Amazon S3 バケットと S3 テーブルバケットを作成します。
  • Lake Formation のデータレイク管理者である IAM ロールを使えるようにしておきます。手順については、「データレイク管理者を作成する」を参照してください。
  • 次のインラインポリシーと信頼ポリシーを設定した IAM ロール RedshifticebergRole を作成します。

    インラインポリシー:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "RedshiftAccess",
          "Effect": "Allow",
          "Action": "redshift:GetClusterCredentialsWithIAM",
          "Resource": "arn:aws:redshift:YOUR-REGION:AWS-ACCOUNT-NUMBER:dbname:YOUR-NAMESPACE-OR-CLUSTER/*"
        },
        {
          "Sid": "S3Access",
          "Effect": "Allow",
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject",
            "s3:ListBucket",
            "s3:GetBucketLocation"
          ],
          "Resource": [
            "arn:aws:s3:::YOUR-BUCKET-NAME/*",
            "arn:aws:s3:::YOUR-BUCKET-NAME"
          ]
        },
        {
          "Sid": "GlueDataCatalogAccess",
          "Effect": "Allow",
          "Action": [
            "glue:CreateDatabase",
            "glue:GetDatabase",
            "glue:GetDatabases",
            "glue:CreateTable",
            "glue:GetTable",
            "glue:GetTables",
            "glue:UpdateTable",
            "glue:DeleteTable"
          ],
          "Resource": "*"
        }
      ]
    }
    

    信頼ポリシー:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "redshift.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        },
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "redshift-serverless.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
  • IAM ロール RedshifticebergRole を Redshift クラスターまたは Serverless 名前空間に関連付けます。
  • customer_db という名前の AWS Glue データベースを新しく作成するか、任意の既存のデータベースを使います。別の名前を使う場合は、以降のコマンドの customer_db を実際のデータベース名に置き換えてください。
  • Redshift Serverless 名前空間で識別子の大文字と小文字の区別が有効になっている場合は、Iceberg テーブルを作成する前に、次のコマンドを実行して無効にします。
    SET enable_case_sensitive_identifier TO FALSE;
    現在の設定を確認するには、次のコマンドを実行します。
    SHOW enable_case_sensitive_identifier;

環境のセットアップ

次の手順で環境をセットアップします。

Amazon S3 の汎用バケットに Apache Iceberg テーブルを作成する

  1. Query Editor V2 で Redshift に接続します。
  2. フェデレーティッドロール RedshifticebergRole 用のユーザーを作成します。
    CREATE USER "IAMR:RedshifticebergRole" WITH PASSWORD DISABLE;
  3. Amazon Redshift の外部スキーマが設定されていることを確認します。Redshift で次のスクリプトを実行してください。
    CREATE EXTERNAL SCHEMA demo_iceberg
    FROM DATA CATALOG DATABASE 'customer_db'
    IAM_ROLE 'arn:aws:iam:::role/RedshifticebergRole';
  4. 前の手順で作成した外部スキーマ demo_iceberg に、Apache Iceberg テーブル形式の外部テーブル customer を作成し、データを挿入します。列の定義を細かく制御したい場合や、後からデータを追加する予定がある場合は、この 2 段階の方法を使います。<<your-bucket>> の部分は、お使いの S3 バケット名に置き換えてください。
    -- Step 1: Define your table structure
    CREATE TABLE demo_iceberg.customer
    (
    customer_id bigint,
    customer_name varchar,
    email varchar,
    city varchar
    )
    USING ICEBERG
    LOCATION 's3://<>/iceberg-data/customers/';
    
    -- Step 2: Insert data
    INSERT INTO demo_iceberg.customer VALUES
    (1, 'Customer1 Smith', 'Customer1.smith@email.com', 'New York'),
    (2, 'Customer2 Johnson', 'Customer2.johnson@email.com', 'Los Angeles'),
    (3, 'Customer3 Brown', 'Customer3.brown@email.com', 'Chicago'),
    (4, 'Customer4 Davis', 'Customer4.davis@email.com', 'Houston'),
    (5, 'Customer5 Wilson', 'Customer5.wilson@email.com', 'Phoenix'),
    (6, 'Customer6 Miller', 'Customer6.miller@email.com', 'Philadelphia'),
    (7, 'Customer7 Garcia', 'Customer7.garcia@email.com', 'San Antonio'),
    (8, 'Customer8 Rodriguez', 'Customer8.rodriguez@email.com', 'San Diego'),
    (9, 'Customer9 Martinez', 'Customer9.martinez@email.com', 'Dallas'),
    (10, 'Customer10 Anderson', 'Customer10.anderson@email.com', 'San Jose'),
    (11, 'Customer11 Taylor', 'Customer11.taylor@email.com', 'Austin'),
    (12, 'Customer12 Thomas', 'Customer12.thomas@email.com', 'Jacksonville'),
    (13, 'Customer13 Jackson', 'Customer13.jackson@email.com', 'Fort Worth'),
    (14, 'Customer14 White', 'Customer14.white@email.com', 'Columbus'),
    (15, 'Customer15 Harris', 'Customer15.harris@email.com', 'Charlotte');
    
    -- Step 3: Select data
    SELECT * FROM demo_iceberg.customer;

    図 2: demo_iceberg.customer の結果

  5. ユーザー IAMR:RedshifticebergRole に外部スキーマへのアクセス権を付与します。
    Grant usage on schema demo_iceberg to "IAMR:RedshifticebergRole";

Amazon S3 のテーブルバケットに Apache Iceberg テーブルを作成する

Amazon S3 のテーブルバケットは、データアクセス権限を一元的に管理する AWS Lake Formation と統合されています。Apache Iceberg テーブルを扱う場合、Lake Formation の統一されたセキュリティフレームワークにより、データレイク全体のアクセス制御がシンプルになります。アクセス権限を一か所にまとめることで、一貫性のある効率的な管理ができ、複数の場所で権限を扱う必要がなくなります。

S3 テーブルバケットを作成するには、次の手順を実行します。

  1. Amazon S3 を開き、左のナビゲーションペインで Table buckets を選択します。
  2. Table buckets ページの Integration with AWS analytics services セクションで、Enable integration を選択します。
  3. Table buckets の一覧で Create table bucket ボタンを選択し、テーブルバケットの名前 (例: iceberg-write-blog) を入力して、Create table bucket を選択します。作成したバケットは、Lake Formation コンソールの S3 テーブルカタログ s3tablescatalog に表示されます。
  4. AWS Lake Formation コンソールで Catalogs を選択し、Catalogs テーブルで s3tablescatalog を選択して詳細ページを開きます。
  5. s3tablescatalog の詳細ページの Catalogs で、テーブルバケット iceberg-write-blog を選択します。
  6. iceberg-write-blog の詳細ページの Databases で、Create database を選択します。
  7. データベース名に iceberg_write_namespace と入力し、ドロップダウンメニューから Catalog を選択して、Create database を選択します。
  8. Lake Formation の IAM ロールに、データベース内でテーブルを作成する権限を付与します。iceberg-write-blog の詳細ページで iceberg_write_namespace のラジオボタンを選択し、Actions、Grant の順に選択します。
  9. Grant permissions ページの Principal type で Principals を選択し、Principals で IAM users and roles を選択して、IAM users and roles のドロップダウンメニューから RedshifticebergRole を選択します。
  10. LF-Tags or catalog resources で Named Data Catalog resources を選択し、Catalogs で iceberg-write-blog を、Databases で iceberg_write_namespace を選択します。
  11. Database permissions で Create table、Drop、Describe のチェックボックスをオンにし、Grant を選択します。

Amazon S3 のテーブルバケットを使って Amazon Redshift で Apache Iceberg テーブルを作成する

AWS Lake Formation のカタログは、同じアカウントの Amazon Redshift データウェアハウスに自動でマウントされます。Amazon Redshift は、自動マウントされた S3 テーブルカタログを使って S3 Tables に直接書き込みます。S3 テーブルバケットに保存された Apache Iceberg テーブルに書き込む SQL の構文は、S3 の汎用バケットに保存された Apache Iceberg テーブルの場合とほぼ同じです。大きな違いは、自動マウントされた S3 テーブルカタログが 3 つの部分からなる表記でのアクセスに対応している点です。そのため、S3 テーブルバケットにあるデータレイクの Apache Iceberg テーブルを参照するときに、EXTERNAL SCHEMA を作成する必要がなくなります。

Apache Iceberg テーブルを作成するには、次の手順を実行します。

  1. RedshifticebergRole に切り替えます。Redshift Query Editor V2 から S3 Tables にアクセスするには、フェデレーティッドユーザーのアカウントを使う必要があります。RedshifticebergRole には、必要な Lake Formation の権限を付与済みです。
  2. Query Editor V2 の Federated user オプションで Redshift にログインします。
  3. Query Editor V2 で、Apache Iceberg テーブル形式の orders テーブルを作成します。
    CREATE TABLE "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders
    (
     customer_id BIGINT,
     order_id BIGINT,
     Total_order_amt DECIMAL(10,2),
     Total_order_tax_amt REAL,
     tax_pct DOUBLE PRECISION,
     order_date DATE,
     order_created_at_tz TIMESTAMPTZ,
     is_active_ind BOOLEAN
    )
    USING ICEBERG 
    PARTITIONED BY (DAY(order_date));
    
  4. 標準の SQL でテーブルにデータを挿入します。
    INSERT INTO "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders
    (order_date, order_id, customer_id, total_order_amt, total_order_tax_amt, tax_pct, order_created_at_tz, is_active_ind)
    VALUES
    ('2024-01-15', 1001, 1, 125.50, 10.04, 0.08, '2024-01-15 10:30:00-06:00', true),
    ('2024-02-20', 1002, 2, 89.99, 6.75, 0.075, '2024-02-20 14:22:15-06:00', true),
    ('2024-03-10', 1003, 3, 234.75, 20.78, 0.0885, '2024-03-10 09:15:30-06:00', false),
    ('2024-04-05', 1004, 1, 67.25, 5.38, 0.08, '2024-04-05 16:45:00-05:00', true),
    ('2024-05-18', 1005, 4, 156.80, 12.54, 0.08, '2024-05-18 11:20:45-05:00', true),
    ('2024-06-22', 1006, 5, 45.99, 4.14, 0.09, '2024-06-22 13:10:20-05:00', true),
    ('2024-07-14', 1007, 2, 312.40, 24.99, 0.08, '2024-07-14 08:35:10-05:00', false),
    ('2024-08-30', 1008, 6, 78.50, 7.07, 0.09, '2024-08-30 15:25:35-05:00', true),
    ('2024-09-12', 1009, 3, 199.99, 18.00, 0.09, '2024-09-12 12:40:50-05:00', true),
    ('2024-10-08', 1010, 7, 523.75, 41.90, 0.08, '2024-10-08 17:15:25-05:00', true),
    ('2024-10-25', 1011, 4, 92.30, 8.31, 0.09, '2024-10-25 10:05:15-05:00', false),
    ('2024-11-02', 1012, 8, 167.45, 13.40, 0.08, '2024-11-02 14:50:40-06:00', true),
    ('2024-11-08', 1013, 1, 34.99, 2.80, 0.08, '2024-11-08 09:30:20-06:00', true),
    ('2024-11-09', 1014, 9, 445.60, 40.10, 0.09, '2024-11-09 16:20:55-06:00', true),
    ('2024-11-10', 1015, 5, 278.85, 22.31, 0.08, '2024-11-10 11:45:30-06:00', true);
    
  5. Redshift に local_orders テーブルを作成し、サンプルのレコードを挿入します。
    CREATE TABLE dev.public.local_orders
    (
    customer_id BIGINT,
    order_id BIGINT,
    Total_order_amt DECIMAL(10,2),
    Total_order_tax_amt REAL,
    tax_pct DOUBLE PRECISION,
    order_date DATE,
    order_created_at_tz TIMESTAMPTZ,
    is_active_ind BOOLEAN
    );
    
    
    INSERT INTO dev.public.local_orders
    (customer_id, order_id, Total_order_amt, Total_order_tax_amt, tax_pct, order_date, order_created_at_tz, is_active_ind)
    VALUES
    (1001, 5001, 299.99, 24.00, 0.08, '2024-01-15', '2024-01-15 14:30:00-05:00', true),
    (1002, 5002, 1250.50, 100.04, 0.08, '2024-01-16', '2024-01-16 09:15:22-05:00', true),
    (1003, 5003, 75.25, 6.02, 0.08, '2024-01-16', '2024-01-16 16:45:33-05:00', true),
    (1004, 5004, 499.99, 40.00, 0.08, '2024-01-17', '2024-01-17 11:20:45-05:00', true),
    (1005, 5005, 149.50, 11.96, 0.08, '2024-01-17', '2024-01-17 13:55:12-05:00', false),
    (1002, 5006, 899.99, 72.00, 0.08, '2024-01-18', '2024-01-18 10:05:30-05:00', true),
    (1006, 5007, 45.75, 3.66, 0.08, '2024-01-18', '2024-01-18 15:40:18-05:00', true),
    (1007, 5008, 1500.00, 120.00, 0.08, '2024-01-19', '2024-01-19 08:25:55-05:00', true),
    (1008, 5009, 250.25, 20.02, 0.08, '2024-01-19', '2024-01-19 12:10:40-05:00', true),
    (1009, 5010, 725.75, 58.06, 0.08, '2024-01-20', '2024-01-20 14:15:28-05:00', true);
    
  6. CREATE TABLE AS (CTAS) の形式で、既存のテーブルから圧縮なしのテーブルを作成します。
    CREATE TABLE "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders_new 
    using ICEBERG
    TABLE PROPERTIES ('compression_type'='uncompressed')
    AS
    select * from dev.public.local_orders;
    
  7. 3 つの部分からなる表記を使い、標準の SQL でデータをクエリします。
    select * from "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders;

    USE 句でデフォルトのデータベースを指定して、データベース名を省略することもできます。

    USE "iceberg-write-blog@s3tablescatalog";
    
    select * from iceberg_write_namespace.orders;

    結果のテーブルは次のようになります。

  8. スキーマの検索パスを設定すれば、表記からスキーマ名を省略でき、テーブルへのアクセスがさらにシンプルになります。
    -- Redshift default database is set to 'iceberg-write-blog@s3tablescatalog'
    USE "iceberg-write-blog@s3tablescatalog";
    
    -- Redshift will search 'iceberg_write_namespace' to resolve table orders
    set search_path to iceberg_write_namespace;
    
    select * from orders;
  9. テーブルの定義を表示します。
    show table "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders 
    
    --Result
    CREATE TABLE "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders 
    (
    customer_id bigint,
    order_id bigint,
    total_order_amt decimal(10, 2),
    total_order_tax_amt float,
    tax_pct double precision,
    order_date date,
    order_created_at_tz timestamptz,
    is_active_ind Boolean
    )
    USING ICEBERG
    PARTITIONED BY (DAY(order_date))
    TABLE PROPERTIES ('compression_type'='snappy');

データを組み合わせる

次の 2 つのソースのデータを組み合わせ、1 つのクエリで連携させる方法を紹介します。

  • S3 の汎用バケットに保存された顧客データ
  • S3 テーブルバケットに保存された注文データ
  1. フェデレーティッドユーザーで Redshift にログインします。
    select 
    b.order_date,
    b.order_id,
    b.total_order_amt,
    CONVERT_TIMEZONE('America/Los_Angeles', b.order_created_at_tz) AS order_pacific_time,
    a.customer_name,
    a.email,
    a.city
    from dev.demo_iceberg.customer a join "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders b
    on(a.customer_id = b.customer_id)
    where b.order_date between '2024-01-15' and '2024-10-25'
    and b.is_active_ind=true;

    2 つのソースを組み合わせたクエリの結果は次のとおりです。

  2. テーブルを削除します。
    Drop TABLE "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders_new;

クリーンアップ

継続的な課金を避けるため、次の手順を順番に実行します。

  1. Apache Iceberg テーブルを削除します。
    DROP TABLE dev.demo_iceberg.customer;
    DROP TABLE "iceberg-write-blog@s3tablescatalog".iceberg_write_namespace.orders;
  2. S3 のオブジェクトを削除します。your-bucket は、作成したバケットの名前に置き換えてください。
    aws s3 rm s3://<your-bucket>/iceberg/ --recursive
  3. Lake Formation の権限を削除します。your-bucket は、作成したバケットの名前に置き換えてください。
    aws lakeformation deregister-resource --resource-arn arn:aws:s3:::<your-bucket>

まとめ

Amazon Redshift の Apache Iceberg 書き込みサポートを使えば、データウェアハウスのパフォーマンスとデータレイクのスケーラビリティを兼ね備えた柔軟なデータアーキテクチャを構築できます。ACID 準拠を保ち、クエリを最適化するパーティショニングも使いながら、Apache Iceberg テーブルにデータを直接書き込めるようになりました。Amazon Redshift でデータレイクに Apache Iceberg テーブルを作成すれば、Amazon EMR や Amazon Athena からすぐにクエリできます。

本シリーズの Part 2 では、Apache Iceberg テーブルに DELETE、UPDATE、MERGE を実行し、ACID 準拠を保ちながら行レベルでデータを変更する方法を紹介します。

詳しくは、ドキュメントの「Apache Iceberg の Amazon Redshift との互換性」と「Apache Iceberg テーブルへの書き込み」を参照してください。最新情報は AWS Database Blog でご覧いただけます。

著者について

Sanket Hase

Sanket Hase

Sanket は、Amazon Redshift チームのエンジニアリングマネージャーです。データレイク分析、ハードウェアとソフトウェアの協調設計、ベクトル化クエリ実行の分野で、クエリ実行チームを率いています。

Harshida Patel

Harshida Patel

Harshida は、AWS のアナリティクス担当プリンシパルソリューションアーキテクトです。

Ritesh Kumar Sinha

Ritesh Kumar Sinha

Ritesh は、サンフランシスコを拠点とするアナリティクススペシャリストソリューションアーキテクトです。16 年以上にわたり、お客様がスケーラブルなデータウェアハウスやビッグデータのソリューションを構築するのを支援してきました。AWS 上で効率的なエンドツーエンドのソリューションを設計・構築するのが好きです。余暇には読書、散歩、ヨガを楽しんでいます。

Raghu Kuppala

Raghu Kuppala

Raghu は、データベース、データウェアハウス、アナリティクスの分野で経験を積んだアナリティクススペシャリストソリューションアーキテクトです。仕事以外では、さまざまな料理を試したり、家族や友人と過ごしたりするのを楽しんでいます。

Xiening Dai

Xiening Dai

Xiening は、Redshift のクエリ処理とデータレイクに取り組むプリンシパルソフトウェアエンジニアです。


この記事は Kiro が翻訳を担当し、Solutions Architect の Woosuk Choi がレビューしました。