[新機能] Amazon Redshift Data Sharing がGAになったので試してみました

2021.03.29

データアナリティクス事業本部コンサルティングチームの石川です。先日、昨年のre:Invent2020で発表されたRA3インスタンスでクラスタ間でデータのコピーや移動することなくデータを共有するサービスData SharingがGA(Generally Available)になりました。本日はこの機能を試してみたいと思います。

Amazon Redshift data sharing とは

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

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

Redshift Data Sharingの詳細は、以下のブログをご覧ください。

用語の定義

data sharingの検証を始める前に、今回の検証で用いる用語について解説します。

データ共有

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

データ共有オブジェクト

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

プロデューサークラスタ

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

コンシューマークラスタ

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

クラスタ名前空間

クラスタ毎に付与されたユニークな識別子。SELECT current_namaspace();でクラスタ名前空間を取得できます。

検証環境

検証クラスタのインスタンス

Data sharingは、RA3インスタンスのみで利用できます。

  • プロデューサークラスタ: ra3.xlplus x 2
  • コンシューマークラスタ: ra3.xlplus x 2

検証シナリオ

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

検証データ

ticketスキーマ及びテーブルは、AWSのサンプルデータを用います。

検証クラスタのNAMESPACE

プロデューサークラスタは、コンシューマークラスタのNAMESPACEを指定して、データ共有を共有します。一方、コンシューマークラスタは、共有したいプロデューサークラスタのNAMESPACEとデータ共有からデータベースを作成することでデータにアクセスできるようになります。

クラスタのNAMESPACEは、以下のようにマネジメントコンソールからも確認できます。

データ共有作成とデータ共有を利用する際に必要になりますので、それぞれのNAMESPACEを取得してメモっておきます。

プロデューサークラスタのNAMESPACE

dev=# select current_namespace;
          current_namespace
--------------------------------------
 37ba07bc-d5bf-4916-97b7-28ba45937392
(1 row)

コンシューマークラスタのNAMESPACE

dev=# select current_namespace;
          current_namespace
--------------------------------------
 45678e0a-3a21-4c1e-911a-4eb61eb5c534
(1 row)

データ共有の作成・設定

プロデューサークラスタの設定

データ共有の作成

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

dev=# CREATE DATASHARE tickit_datashare;
CREATE DATASHARE

デフォルトでは、データ共有のパブリックアクセスは許可しません。データ共有のパブリックアクセスを許可する場合は、更に以下の設定が必要です。

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

コンシューマークラスタで、クエリを実行したときに以下のエラーが出る場合は、上記の設定が必要です。

ERROR:  Datashare does not allow publicly accessible consumers

データ共有にtickitスキーマを追加

まずは、データ共有にスキーマを追加します。

dev=# ALTER DATASHARE tickit_datashare ADD SCHEMA tickit;
ALTER DATASHARE

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

データ共有に共有したいテーブルを追加します。データ共有を作成した後でもプロデューサー側で共有したテーブルを削除できます。

dev=# ALTER DATASHARE tickit_datashare ADD TABLE tickit.users;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.venue;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.category;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.date;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.event;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.listing;
ALTER DATASHARE tickit_datashare ADD TABLE tickit.sales;

ALTER DATASHARE
ALTER DATASHARE
ALTER DATASHARE
ALTER DATASHARE
ALTER DATASHARE
ALTER DATASHARE
ALTER DATASHARE

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

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

dev=# GRANT USAGE ON DATASHARE tickit_datashare TO NAMESPACE '45678e0a-3a21-4c1e-911a-4eb61eb5c534';
GRANT

これでプロデューサークラスタのデータ共有の共有設定は完了です。引き続きコンシューマークラスタの設定を続けていただい構いませんが、実際に登録したデータ共有やオブジェクト、コンシューマーの状態を確認方法について解説します。

データ共有の一覧の確認

データ共有の一覧を確認します。プロデューサークラスタなので自分が作成したデータ共有が表示されます。プロデューサークラスタはデータ共有しているので、share_typeはOUTBOUNDです。

dev=# SELECT * FROM svv_datashares;
-[ RECORD 1 ]-------+-----------------------------------------------------------------
share_name          | tickit_datashare
share_id            | 101571
share_owner         | 100
source_database     | dev
consumer_database   |
share_type          | OUTBOUND
createdate          | 2021-03-29 13:38:04
is_publicaccessible | f
share_acl           |
producer_account    | 123456789012
producer_namespace  | 37ba07bc-d5bf-4916-97b7-28ba45937392

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

データ共有のオブジェクト一覧も同様に確認できます。プロデューサークラスタはデータ共有しているので、share_typeはOUTBOUNDです。

dev=# SELECT * FROM svv_datashare_objects;
-[ RECORD 1 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.users
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 2 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.venue
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 3 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.category
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 4 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.date
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 5 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.event
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 6 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.listing
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 7 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | table
object_name        | tickit.sales
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392
-[ RECORD 8 ]------+-------------------------------------
share_type         | OUTBOUND
share_name         | tickit_datashare
object_type        | schema
object_name        | tickit
producer_account   | 123456789012
producer_namespace | 37ba07bc-d5bf-4916-97b7-28ba45937392

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

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

dev=# SELECT * FROM svv_datashare_consumers;
-[ RECORD 1 ]------+-------------------------------------
share_name         | tickit_datashare
consumer_account   |
consumer_namespace | 45678e0a-3a21-4c1e-911a-4eb61eb5c534
share_date         | 2021-03-29 13:43:18

コンシューマークラスタの設定

データ共有の一覧の確認

データ共有の一覧を確認します。コンシューマークラスタなのでプロデューサークラスタが共有してくれたデータ共有が表示されます。コンシューマークラスタはデータ共有を参照しているので、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 | f
share_acl           |
producer_account    | 123456789012
producer_namespace  | 37ba07bc-d5bf-4916-97b7-28ba45937392

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

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

dev=# CREATE DATABASE consumer_tickit
FROM DATASHARE tickit_datashare OF NAMESPACE '37ba07bc-d5bf-4916-97b7-28ba45937392';
CREATE DATABASE

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

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

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

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

共有データの参照

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

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

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

dev=# select
consumer_tickit.tickit.sales.sellerid,
consumer_tickit.tickit.users.username,
(consumer_tickit.tickit.users.firstname ||' '|| consumer_tickit.tickit.users.lastname) as name,
consumer_tickit.tickit.users.city,
sum(consumer_tickit.tickit.sales.qtysold)
from consumer_tickit.tickit.sales, consumer_tickit.tickit.date, consumer_tickit.tickit.users
where consumer_tickit.tickit.sales.sellerid = consumer_tickit.tickit.users.userid
and consumer_tickit.tickit.sales.dateid = consumer_tickit.tickit.date.dateid
and consumer_tickit.tickit.date.year = 2008
and consumer_tickit.tickit.users.city = 'San Diego'
group by 1,2,3,4
order by 5 desc
limit 5;
 sellerid | username |       name        |   city    | sum
----------+----------+-------------------+-----------+-----
    49977 | JJK84WTE | Julie Hanson      | San Diego |  22
    19750 | AAS23BDR | Charity Zimmerman | San Diego |  21
    29069 | SVL81MEQ | Axel Grant        | San Diego |  17
    43632 | VAG08HKW | Griffin Dodson    | San Diego |  16
    18888 | KMQ52NVN | Joan Wright       | San Diego |  14
(5 rows)

データベースオブジェクトを<database>.<schema>.<object>の3つをドットで修飾した表記法は、BIツールなどでは、データベースの指定がサポートされていないためスキーマが参照できません。BIツールからスキーマとして参照できるようにするには、更に<database>.<schema>の部分を外部スキーマとして登録し、<external_schema>.<table>の形式で再定義することで回避できます。

ワークアラウンドや、Cross-Database Queriesについては、以下のブログを参照してください。

作成したデータベースからデータを直接参照はできない

データベース一覧を確認すると、consumer_tickitデータベースがあることを確認できます。

dev=# select oid as database_id,
       datname as database_name,
       datallowconn as allow_connect
from pg_database
order by oid;
 database_id |  database_name  | allow_connect
-------------+-----------------+---------------
           1 | template1       | t
      101543 | dev             | t
      101544 | padb_harvest    | t
      101545 | template0       | f
      101548 | consumer_tickit | f
(5 rows)

しかし、作成したデータベースを指定してRedshiftに接続すると以下のエラーメッセージが出力されます。

$ psql -h datashare-consumer.cwquxezuo2x1.ap-northeast-1.redshift.amazonaws.com -U awsuser -d consumer_tickit -p 5439
Password for user awsuser:
psql: error: FATAL:  Cannot connect to shared database "consumer_tickit". Connect to the databases in your cluster instead and use cross-database query notation <shareddatabase>.<schema>.<object> to query the data in shared database.

共有データベース「consumer_tickit」に接続できません。 代わりに、クラスター内のデータベースに接続し、データベース間クエリ表記 <shareddatabase>.<schema>.<object> を使用して共有データベース内のデータをクエリします。

プロデューサークラスタのデータ更新をコンシューマークラスタで確認する

Redshift Data Sahringの驚くことは、プロデューサークラスタのライブデータをコンシューマークラスタで直ちに参照可能な点です。

まずはプロデューサークラスタからテーブルにデータを追加します。

dev=> INSERT INTO tickit.users (userid, username, firstname, lastname, city) VALUES(50000, 'I5H1KAWA', 'Satoru', 'Ishikawa', 'Sapporo');
INSERT 0 1

コンシューマークラスタで確認します。想定通り、更新が適用されました。

dev=# SELECT * FROM consumer_tickit.tickit.users WHERE consumer_tickit.tickit.users.userid = 50000;
-[ RECORD 1 ]-+---------
userid        | 50000
username      | I5H1KAWA
firstname     | Satoru
lastname      | Ishikawa
city          | Sapporo
state         |
email         |
phone         |
likesports    |
liketheatre   |
likeconcerts  |
likejazz      |
likeclassical |
likeopera     |
likerock      |
likevegas     |
likebroadway  |
likemusicals  |

データ共有の削除

データ共有の削除は、どちらからでも可能です。プロデューサーから削除するには、データ共有を削除するにはDROP DATASHAREするだけです。

dev=# DROP DATASHARE tickit_datashare;
DROP DATASHARE

テーブルの共有の削除も可能です。

dev=# ALTER DATASHARE tickit_datashare REMOVE TABLE tickit.users;
ALTER DATASHARE

まとめ

データ共有は、「データ共有」という器にスキーマやテーブルを追加して他のクラスタに共有します。共有されたクラスタは、「データ共有」からデータベースを作成することでデータにアクセスできるようになります。

デフォルトのdevデータベースからアクセスする場合は、<database>.<schema>.<object>の3つをドットで修飾した表記法で参照します。データベースオブジェクトを<database>.<schema>.<object>の3つをドットで修飾した表記法は、BIツールなどでは、データベースの指定がサポートされていないためスキーマが参照できません。BIツールからスキーマとして参照できるようにするには、更に<database>.<schema>の部分を外部スキーマとして登録し、<external_schema>.<table>の形式で再定義することで回避できます。

想定通りデータ共有は簡単に設定できました。今後、AWSからサンプルデータやサードパーティベンダが提供するデータなども使えることを期待しています。

合わせて読みたい

Redshift Data Sharingの詳細は、以下のブログをご覧ください。