PostgreSQLのdblink機能を使ってAmazon RedshiftとRDS(PostgreSQL)を結合する

Amazon RDS

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日、『AWS Big Data Blog』にて以下のエントリが公開されていました。Amazon RedshiftとRDS(PostgreSQL)を、dblinkという機能を使って結合するというものです。一体どの様な仕組みでJOIN出来るのか、とても気になったので早速試してみました。

目次

 

Amazon RedshiftとRDS(PostgreSQL)の違い

Amazon Redshiftはオンライン分析処理(OLAP)ワークロードを得意とする高性能のペタバイト規模のDWHサービスです。一方RDS(PostgreSQL)やAuroraの様なデータベースは(大抵は多くても)テラバイト規模のデータを格納し、オンライントランザクション処理(OLTP)のワークロードを得意とします。

Amazon Redshiftは列指向アーキテクチャを使用します。これはOLTPアプローチの行による構成ではなく、ディスク上の列によってデータが構成されているものです。詳しくは以下をご参照ください。

列指向アーキテクチャでは、テーブル列のサブセットを照会する際に大幅にI/Oを削減出来るという利点があります。そしてデータは列毎に格納される為、高いレベルで圧縮され更にI/Oを削減する形になるのでより多くのデータを保存し、素早くクエリを返す事が出来ます。

RDS(PostgreSQL)は行ベースのアーキテクチャを使用しています。これはSELECT,INSERT,UPDATE,DELETEと言った一度に少数の行を処理を行う、所謂典型的なOLTP処理に利点があります。

Amazon Redshiftは並列処理(MPP)、シェアード・ナッシング・アーキテクチャを採用しています。これは、Amazon Redshiftが単一のクエリを実行する際でも多くのコンピュータ(これは"ノード"と呼ばれます)間で全てのコンピューティングリソースを使用する設計となっている事を意味します。これにより、多数の行に対して分析を行う処理に対して優れた性能を発揮します。対照的に、殆どのOLTPデータベースはそれぞれのクエリに対し、1台のマシンでリソースのサブセットを使用します。

これらのアーキテクチャの違いは、それぞれのクエリはAmazon Redshiftよりも少ないリソース消費量で済むので、殆どのOLTPデータベースは同時実行クエリを処理出来るという事を意味します。

2つのシステムはとても良くお互いを補完している為、Amazon Redshiftの高パフォーマンスのパワーとRDS(PostgreSQL)の豊富な機能をリンクさせる事は魅力的な提案となります。これら2つのシステムをリンクさせる事は可能なのでしょうか?RDS(PostgreSQL)データベースはMPPデータベースではありません、ですが、複数のインスタンスを互いにリンクさせる機能はあります。

興味深い事に、Amazon Redshiftは元々PostgreSQLからフォークされたプロダクトでした。PostgreSQLのドライバとAPIライブラリがAmazon Redshiftで動作するのもこのためです。このPostgreSQLの機能とAmazon Redshiftの互換性の組み合わせで、2つのシステムを接続された状態にしておく事が出来ます。この接続により、PostgreSQLでクエリを発行し、Amazon Redshiftでそのクエリに対して結果を返す事が出来るようになります。

Amazon RedshiftとRDS(PostgreSQL)を組み合わせる事で、以下の様な利点が得られます。

Redshift_pg_Image_1

上記図では、エンドユーザーとデータベース間の接続フローを示しています。必要に応じて、必要な場合に、Amazon Redshiftに直接接続出来ます。このケースでは、2つの接続管理を簡略化する為に、Amazon EC2インスタンス上でpgbouncer-rrの使用を検討しています。

以下の図はこのソリューションを示したものです。

Redshift_pg_Image_2

 

PostgreSQL/Redshift間の接続を実現する2つの拡張

PostgreSQLには、クエリをリモートで実行する為の2つの拡張が含まれています。1つ目の拡張は、PostgreSQL外部データラッパー、postgres_fdwです。

postgres_fdwモジュールを使うと、外部テーブルの作成が出来るようになります。外部テーブルは、ローカルのネイティブなテーブルと同じ方法で問い合わせる事が出来るようになります。ただし、postgres_fdwが集約関数、LIMIT句に未対応の為、を現時点では全てのクエリがリモート側では実行される訳ではありません。(この辺り、以下のブログエントリが良い感じでまとまっていたので載せておきます)

2つ目の拡張はdblinkです。これはdblinkと呼ばれている関数を含みます。詳しくは以下をご参照ください。

 

動作環境の準備

必要な関数の情報を確認出来ましたので、実際に環境を整えて見たいと思います。手順は以下の通り。

1.Amazon Redshiftクラスタを準備。

2.バージョン9.5以上のRDS(PostgreSQL)を、Amazon Redshiftを立ち上げたクラスタと同じAZに準備します。

launch-postgresql-instance_01

3.RedshiftのVPCセキュリティグループの設定を、Amazon RDS(PostgreSQL)のエンドポイントからのアクセスを許可する様にしておきます。

4.下記ページを参考に、データをRedshiftクラスタにロードしておきます。

# create table public.users (
	userid integer not null distkey sortkey,
	username char(8),
	firstname varchar(30),
	lastname varchar(30),
	city varchar(30),
	state char(2),
	email varchar(100),
	phone char(14),
	likesports boolean,
	liketheatre boolean,
	likeconcerts boolean,
	likejazz boolean,
	likeclassical boolean,
	likeopera boolean,
	likerock boolean,
	likevegas boolean,
	likebroadway boolean,
	likemusicals boolean);
CREATE
# copy public.users from 's3://awssampledbuswest2/tickit/allusers_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' region 'us-west-2';
INFO:  Load into table 'users' completed, 49990 record(s) loaded successfully.
COPY
Time: 5056.187 ms
# create table public.venue (
	venueid smallint not null distkey sortkey,
	venuename varchar(100),
	venuecity varchar(30),
	venuestate char(2),
	venueseats integer);
CREATE
# copy public.venue from 's3://awssampledbuswest2/tickit/venue_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' region 'us-west-2';
INFO:  Load into table 'venue' completed, 202 record(s) loaded successfully.
COPY
Time: 14909.103 ms
# create table public.category (
	catid smallint not null distkey sortkey,
	catgroup varchar(10),
	catname varchar(10),
	catdesc varchar(50));
CREATE
# copy public.category from 's3://awssampledbuswest2/tickit/category_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' region 'us-west-2';
INFO:  Load into table 'category' completed, 11 record(s) loaded successfully.
COPY
Time: 13360.362 ms
# create table public.date (
	dateid smallint not null distkey sortkey,
	caldate date not null,
	day character(3) not null,
	week smallint not null,
	month character(5) not null,
	qtr character(5) not null,
	year smallint not null,
	holiday boolean default('N'));
CREATE
# copy public.date from 's3://awssampledbuswest2/tickit/date2008_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' region 'us-west-2';
INFO:  Load into table 'date' completed, 365 record(s) loaded successfully.
COPY
Time: 17469.775 ms
# create table public.event (
	eventid integer not null distkey,
	venueid smallint not null,
	catid smallint not null,
	dateid smallint not null sortkey,
	eventname varchar(200),
	starttime timestamp);
CREATE
# copy event from 's3://awssampledbuswest2/tickit/allevents_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' timeformat 'YYYY-MM-DD HH:MI:SS' region 'us-west-2';
INFO:  Load into table 'event' completed, 8798 record(s) loaded successfully.
COPY
Time: 16643.198 ms
# create table public.listing (
	listid integer not null distkey,
	sellerid integer not null,
	eventid integer not null,
	dateid smallint not null  sortkey,
	numtickets smallint not null,
	priceperticket decimal(8,2),
	totalprice decimal(8,2),
	listtime timestamp);
CREATE
# copy public.listing from 's3://awssampledbuswest2/tickit/listings_pipe.txt' 
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '|' region 'us-west-2';
INFO:  Load into table 'listing' completed, 192497 record(s) loaded successfully.
COPY
Time: 28819.729 ms
# create table public.sales (
	salesid integer not null,
	listid integer not null distkey,
	sellerid integer not null,
	buyerid integer not null,
	eventid integer not null,
	dateid smallint not null sortkey,
	qtysold smallint not null,
	pricepaid decimal(8,2),
	commission decimal(8,2),
	saletime timestamp);
CREATE
# copy sales from 's3://awssampledbuswest2/tickit/sales_tab.txt'
credentials 'aws_iam_role=arn:aws:iam::XXXXXXXXXXXX:role/cm-xxxxxxxxxx-role' 
delimiter '\t' timeformat 'MM/DD/YYYY HH:MI:SS' region 'us-west-2';
INFO:  Load into table 'sales' completed, 172456 record(s) loaded successfully.
COPY
Time: 27723.981 ms

一通りのデータを格納し終わった後の件数確認。

# SELECT COUNT(*) FROM public.users;
 count 
-------
 49990
(1 row)

# SELECT COUNT(*) FROM public.venue;
 count 
-------
   202
(1 row)

# SELECT COUNT(*) FROM public.category;
 count 
-------
    11
(1 row)

# SELECT COUNT(*) FROM public.date;
 count 
-------
   365
(1 row)

# SELECT COUNT(*) FROM public.event;
 count 
-------
  8798
(1 row)

# SELECT COUNT(*) FROM public.listing;
 count  
--------
 192497
(1 row)

# SELECT COUNT(*) FROM public.sales;
 count  
--------
 172456
(1 row)

5.RDS(PostgreSQL)インスタンスに接続し、以下SQLコードを実行。この際、必要な設定値についてはお試しのAmazon Redshift環境の値に置き換えて設定してください。

/** EXTENSIONの作成x2 */
pgsqldb=> CREATE EXTENSION postgres_fdw;
CREATE EXTENSION
pgsqldb=> CREATE EXTENSION dblink;
CREATE EXTENSION
pgsqldb=> CREATE SERVER foreign_server
  FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (
    host 'XX.XXX.XX.XXX', // Amazon RedshiftのIPアドレスを設定
    port '5439',          // Amazon Redshiftの接続ポート番号を設定
    dbname 'xyzxyzxyz',   // Amazon Redshiftの接続データベース名を設定
    sslmode 'require');
CREATE SERVER
pgsqldb=> CREATE USER MAPPING FOR xxxxx // RDS(PostgreSQL)接続ユーザー名を設定
  SERVER foreign_server
  OPTIONS (
  user 'xxxxxxxxxx',      // Amazon RedshiftのDB接続ユーザー名を設定
  password 'yyyyyyyyyy'); // Amazon RedshiftのDB接続パスワードを設定
CREATE USER MAPPING

 

各種接続・動作確認

準備が整いました。以下、それぞれの用途について実際に試してみたいと思います。

 

基本的なクエリ

Dblink関数を使う際は、以下クエリに示すようにSQLステートメントを文字列として渡し、結果セットを定義する必要があります。(最後のLIMIT句はブログへの内容表示上別途付与したものです)

pgsqldb=> SELECT *
pgsqldb-> FROM dblink('foreign_server',$REDSHIFT$
pgsqldb$>     SELECT sellerid, sum(pricepaid) sales
pgsqldb$>     FROM sales 
pgsqldb$>     WHERE saletime >= '2008-01-01'
pgsqldb$>     AND saletime < '2008-02-01'
pgsqldb$>     GROUP BY sellerid 
pgsqldb$>     ORDER BY sales DESC
pgsqldb$> $REDSHIFT$) AS t1 (sellerid int, sales decimal)
pgsqldb-> LIMIT 30;

以下は主なポイント。

  • 前述の手順で作成したサーバーへの設定をforeign serverで行っています。
  • SQLクエリは$REDSHIFT$という、2つの$で所定の文字を囲んだ区切り文字列の間に記載。$区切り文字列を使う事で認識し易くなります。
  • $REDSHIFT$とラベリングされた区切り文字は、Redshiftに送られる事になるSQL文字列をハイライト表示させるのに役立ちます。
  • クエリの結果はレコードセットになります。結果はsellerid int, sales decimalのような形でデータ型を指定しておく必要があります。これを行う事によって結合及び処理が行えるようになります。

結果は以下の様になります。

 sellerid |  sales   
----------+----------
     9084 | 15094.00
    46718 | 14850.00
    46790 | 14154.00
    14420 | 14064.00
    35440 | 13554.00
    37417 | 13320.00
    48120 | 12336.00
    14907 | 12078.00
    10376 | 11766.00
      816 | 11130.00
    37573 | 10530.00
    43194 | 10512.00
    37408 | 10366.00
    46468 | 10348.00
    13565 | 10185.00
    48599 | 10140.00
    32895 |  9934.00
    37430 |  9710.00
    30431 |  9660.00
    21028 |  9660.00
    19978 |  9636.00
     4787 |  9460.00
    23008 |  9376.00
    34397 |  9350.00
    10682 |  9099.00
    44123 |  8680.00
    14497 |  8513.00
    33040 |  8247.00
    11577 |  8148.00
    20305 |  8140.00
(30 rows)

pgsqldb=> 

 

ビューの参照

ビューについても、以下の様な形で利用する事が出来ます。

pgsqldb=> CREATE OR REPLACE VIEW v_sales AS
pgsqldb-> SELECT *
pgsqldb-> FROM dblink ('foreign_server',$REDSHIFT$ 
pgsqldb$>     SELECT sellerid, sum(pricepaid) sales
pgsqldb$>     FROM sales 
pgsqldb$>     WHERE saletime >= '2008-01-01'
pgsqldb$>     AND saletime < '2008-02-01'
pgsqldb$>     GROUP BY sellerid 
pgsqldb$>     ORDER BY sales DESC
pgsqldb$> $REDSHIFT$) AS t1 (sellerid int, sales decimal);
CREATE VIEW

pgsqldb=> SELECT * from v_sales LIMIT 15;
 sellerid |  sales   
----------+----------
     9084 | 15094.00
    46718 | 14850.00
    46790 | 14154.00
    14420 | 14064.00
    35440 | 13554.00
    37417 | 13320.00
    48120 | 12336.00
    14907 | 12078.00
    10376 | 11766.00
      816 | 11130.00
    37573 | 10530.00
    43194 | 10512.00
    37408 | 10366.00
    46468 | 10348.00
    13565 | 10185.00
(15 rows)

 

ユーザー定義関数の利用

他のアプローチとして、ユーザー定義関数(UDF)を使うというものがあります。 ビューとは対照的に、UDFは実行時にパラメータを指定する事が出来ます。前述の例では日付の範囲指定はビュー内でハードコーディングされていました。UDFを使うと、任意の日時の範囲指定を行う事が出来ます。以下のコードでは、PostgreSQLでUDFを作成しています。

pgsqldb=> CREATE OR REPLACE FUNCTION get_sales(_startdate timestamp, _enddate timestamp)
pgsqldb-> RETURNS TABLE (sellerid int, sales decimal) AS
pgsqldb-> $BODY$
pgsqldb$> DECLARE
pgsqldb$> remote_sql TEXT;
pgsqldb$> BEGIN
pgsqldb$> remote_sql = FORMAT( '
pgsqldb$>     SELECT sellerid, sum(pricepaid) sales
pgsqldb$>     FROM sales 
pgsqldb$>     WHERE saletime >= %L AND saletime < %L 
pgsqldb$>     GROUP BY sellerid 
pgsqldb$>     ORDER BY sales DESC
pgsqldb$> ', _startdate, _enddate);
pgsqldb$> RETURN QUERY 
pgsqldb$> SELECT *
pgsqldb$> FROM dblink('foreign_server', remote_sql) 
pgsqldb$> AS t1  (sellerid int, sales decimal);
pgsqldb$> END;
pgsqldb$> $BODY$
pgsqldb-> LANGUAGE plpgsql VOLATILE;
CREATE FUNCTION

利用方法及び結果は以下の様な形となります。

pgsqldb=> SELECT * FROM get_sales ('2008-01-01', '2008-02-01') LIMIT 35;
 sellerid |  sales   
----------+----------
     9084 | 15094.00
    46718 | 14850.00
    46790 | 14154.00
    14420 | 14064.00
    35440 | 13554.00
    37417 | 13320.00
    48120 | 12336.00
    14907 | 12078.00
    10376 | 11766.00
      816 | 11130.00
    37573 | 10530.00
    43194 | 10512.00
    37408 | 10366.00
    46468 | 10348.00
    13565 | 10185.00
    48599 | 10140.00
    32895 |  9934.00
    37430 |  9710.00
    30431 |  9660.00
    21028 |  9660.00
    19978 |  9636.00
     4787 |  9460.00
    23008 |  9376.00
    34397 |  9350.00
    10682 |  9099.00
    44123 |  8680.00
    14497 |  8513.00
    33040 |  8247.00
    11577 |  8148.00
    20305 |  8140.00
    44920 |  7964.00
    23732 |  7833.00
    10625 |  7758.00
    35566 |  7745.00
    20766 |  7616.00
(35 rows)

 

マテリアライズドビューでデータのキャッシュ

頻繁にアクセスされるデータの場合、マテリアライズドビューを使う方が良い場合があります。マテリアライズドビューは結果をキャッシュし、これによりクエリが結果の再計算をスキップ出来るようになります。これは、ダッシュボードの様に、頻繁にリクエストされる少量のデータをキャッシュするような場合、理想的なケースとなります。

以下のマテリアライズドビューでは、米国の州毎にスポーツが好きなユーザーの人数カウントをしています。マテリアライズドビュー作成のDDLは以下の通りです。

pgsqldb=> CREATE MATERIALIZED VIEW v_users_likes_by_state AS
pgsqldb-> SELECT *
pgsqldb-> FROM dblink('foreign_server',$REDSHIFT$
pgsqldb$>         SELECT state, sum(likesports::int) sports_like_count
pgsqldb$>         FROM users 
pgsqldb$>         GROUP BY state
pgsqldb$> $REDSHIFT$) AS t1 (state text, sports_like_count int);
SELECT 63

マテリアライズドビューを作成すると、クエリはAmazon Redshiftに対して発行されます。クエリが再度マテリアライズドビューに対して発行される際、Amazon Redshiftに対して発行されるクエリは無く、結果が迅速にPostgreSQLから返されます。マテリアライズドビューへのクエリは通常のビューに対して行うものと同じです。結果は以下の様な形となります。

pgsqldb=> SELECT * FROM v_users_likes_by_state;
 state | sports_like_count 
-------+-------------------
 AK    |               185
 AZ    |                82
 YT    |               333
 TX    |                72
 DC    |                87
 CT    |                76
 RI    |                93
 NH    |                80
 GA    |                80
 OK    |                84
 IN    |                95
 QC    |               338
 NJ    |                92
 MN    |                73
 PA    |                81
 NB    |               307
 MD    |                75
 NS    |               325
 AL    |                97
 IL    |                85
 AB    |               332
 VT    |                90
 UT    |                83
 TN    |                88
 ME    |                71
 OH    |                84
 NU    |               314
 NL    |               341
 SK    |               331
 MB    |               326
 NY    |               101
 KS    |                84
 LA    |                99
 MO    |                84
 BC    |               341
 ND    |                79
 MA    |                95
 MI    |                98
 ID    |                93
 CO    |                99
 FL    |                99
 KY    |                88
 WV    |                92
 ON    |               323
 NM    |                76
 WI    |                80
 PE    |               333
 NE    |                86
 MS    |                90
 WY    |                65
 OR    |                70
 MT    |                91
 NT    |               351
 CA    |                92
 SD    |                76
 VA    |                81
 NC    |                86
 SC    |                82
 DE    |                92
 HI    |                86
 WA    |                88
 NV    |                93
 IA    |                89
(63 rows)

マテリアライズドビューが保持しているキャッシュはデータの内容が古くなる可能性があります。以下SQL文では、マテリアライズドビューに対してクエリの再発行を行い、データをリフレッシュしています。

REFRESH MATERIALIZED VIEW v_users_likes_by_state;

一定の間隔でマテリアライズドビューをリフレッシュするのに、AWS Lambdaを使用出来ます。以下はNode.jsでのコード実践例です。

var pg = require("pg");
 
exports.handler = function(event, context) {   
    var conn = "pg://username:password@host:port/dbname";
    var client = new pg.Client(conn);
    client.connect(function(err) {
        if (err) {
            context.fail("Failed" + err);
        }
        client.query('REFRESH MATERIALIZED VIEW v_users_likes_by_state', function (err, result) {
            if (err) {
                context.fail("Failed to run query" + err);
            }
            client.end();
            context.succeed("Successfully Refreshed.");
        });
    });
};

AWS Lambdaではpgモジュールを使う際、以下のコマンドを使用してインストールする事が出来ます。

npm install pg

AWS Lambdaに展開するファイル作成の詳細については以下をご参照ください。

 

Amazon RedshiftからRDS(PostgreSQL)へのデータコピー

データ量が多い場合、マテリアライズドビューを使う代わりに、dblink機能を使ってデータをPostgreSQLのテーブルにコピーする方が良いかも知れません。これは、新しいデータを、必要な最新分のデータのみ欲しい場合に便利です。マテリアライズドビューの欠点は、最初から全てのデータをコピーしてしまうという点です。

PostgreSQLに以下のテーブルを作成します。

pgsqldb=> CREATE TABLE sales_summary (
pgsqldb(>    saletime timestamp,
pgsqldb(>    sellerid int,
pgsqldb(>    sales decimal
pgsqldb(> );
CREATE TABLE

PostgreSQLでは読み込みを最適化する為にインデックスを使います。そして新しいBRINは順序付けされたタイムスタンプに対しての適切なインデックスです。インデックス作成のSQL文は以下。

pgsqldb=> CREATE INDEX idx_sales_summary_brin
pgsqldb->    ON sales_summary
pgsqldb->    USING BRIN (saletime);
CREATE INDEX

以下のクエリでは、dblink機能を使ってRedshiftに対して発行したクエリの結果をPostgreSQLに挿入しています。

pgsqldb=> INSERT INTO sales_summary
pgsqldb-> SELECT *
pgsqldb-> FROM dblink('foreign_server',$REDSHIFT$
pgsqldb$>     SELECT date_trunc('hours', saletime) AS ts, sellerid, sum(pricepaid) sales
pgsqldb$>     FROM sales 
pgsqldb$>     WHERE saletime >= '2008-01-01'
pgsqldb$>     AND saletime < '2008-02-01'
pgsqldb$>     GROUP BY ts, sellerid 
pgsqldb$>     ORDER BY sales 
pgsqldb$> $REDSHIFT$) AS t1 (saletime timestamp, sellerid int, sales decimal);
INSERT 0 7472

実行後の結果を確認して見ます。ちゃんとデータが入ってますね!

pgsqldb=> SELECT COUNT(*) FROM sales_summary;
 count 
-------
  7472
(1 row)

pgsqldb=> SELECT * FROM sales_summary ORDER BY saletime ASC LIMIT 20;
      saletime       | sellerid |  sales  
---------------------+----------+---------
 2008-01-01 01:00:00 |     6955 |  347.00
 2008-01-01 02:00:00 |    43282 |  708.00
 2008-01-01 03:00:00 |    48680 |  688.00
 2008-01-01 06:00:00 |    20429 |  472.00
 2008-01-01 07:00:00 |    37631 |  337.00
 2008-01-01 07:00:00 |    45818 |  836.00
 2008-01-01 09:00:00 |    30047 |  234.00
 2008-01-01 12:00:00 |     3003 | 1730.00
 2008-01-01 12:00:00 |     2186 | 4192.00
 2008-01-02 01:00:00 |    27144 |  494.00
 2008-01-02 01:00:00 |     5933 |  177.00
 2008-01-02 01:00:00 |    18692 |   90.00
 2008-01-02 02:00:00 |    11656 |  456.00
 2008-01-02 02:00:00 |    43282 |  354.00
 2008-01-02 03:00:00 |     1303 |  196.00
 2008-01-02 03:00:00 |    37430 | 8672.00
 2008-01-02 03:00:00 |    30412 |  469.00
 2008-01-02 03:00:00 |    33619 |  241.00
 2008-01-02 04:00:00 |    33657 |  269.00
 2008-01-02 05:00:00 |    30285 |  108.00
(20 rows)

 

結論

Dblink機能を使って、Amazon Redshiftに接続してPostgreSQLの機能を利用する事が出来ます。これにより、頻繁にクエリされる小さいデータセットに対しては以下2つの選択が出来るようになりました。1つはマテリアライズドビュー、もう1つはデータをコピーしておく事です。キャッシュされていないデータを照会する場合も、同様に2つの選択を検討する事が可能です。通常のビューと、パラメータを受け取るUDFです。dblinkを使ってAmazon Redshiftと接続する事で多くの用途に関する可能性(PostGISやLADPサポート(これはAmazon EC2のみ))も考えられますが、これらは記事の範囲を超えている為言及はしません。

 

まとめ

以上、dblink機能を使ったPostgreSQLとAmazon Redshiftの連携に関するエントリでした。データ量やPostgreSQLのスペック等にも影響して来るので使い所にも気を付ける必要があるかと思いますが、これはとても便利な機能ですね!皆様もビッグデータ業務で必要に応じてこちらのソリューションを検討してみてください。

AWS Cloud Roadshow 2017 福岡