Amazon Redshift データ共有の書き込みクエリのサポートを試す!(プレビュー) #AWSreInvent

2023.12.26

データアナリティクス事業本部のコンサルティングチームの石川です。

re:Invent2023でAmazon Redshiftのデータ共有を介した複数のデータウェアハウスからの書き込みクエリのサポートが発表されました。このアップデートでAWSアカウント内またはアカウント間で読み取りと書き込みの両方のクエリをデータ共有で実行できるようになりました。(プレビュー段階では、同じAWSアカウント内となります。)

執筆時点ではプレビューですが、早速試してみます。なお、プレビュー機能は、主に評価とテストのために提供されるものです。本番システムでは使用しないでください。

Redshift のデータ共有(Data Sharing)とは

Redshift間でデータのコピーや移動することなくデータを共有するサービスで、Amazon Redshift間でライブデータを素早くデータアクセスが可能になります。データ共有はデータへのライブアクセスを提供するため、データが更新されてもユーザーは常に最新の一貫性のある情報を見ることができます。

コンシューマーRedshift(共有される側のRedshift)の共有データにアクセスできるユーザーとグループは、標準のSQLおよび分析ツールを使用して、高性能でデータを検出およびクエリできます。データ共有により、共有データにアクセスするワークロードは互いに分離されます。Amazon Redshiftでデータ共有を使用するための追加コストはありません。

今回のアップデータでは、読み込みに加えて書き込みもサポートしました。

用語の定義

データ共有

データを共有するプロデューサーは、CREATE DATASHARE <sharename>コマンドを使用して1つ以上のデータ共有を作成します。データを共有する単位をデータ共有と呼びます。

データ共有オブジェクト

上記のデータ共有に追加したプロデューサーのオブジェクト(テーブルやビューなど)をデータ共有オブジェクトと呼びます。

プロデューサーRedshift

データを共有するRedshiftを表します。Producer-Consumerパターンのプロデューサーです。

コンシューマーRedshift

データを共有されるRedshiftを表します。Producer-Consumerパターンのコンシューマーです。

名前空間ID(Namespace ID)

ネームスペース毎に付与されたユニークな識別子。

検証環境

検証用Redshift Serverlessのワークスペース

Amazon Redshift のデータ共有による複数のウェアハウスからの書き込みに対するサポートは、PREVIEW_2023 トラックを利用できるすべてのリージョンで、このトラックを使用する ra3.4xl クラスター、ra3.16xl クラスター、サーバーレスワークグループでご利用いただけます。

今回は、Redshift Serverlessでお気軽に試したいと思ったのですが、メンテナンストラックのPREVIEW_2023はどこで設定するのか分からず、途方に暮れていたところマネジメントコンソールの上にそれらしいボタンを発見、後は普通にワークスペースを作成できました。

今回は、2つのRedshift Serverlessワークスペースを作成しました。

  • プロデューサーのRedshift: preview-producer-ns
    • 名前空間ID(Namespace ID):810c95ce-d813-4219-a42c-40f385dcea75
  • コンシューマーのRedshift: preview-consumer-ns
    • 名前空間ID(Namespace ID):0e1a85a3-607d-4b3d-a762-0f10bdde84c7

Redshiftのデータ共有(Data Sharing)では、共有する側(以降、Producerと呼びます)と共有される側(以降、Consumerと呼びます)を2つのRedshiftを準備します。

検証シナリオ

今回は、プロデューサーワークスペースのticketスキーマとそのテーブルのデータ共有を作成して、コンシューマーRedshiftに共有します。コンシューマーRedshiftでは、共有されたデータ共有を用いてデータベースを定義します。

データ共有の作成・設定

プロデューサーRedshiftの設定

データ共有するスキーマ・テーブルの準備

サクッと、サンプルのデータを用意したいので、sample_data_devデータベースのテーブルをコピーします。

dev=# CREATE SCHEMA tickit;
CREATE SCHEMA

dev=# CREATE TABLE tickit.users AS SELECT * FROM sample_data_dev.tickit.users;
CREATE TABLE

データ共有の作成

最初にデータ共有を作成します。ここで作成した「データ共有」という器にスキーマやテーブルを追加します。

dev=# CREATE DATASHARE tickit_datashare;
CREATE DATASHARE

dev=# ALTER DATASHARE tickit_datashare SET publicaccessible = TRUE;
ALTER DATASHARE

tickit_datashareに対して、CREATE, USAGEを許可します。

dev=# SET search_path TO tickit;
SET

dev=# GRANT CREATE, USAGE ON SCHEMA tickit TO DATASHARE tickit_datashare;
GRANT

データ共有にtickitスキーマの各テーブルを追加

データ共有に共有したいテーブルを追加します。tickit_datashare.userに対して、SELECTとINSERTを付与します。← 読み(SELECT)、書き込み(INSERT)できる。

dev=# GRANT SELECT, INSERT ON TABLE tickit.users TO DATASHARE tickit_datashare;

GRANT

作成したデータ共有をコンシューマーRedshiftに共有する

作成したデータ共有は、コンシューマーRedshiftのNAMESPACEを指定して共有します。

dev=# GRANT USAGE ON DATASHARE tickit_datashare TO NAMESPACE '0e1a85a3-607d-4b3d-a762-0f10bdde84c7';
GRANT

これでプロデューサーRedshiftのデータ共有の共有設定は完了です。マネジメントコンソールからはこのように確認できます。

データ共有名(tickit_datashare)をクリックすると、詳細を確認できます。

データ共有したコンシューマーRedshift一覧

プロデューサーRedshiftで作成したデータ共有をどのコンシューマーRedshiftに共有したかを確認できます。

dev=# SELECT * FROM svv_datashare_consumers;
-[ RECORD 1 ]------+-------------------------------------
share_name         | tickit_datashare
consumer_account   |
consumer_namespace | 0e1a85a3-607d-4b3d-a762-0f10bdde84c7
share_date         | 2023-12-26 12:45:48

マネジメントコンソールからはこのように確認できます。

コンシューマーRedshiftの設定

データ共有の一覧の確認

データ共有の一覧を確認します。コンシューマーRedshiftなのでプロデューサーRedshiftが共有してくれたデータ共有が表示されます。コンシューマーRedshiftはデータ共有を参照しているので、share_typeはINBOUNDです。

dev=# SELECT * FROM svv_datashares;
-[ RECORD 1 ]-------+-----------------------------------------------------------------
share_name          | tickit_datashare
share_id            |
share_owner         |
source_database     |
consumer_database   |
share_type          | INBOUND
createdate          |
is_publicaccessible | t
share_acl           |
producer_account    | 123456789012
producer_namespace  | 810c95ce-d813-4219-a42c-40f385dcea75
managed_by          |

データ共有のオブジェクト一覧

データ共有のオブジェクト一覧も同様に確認できます。コンシューマーRedshiftはデータ共有しているので、share_typeはINBOUNDです。

dev=# SELECT * FROM svv_datashare_objects;
-[ RECORD 1 ]------+-------------------------------------
share_type         | INBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.users
producer_account   | 123456789012
producer_namespace | 810c95ce-d813-4219-a42c-40f385dcea75
include_new        |
-[ RECORD 2 ]------+-------------------------------------
share_type         | INBOUND
share_name         | tickit_datashare
object_type        | schema
object_name        | tickit
producer_account   | 123456789012
producer_namespace | 810c95ce-d813-4219-a42c-40f385dcea75
include_new        |

データ共有からデータベースを作成

データ共有からデータベースを作成して、共有されたデータの参照します。データベースを作成を作成する際には、プロデューサーRedshiftのNAMESPACEとデータ共有でデータベースを作成します。

dev=# CREATE DATABASE consumer_tickit
FROM DATASHARE tickit_datashare OF NAMESPACE '810c95ce-d813-4219-a42c-40f385dcea75';
CREATE DATABASE

adminユーザーに作成したデータベースの使用許可を付与

作成したデータベースを参照するにはデータベースの使用許可を付与しなければなりません。

dev=# GRANT USAGE ON DATABASE consumer_tickit TO admin;
GRANT

これでコンシューマーRedshiftのデータ共有の共有設定も完了です。

共有データの参照

次は、共有されたデータを参照してみます。Redshiftに接続する際に指定したデータベースによって、データへのアクセス方法が異なります。

別のデータベースからデータを参照

デフォルトのdevデータベースからアクセスする場合は、<database>.<schema>.<object>の3つをドットで修飾した表記法で参照します。所謂、Cross-Databaseです。以下の例では、テーブルのエイリアスを指定してクエリの記述を簡素化しています。

dev=# SELECT * FROM consumer_tickit.tickit.users limit 1;
-[ RECORD 1 ]-+--------------------------------
userid        | 7
username      | OWY35QYB
firstname     | Tamekah
lastname      | Juarez
city          | Moultrie
state         | WV
email         | elementum@semperpretiumneque.ca
phone         | (297) 875-7247
likesports    |
liketheatre   |
likeconcerts  |
likejazz      | t
likeclassical | t
likeopera     | f
likerock      |
likevegas     |
likebroadway  | f
likemusicals  | f

データ共有内のオブジェクトへの書き込み

データ共有内のオブジェクトに書き込む方法

プレビューの段階では、データ共有内のオブジェクトに書き込む方法は 2 つあります。なお、将来的には、<database>.<schema>.<object>の3つをドットで修飾した表記法もサポートする予定との記載がありました。

  1. USE コマンドを使用してローカル データベースに接続する
  2. Redshift JDBC、ODBC、または Python ドライバーを介して datashares データベースに直接接続します

今回は、1の「USE コマンドを使用してローカル データベースに接続する」方法でデータ共有内のオブジェクトへの書き込みを試みます。

USEコマンドを使用すると、<schema>.<object>の2つをドットで修飾した表記法でデータ共有オブジェクトをクエリし、複数ステートメントのトランザクションを実行できます。複数ステートメントのトランザクションは単一データベース内でのみ実行できます。

USE datashare database;

RESET USE コマンドを実行すると、接続しているデータベースの使用に戻ることができます。

RESET USE;

だが、しかし、、、USE うまくいきませんでした。きっと、私が全て悪いと思います。試行錯誤は、以下のとおりです。

dev=# USE datashare database;
ERROR:  syntax error at or near "datashare"
LINE 1: USE datashare database;
            ^

dev=# USE consumer_tickit database;
ERROR:  syntax error at or near "database"
LINE 1: USE consumer_tickit database;
                            ^
dev=# USE datashare consumer_tickit;
ERROR:  syntax error at or near "datashare"
LINE 1: USE datashare consumer_tickit;
            ^
dev=# USE tickit_datashare consumer_tickit;
ERROR:  syntax error at or near "consumer_tickit"
LINE 1: USE tickit_datashare consumer_tickit;
                             ^
dev=# RESET USE;
RESET

ということでした、、、でも諦めない。「...将来的には、<database>.<schema>.<object>の3つをドットで修飾した表記法もサポートする予定...」って、あったので試したところうまくいきました。

ので、今日はサポートしていないはずの3つをドットで修飾した表記法で、クエリを実行します。(我ながら、力技感ハンパないな。)

オブジェクトの書き込み(テーブル追加)

プロデューサーで、CREATEを許可したので、テーブル追加できるか試してみます。

まず、コンシューマーでCREATE TABLEを実行します。SELECTでテーブルに対してクエリできた、つまりテーブルが作成できたことが確認できました。

dev=# CREATE TABLE consumer_tickit.tickit.ishikawa (id int, name varchar(256));
CREATE TABLE

dev=# SELECT * FROM consumer_tickit.tickit.ishikawa;
 id | name
----+------
(0 rows)

では、プロデューサーでテーブルを確認します。

dev=# SELECT * FROM tickit.ishikawa;
 id | name
----+------
(0 rows)

見えました、つまりコンシューマーで作成したテーブル(書き込み)がプロデューサーで確認できたことになります。

いい感じだぞ、この調子だ!

オブジェクトの書き込み(テーブルのレコード追加)

プロデューサーで、INSERTを許可したので、テーブルのレコード追加できるか試してみます。

まず、コンシューマーでINSERT INTOを実行します。

dev=# INSERT INTO consumer_tickit.tickit.ishikawa (id, name) VALUES(1, 'consumer');
INSERT 0 1

dev=# SELECT * FROM consumer_tickit.tickit.ishikawa;
 id |   name
----+----------
  1 | consumer
(1 row)

INSERT INTOできたことが確認できました。

では、プロデューサーでテーブルを確認します。

見えました、つまりコンシューマーで作成したテーブルに対してデータの追加(書き込み)がプロデューサーで確認できたことになります。

dev=# SELECT * FROM tickit.ishikawa;
 id |   name
----+----------
  1 | consumer
(1 row)

ちなみに、オブジェクトオーナーを確認したところ、ややこしい感じになっています。オブジェクトオーナーは、プロデューサーの方で適切に変更したほうが良さそうですね。

dev=# SET search_path TO tickit;
SET

dev=# \d
                                  List of relations
 schema |   name   | type  |                          owner
--------+----------+-------+----------------------------------------------------------
 tickit | ishikawa | table | ds:tickit_datashare_nsp_0e1a85a3607d4b3da7620f10bdde84c7
 tickit | users    | table | admin
(2 rows)

では、さらに調子に乗って、プロデューサーからテーブルに対してデータの追加(書き込み)してみます。

dev=# INSERT INTO tickit.ishikawa (id, name) VALUES(2, 'producer');
INSERT 0 1

dev=# SELECT * FROM tickit.ishikawa;
 id |   name
----+----------
  1 | consumer
  2 | producer
(2 rows)

オブジェクトオーナーではありませんが、データベース管理ユーザーなので、問題なく書き込みできました。つまり、相互に書き込み(INSERT)できるということです。

コンシューマーからも確認できました。バッチリですね。

dev=# select * from consumer_tickit.tickit.ishikawa;
 id |   name
----+----------
  1 | consumer
  2 | producer
(2 rows)

なお、クエリエディタv2からもテーブルが見えています。

最後に

今回は、同じAWSアカウントに2つのRedshift Serverlessを用意して検証しました。

まだ、プレビューの段階ですので、データ共有の要件と制限などありますが、データ共有によるテーブルの作成(CREATE)と更新(INSERT)が動作することが確認できました。

さまざまなテーブルに対して SELECT、INSERT、UPDATE などの権限を付与したり、さまざまなスキーマに対して USAGE や CREATE などの権限を付与したりできることも確認しました。

また、アカウント間でデータを共有する場合、プロデューサー アカウント管理者は、これらのアカウントがデータへの読み取り専用アクセスにするかどうかを選択でき、さらに、プロデューサー アカウント管理者は、特定の名前空間またはリージョンに読み取り専用、読み取りおよび書き込み、またはデータへのアクセスを許可するかどうかを決定できることも確認できました。

下記のマニュアルによると、データはライブであり、書き込みトランザクションがコミットされるとすぐにすべてのウェアハウスで利用できるようになるそうです。USEコマンドについては、一般提供開始(GA)になったら確認したいと思います。

合わせて読みたい