Amazon Redshift
データベース開発者ガイド

Amazon Redshift Spectrum 用の外部テーブルの作成

Amazon Redshift Spectrumは、外部テーブルを使用して Amazon S3 に保存されたデータにクエリを実行します。他の Amazon Redshift テーブルで使用したものと同じ SELECT 構文で、外部テーブルにクエリを実行できます。外部テーブルは読み取り専用です。外部テーブルに書き込むことはできません。

外部テーブルは外部スキーマで作成します。外部テーブルを作成するには、外部スキーマの所有者またはスーパーユーザーである必要があります。外部スキーマの所有者を移行するには、「ALTER SCHEMA」を使用して所有者を変更します。次の例は、spectrum_schema スキーマの所有者を newowner に変更します。

alter schema spectrum_schema owner to newowner;

Redshift Spectrum クエリを実行するには、次のアクセス許可が必要です。

  • スキーマのアクセス権限の使用

  • 現在のデータベースに一時テーブルを作成するアクセス権限

次の例では、スキーマ spectrum_schema の使用許可を spectrumusers ユーザーグループに付与しています。

grant usage on schema spectrum_schema to group spectrumusers;

次の例では、データベース spectrumdb の一時アクセス権限を spectrumusers ユーザーグループに付与しています。

grant temp on database spectrumdb to group spectrumusers;

外部テーブルは、Amazon Redshift、AWS Glue、Amazon Athena、または Apache Hive メタストアに作成できます。詳細については、AWS Glue 開発者ガイド の「AWS Glue の使用開始」、Amazon Athena ユーザーガイドの「開始方法」、または Amazon EMR 開発者ガイド の「Apache Hive」を参照してください。

外部テーブルが AWS Glue、Athena または Hive メタストアで定義されている場合は、最初に外部データベースを参照する外部スキーマを作成します。その後、テーブル名の先頭にスキーマ名を付けることで、Amazon Redshift にテーブルを作成することなしに SELECT ステートメント内の外部テーブルを参照できます。詳細については、「Amazon Redshift Spectrum 用の外部スキーマの作成」を参照してください。

Amazon Redshift が AWS Glue データカタログ でテーブルを表示できるようにするには、glue:GetTable を Amazon Redshift IAM ロールに追加します。それ以外の場合は、以下のようなエラーが発生する場合があります。

RedshiftIamRoleSession is not authorized to perform: glue:GetTable on resource: *;

たとえば、Athena 外部カタログに lineitem_athena という名前の外部テーブルが定義されているとします。この場合、athena_schema という名前の外部スキーマを定義し、次の SELECT ステートメントを使ってテーブルにクエリを実行できます。

select count(*) from athena_schema.lineitem_athena;

Amazon Redshift で外部テーブルを定義するには、CREATE EXTERNAL TABLE コマンドを使用します。外部テーブルステートメントはテーブル列、データファイルの型式、Amazon S3 内でのデータの場所を定義します。Redshift Spectrum は、指定フォルダまたはそのサブフォルダ内のファイルをスキャンします。Redshift Spectrum は、隠しファイル、ファイル名がピリオド、下線、ハッシュマーク (「.」、「_」、「#」) で始まるファイル、またはファイル名がチルド (「~」) で終わるファイルは無視します。

次の例では、SALES という名前のテーブルを spectrum という名前の Amazon Redshift 外部スキーマに作成します。データはタブ区切りのテキストファイルになっています。

create external table spectrum.sales( salesid integer, listid integer, sellerid integer, buyerid integer, eventid integer, dateid smallint, qtysold smallint, pricepaid decimal(8,2), commission decimal(8,2), saletime timestamp) row format delimited fields terminated by '\t' stored as textfile location 's3://awssampledbuswest2/tickit/spectrum/sales/' table properties ('numRows'='172000');

外部テーブルを表示するには、SVV_EXTERNAL_TABLES システムビューに対してクエリを実行します。

疑似列

デフォルトでは、Amazon Redshift は疑似列 ($path および $size) を使用して外部テーブルを作成します。これらの列を選択すると、Amazon S3 のデータファイルへのパスとクエリによって返された各行のデータファイルのサイズが表示されます。列名 ($path および $size) は、二重引用符で囲う必要があります。SELECT * 句は、疑似列を返しません。次の例に示すように、$path と $size の列名をクエリに明示的に含める必要があります。

select "$path", "$size" from spectrum.sales_part where saledate = '2008-12-01';

セッションの疑似列の作成を無効にするには、spectrum_enable_pseudo_columns 設定パラメータを false に設定します。

重要

Redshift Spectrum では、Amazon S3 のデータファイルをスキャンして結果セットのサイズを確認しているため、$size または $path を選択すると料金が発生します。詳細については、「Amazon Redshift 料金表」を参照してください。

疑似列の例

次の例では、外部テーブルの関連データファイルの合計サイズを返します。

select distinct "$path", "$size" from spectrum.sales_part; $path | $size ---------------------------------------+------- s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-01/ | 1616 s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-02/ | 1444 s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-03/ | 1644

Redshift Spectrum 外部テーブルのパーティション化

データをパーティション化する際は、パーティションキーをフィルタリングすることで Redshift Spectrum がスキャンするデータ量を制限できます。すべてのキーでデータをパーティション化できます。

一般的な方法では、時間に基づいてデータをパーティション化します。たとえば、年、月、日、時ごとにパーティション化を行います。ソースのデータが多岐にわたる場合は、データソース ID と日付ごとにパーティション化できます。

次の手順でデータをパーティション化する方法を示します。

データをパーティション化するには

  1. パーティションキーに従って Amazon S3 のフォルダにデータを保存します。

    パーティション値ごとにフォルダを 1 つ作成し、パーティションキーとパーティション値を使ってフォルダ名を設定します。たとえば、日付でパーティションする場合、saledate=2017-04-30saledate=2017-04-30 などの名前のフォルダが存在する場合があります。Redshift Spectrum は、パーティションフォルダとそのサブフォルダ内のファイルをスキャンします。また、Redshift Spectrum は、非表示のフォルダと、ピリオド、アンダースコア、ハッシュマーク ( . , _, or #) またはチルダ (~) で始まる名前のフォルダを無視します。

  2. 外部テーブルを作成し、PARTITIONED BY 句でパーティションキーを指定します。

    パーティションキーをテーブル列の名前と同じにすることはできません。SMALLINT、INTEGER、BIGINT、DECIMAL、REAL、DOUBLE PRECISION、BOOLEAN、CHAR、VARCHAR、DATE、または TIMESTAMP データ型を使用できます。

  3. パーティションを追加します。

    ALTER TABLE … ADD PARTITION を使用して各パーティションを追加し、パーティション列とキー値、Amazon S3 内のパーティションフォルダの場所を指定します。単一の ALTER TABLE … ADD ステートメントを使用して複数のパーティションを追加できます。次の例では、'2008-01-01''2008-02-01' のパーティションを追加します。

    alter table spectrum.sales_part add partition(saledate='2008-01-01') location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-01/' partition(saledate='2008-02-01') location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-02/';

    注記

    AWS Glue を使用する場合、単一の ALTER TABLE ステートメントを使用して、最大 100 パーティションまで追加できます。

データのパーティション化の例

次の例では、1 つのパーティションキーでパーティション化された外部テーブルと、2 つのパーティションキーでパーティション化された外部テーブルを作成します。

この例のサンプルデータは、認証済みのすべての AWS ユーザーに読み取りアクセスを許可する Amazon S3 バケットにあります。クラスターと外部データファイルは同じ AWS リージョンに存在する必要があります。サンプルデータバケットは 米国西部 (オレゴン) リージョン (us-west-2) にあります。Redshift Spectrum を使用してデータにアクセスするには、クラスターも us-west-2 に存在する必要があります。Amazon S3 内のフォルダをリスト表示するには次のコマンドを実行します。

aws s3 ls s3://awssampledbuswest2/tickit/spectrum/sales_partition/
PRE saledate=2008-01/
PRE saledate=2008-02/
PRE saledate=2008-03/

外部スキーマがない場合は、次のコマンドを実行します。AWS Identity and Access Management (IAM) ロールを Amazon リソースネーム (ARN) に置き換えます。

create external schema spectrum from data catalog database 'spectrumdb' iam_role 'arn:aws:iam::123456789012:role/myspectrumrole' create external database if not exists;

例 1: 1 つのパーティションキーによるパーティション化

次の例では、月別にパーティション化された外部テーブルを作成します。

月別にパーティション化された外部テーブルを作成するには、次のコマンドを実行します。

create external table spectrum.sales_part( salesid integer, listid integer, sellerid integer, buyerid integer, eventid integer, dateid smallint, qtysold smallint, pricepaid decimal(8,2), commission decimal(8,2), saletime timestamp) partitioned by (saledate char(10)) row format delimited fields terminated by '|' stored as textfile location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/' table properties ('numRows'='172000');

パーティションを追加するには、次の ALTER TABLE コマンドを実行します。

alter table spectrum.sales_part add partition(saledate='2008-01') location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-01/' partition(saledate='2008-02') location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-02/' partition(saledate='2008-03') location 's3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-03/';

次のクエリを実行するには、パーティション化されたテーブルからデータを選択します。

select top 5 spectrum.sales_part.eventid, sum(spectrum.sales_part.pricepaid) from spectrum.sales_part, event where spectrum.sales_part.eventid = event.eventid and spectrum.sales_part.pricepaid > 30 and saledate = '2008-01' group by spectrum.sales_part.eventid order by 2 desc;
eventid | sum     
--------+---------
   4124 | 21179.00
   1924 | 20569.00
   2294 | 18830.00
   2260 | 17669.00
   6032 | 17265.00

外部テーブルパーティションを表示するには、SVV_EXTERNAL_PARTITIONS システムビューにクエリを実行します。

select schemaname, tablename, values, location from svv_external_partitions where tablename = 'sales_part';
schemaname | tablename  | values      | location                                                                
-----------+------------+-------------+-------------------------------------------------------------------------
spectrum   | sales_part | ["2008-01"] | s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-01
spectrum   | sales_part | ["2008-02"] | s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-02
spectrum   | sales_part | ["2008-03"] | s3://awssampledbuswest2/tickit/spectrum/sales_partition/saledate=2008-03

例 2: 複数のパーティションキーによるパーティション化

dateeventid でパーティション化された外部テーブルを作成するには、次のコマンドを実行します。

create external table spectrum.sales_event( salesid integer, listid integer, sellerid integer, buyerid integer, eventid integer, dateid smallint, qtysold smallint, pricepaid decimal(8,2), commission decimal(8,2), saletime timestamp) partitioned by (salesmonth char(10), event integer) row format delimited fields terminated by '|' stored as textfile location 's3://awssampledbuswest2/tickit/spectrum/salesevent/' table properties ('numRows'='172000');

パーティションを追加するには、次の ALTER TABLE コマンドを実行します。

alter table spectrum.sales_event add partition(salesmonth='2008-01', event='101') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-01/event=101/' partition(salesmonth='2008-01', event='102') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-01/event=102/' partition(salesmonth='2008-01', event='103') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-01/event=103/' partition(salesmonth='2008-02', event='101') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-02/event=101/' partition(salesmonth='2008-02', event='102') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-02/event=102/' partition(salesmonth='2008-02', event='103') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-02/event=103/' partition(salesmonth='2008-03', event='101') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-03/event=101/' partition(salesmonth='2008-03', event='102') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-03/event=102/' partition(salesmonth='2008-03', event='103') location 's3://awssampledbuswest2/tickit/spectrum/salesevent/salesmonth=2008-03/event=103/';

次のクエリを実行するには、パーティション化されたテーブルからデータを選択します。

select spectrum.sales_event.salesmonth, event.eventname, sum(spectrum.sales_event.pricepaid) from spectrum.sales_event, event where spectrum.sales_event.eventid = event.eventid and salesmonth = '2008-02' and (event = '101' or event = '102' or event = '103') group by event.eventname, spectrum.sales_event.salesmonth order by 3 desc;
salesmonth | eventname       | sum    
-----------+-----------------+--------
2008-02    | The Magic Flute | 5062.00
2008-02    | La Sonnambula   | 3498.00
2008-02    | Die Walkure     |  534.00

外部テーブル列を ORC 列にマッピングする

Amazon Redshift Spectrum 外部テーブルを使用して、ORC 形式のファイルからデータをクエリします。最適化された行列 (ORC) 形式は、ネストデータ構造をサポートする列指向ストレージファイル形式です。ネストデータをクエリする方法の詳細については、「Amazon Redshift Spectrum を使用したネストデータのクエリ」を参照してください。

ORC ファイルのデータを参照する外部テーブルを作成する場合、外部テーブルの各列を ORC データにある列にマッピングします。それを行うには、次のいずれかの方法を使用します。

列名によるマッピングがデフォルトです。

位置によるマッピング

位置マッピングでは、外部テーブルで統合された最初の列は ORC データファイルの最初の列にマッピングし、2 番目は 2 番目に、のようになります。位置によるマッピングでは、外部テーブルと ORC ファイルの列の順序が一致する必要があります。列の順序が一致しない場合、名前で列をマッピングすることができます。

重要

以前のリリースでは、Redshift Spectrum は位置によるマッピングをデフォルトで使用しました。既存のテーブルに引き続き位置マッピングを使用する必要がある場合は、次の例に示すように、テーブルプロパティ orc.schema.resolutionposition に設定します。

alter table spectrum.orc_example set table properties('orc.schema.resolution'='position');

たとえば、テーブル SPECTRUM.ORC_EXAMPLE は次のように定義されています。

create external table spectrum.orc_example( int_col int, float_col float, nested_col struct< "int_col" : int, "map_col" : map<int, array<float >> > ) stored as orc location 's3://example/orc/files/';

テーブル構造は次のように抽象化することができます。

• 'int_col' : int
• 'float_col' : float
• 'nested_col' : struct
   o 'int_col' : int
   o 'map_col' : map
      - key : int
      - value : array
         - value : float

基盤となる ORC ファイルには次の構造があります。

• ORC file root(id = 0)
   o 'int_col' : int (id = 1)
   o 'float_col' : float (id = 2)
   o 'nested_col' : struct (id = 3)
      - 'int_col' : int (id = 4)
      - 'map_col' : map (id = 5)
         - key : int (id = 6)
         - value : array (id = 7)
            - value : float (id = 8)

この例では、外部テーブルの各列を ORC ファイルにある列に厳密に位置によってマッピングできます。以下にマッピングを示します。

外部テーブル列名 ORC 列 ID ORC 列名
int_col 1 int_col
float_col 2 float_col
nested_col 3 nested_col
nested_col.int_col 4 int_col
nested_col.map_col 5 map_col
nested_col.map_col.key 6 NA
nested_col.map_col.value 7 NA
nested_col.map_col.value.item 8 NA

列名によるマッピング

名前マッピングを使用して、外部テーブルの列を同じレベル、同じ名前で ORC ファイルの名前を付けられた列にマッピングします。

たとえば、前の例、SPECTRUM.ORC_EXAMPLE のテーブルを次のファイル構造を使用する ORC ファイルにマッピングするとします。

• ORC file root(id = 0)
   o 'nested_col' : struct (id = 1)
      - 'map_col' : map (id = 2)
         - key : int (id = 3)
         - value : array (id = 4)
            - value : float (id = 5)
      - 'int_col' : int (id = 6)
   o 'int_col' : int (id = 7)
   o 'float_col' : float (id = 8)

位置マッピングを使用して、Redshift Spectrum は以下のマッピングを試行します。

外部テーブル列名 ORC 列 ID ORC 列名
int_col 1 struct
float_col 7 int_col
nested_col 8 float_col

前述の位置マッピングでテーブルに対してクエリを実行すると、構造が異なるため SELECT コマンドはタイプ検証で失敗します。

列名マッピングを使用して、同じ外部テーブルを前の例に示されている両方のファイル構造にマッピングできます。テーブル列 int_colfloat_colnested_col は、ORC ファイルにある同じ名前の列に列名でマッピングします。外部テーブルにある nested_col という名前の列は、map_colint_col という名前のサブ列がある struct 列です。サブ列も列名で ORC ファイルにある対応する列に正しくマッピングします。