新機能『Amazon Redshift Spectrum』から Amazon EMR (Hive on Tez) のテーブルを参照する

Amazon Redshift

Amazon S3にあるデータに対して、Amazon Redshiftから直接クエリを投げる事が出来る機能です。前回のブログで Amazon Redshift Spectrumは 既存の Amazon Athena のテーブルを参照できることが確認できました。マニュアルに以下の記載があります。

You create Redshift Spectrum tables by defining the structure for your files and registering them as tables in an external data catalog. The external data catalog can be either the data catalog that comes with Amazon Athena or your own Apache Hive metastore.

Redshift Spectrumテーブルを作成するには、ファイルの構造を定義し、外部データカタログにテーブルとして登録します。外部データカタログは、Amazon Athenaに付属のデータカタログまたは独自のApache Hiveメタストアのいずれかになります。

Amazon Redshift Spectrum Overview より引用

引き続き、今回は Amazon Redshift Spectrum が Amazon EMR (Hive on Tez) のテーブルを参照することを確認します。

Spectrumの設定・利用手順

Spectrumの設定は Amazon Athena からデータ定義言語(DDL)コマンドを使用してデータベースとテーブルを定義した後、Amazon Redshift からデータ定義言語(DDL)コマンドを使用してテーブルを定義します。

ステップ1:Amazon Redshift 用の IAM ロールを作成する

Amazon EMRと連携するため、Amazon EMRの外部データカタログとAmazon S3のデータファイルにアクセス持つIAMロールを作成してRedshiftクラスタに付与、もしくは権限を追加する必要があります。Amazon Redshiftでロールを使用する方法の詳細については、「IAMロールを使用したCOPYおよびUNLOAD操作の承認」を参照してください。

ここでは mySpectrumRole というロール名に、AmazonS3ReadOnlyAccessAmazonElasticMapReduceFullAccessの2つのマネージドポリシーを付与しています。

20170425-redshift-spectrum-emr-role

ステップ2:IAM ロールをクラスタに関連付ける

Amazon Redshiftが外部データカタログとAmazon S3にアクセスすることを許可するIAMロールを作成したら、そのロールをAmazon Redshiftクラスタに関連付けます。ステップ1で作成した IAMロールの ロール ARN は外部テーブルを定義する際に利用します。

20170425-redshift-spectrum-emr-role-arn

AWS Management Consoleにサインインし、Amazon Redshiftコンソール を開き、ステップ1で作成したmySpectrumRoleForEMR を選択します。

20170425-redshift-spectrum-emr-iam-role

ステップ3:Amazon EMR (Hive on Tez) のクラスタの構築

Amazon EMR (emr-5.4.0)のクラスタはデフォルトの Core Hadoop で Hive と Tezが選択されていますデフォルトのまま構築します。注意点は、Redshift Spectrum は同じEMRと通信できるようにように同一VPC かつ セキュリティグループを設定してください。

20170426-spectrum-emr

ステップ4:Amazon Redshift に 外部スキーマの作成

外部スキーマは外部データカタログ内のデータベースを参照し、Amazon EMR が Amazon Redshift の代わりにAmazon S3にアクセスを認可するための IAMロールのARN を提供します。Amazon Redshift から Amazon EMR の Hiveメタストアを使用して、データベースを対応付けます。

外部スキーマの作成

外部スキーマを作成するには、CREATE EXTERNAL SCHEMAコマンドを実行します。次のコマンドのIAMロールARNを、手順1で作成したロールARNに置き換えてから、SQLクライアントでコマンドを実行します。

uriにはmasterのIPアドレス、ポートはHiveメタストアのデフォルトポートを指定しました。

cmdb=# create external schema spectrum_hive
cmdb-# from hive metastore
cmdb-# database 'default'
cmdb-# uri '10.0.0.122' port 9083
cmdb-# iam_role 'arn:aws:iam::123456789012:role/mySpectrumRoleForEMR'
cmdb-# ;
CREATE SCHEMA

参考:Creating External Schemas for Amazon Redshift Spectrum

pg_external_schemaは、外部スキーマ名の一覧を取得できます。

cmdb=# select * FROM pg_external_schema pe join pg_namespace pn ON pe.esoid = pn.oid;
 esoid | eskind | esdbname | esoptions | nspname | nspowner | nspacl
--------+--------+------------+---------------------------------------------------------------------------------------------------+----------------+----------+--------
 709550 | 2 | default | {"URI":"10.0.0.122","PORT":9083,"IAM_ROLE":"arn:aws:iam::123456789012:role/mySpectrumRoleForEMR"} | spectrum_hive | 100 |
(1 row)

ステップ5:Amazon EMR に テーブルを作成する

今回はデフォルトデータベース defaultにテーブルを作成します。データを参照できることも確認しておきます。

[hadoop@ip-10-0-0-122 ~]$ hive

Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
hive> SET hive.execution.engine;
hive.execution.engine=tez
hive>
hive> CREATE EXTERNAL TABLE IF NOT EXISTS sales_hive (
    > salesid int,
    > listid int,
    > sellerid int,
    > buyerid int,
    > eventid int,
    > dateid smallint,
    > qtysold smallint,
    > pricepaid decimal(8,2),
    > commission decimal(8,2),
    > saletime timestamp
    > )
    > ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
    > WITH SERDEPROPERTIES (
    >  'serialization.format' = '\t',
    >  'field.delim' = '\t'
    > ) LOCATION 's3://awssampledb/tickit/spectrum/sales/'
    > -- TBLPROPERTIES ('has_encrypted_data'='false')
    > ;
OK
Time taken: 6.455 seconds
hive> select count(*) from sales_hive;
Query ID = hadoop_20170426044624_ce094a75-3bc4-42fd-9e08-52b1b02a54f2
Total jobs = 1
Launching Job 1 out of 1


Status: Running (Executing on YARN cluster with App id application_1493180857544_0001)

----------------------------------------------------------------------------------------------
        VERTICES      MODE        STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED
----------------------------------------------------------------------------------------------
Map 1 .......... container     SUCCEEDED      1          1        0        0       0       0
Reducer 2 ...... container     SUCCEEDED      1          1        0        0       0       0
----------------------------------------------------------------------------------------------
VERTICES: 02/02  [==========================>>] 100%  ELAPSED TIME: 10.18 s
----------------------------------------------------------------------------------------------
OK
172462
Time taken: 13.583 seconds, Fetched: 1 row(s)
hive> show databases;
OK
default
Time taken: 0.031 seconds, Fetched: 1 row(s)
hive> show tables;
OK
sales_hive
Time taken: 0.069 seconds, Fetched: 1 row(s)

ステップ6:Amazon S3でデータを照会する

Redshift から spectrum_hive.sales_hiveテーブルの行数を取得できました。

cmdb=# select count(*) from spectrum_hive.sales_hive;
 count
--------
 172462
(1 row)

まとめ

Amazon Redshift Spectrumは、Amazon EMR (Hive on Tez) のデータベース名に対応する外部スキーマを登録することで、Amazon EMR (Hive on Tez) のテーブルに対してクエリーを実行できることを確認できました。すでに Amazon Redshift と Amazon EMRをお使いの環境であれば、外部スキーマを定義するだけでこれらのテーブル間の結合や条件フィルタリング、集約が可能になります。セキュリティグループやポートなど通信が伴うので、最初はデバックするのに事前にEMR上にテーブルを作成して、SELECTコマンドを実行して外部スキーマ設定の検証をするのが良いでしょう。

Athena(Presto)はデータを主にメモリで処理しますが、EMRはHiveのエンジンを切り替えることができ、中でもTezはメモリとファイルとうまく組み合わせて大きなデータに対してもクエリが実行できます。このように用途に応じて選択が可能になるのも Amazon Redshift Spectrum の強みと言えます。

参考:「Tez on EMRを試してみた」というタイトルで話しました #cmdevio2015G

AWS Cloud Roadshow 2017 福岡