Amazon Athena テーブルにクエリを実行するとレコードがゼロになるのはなぜですか?

所要時間2分
0

Amazon Athena で CREATE TABLE ステートメントを実行しまし、必要な列とそのデータ型を指定しました。SELECT* FROM table-name というクエリを実行すると、出力は「ゼロレコードが返されました。」

解決策

クエリがゼロレコードを返すのには、いくつかの一般的な理由があります。ユースケースに基づいて、一般的な理由とトラブルシューティング手順に関連するセクションを参照してください。

AWS Glue パーティション

クローラー設定で選択したファイル

クローラーを使用する場合は、クローラーがファイルではなく Amazon Simple Storage Service (Amazon S3) バケットを指していることを確認してください。また、S3 バケットパスの末尾にスラッシュが含まれていないことを確認してください。たとえば、s3://doc-example-bucket/new/data.json ではなく s3://doc-example-bucket/new を使用します。

不正確な LOCATION パス

入力データの Amazon S3 LOCATION パスを確認します。入力された LOCATION パスが正しくない場合、Athena はゼロレコードを返します。S3 バケットパスにファイル、末尾のスラッシュ、またはワイルドカードが含まれていないことを確認してください。たとえば、s3://doc-example-bucket/new/data.json ではなく s3://doc-example-bucket/new を使用します。

LOCATION パス内の二重スラッシュ

Athena は、二重スラッシュ (//) を含むテーブル LOCATION パスをサポートしていません。たとえば、次の LOCATION パスは空の結果を返します。s3://doc-example-bucket/myprefix//input//

この問題を解決するには、二重スラッシュのない場所にファイルをコピーします。以下は、ファイルをコピーするための AWS コマンドラインインターフェイス (AWS CLI) コマンドです。

aws s3 cp s3://doc-example-bucket/myprefix//input// s3://doc-example-bucket/myprefix/input/ --recursive

**注:**AWS CLI のコマンドの実行時にエラーが発生する場合は、「AWS CLI エラーのトラブルシューティング」を参照してください。また、AWS CLI の最新バージョンを使用していることを確認してください。

特殊文字

テーブルの列名には、アンダースコアまたは大文字のみを使用するのがベストプラクティスです。例えば、列には table_name という名前を付けることはできますが、table-name という名前は付けられません。

**注:**AWS Glue と Athena は、キャメルケース、大文字、またはアンダースコア以外の特殊文字を読み取ることができません。

**同じ S3 プレフィックスに保存されている複数のテーブルのデータ **

AWS Glue クローラーは、同じ S3 プレフィックスに保存されているデータ用に個別のテーブルを作成します。ただし、Athena でこれらのテーブルをクエリすると、レコードはゼロになります。たとえば、テーブルの場所が次の例のような場合、Athena クエリはゼロレコードを返します。

  • s3://doc-example-bucket/table1.csv
  • s3://doc-example-bucket/table2.csv

この問題を解決するには、以下の例のようにテーブルごとに個別の S3 プレフィックスを作成します。

  • s3://doc-example-bucket/table1/table1.csv
  • s3://doc-example-bucket/table2/table2.csv

次に、この例のようなクエリを実行して、テーブル table1 の場所を更新します。

ALTER TABLE table1 SET LOCATION 's3://doc-example-bucket/table1';

まだロードされていないパーティション

Athena は、テーブルの作成時にのみメタデータを作成します。データは、クエリを実行したときにのみ解析されます。テーブルにパーティションが定義されている場合、そのパーティションは AWS Glue データカタログまたは内部の Athena データカタログにまだロードされていない可能性があります。MSCK REPAIR TABLE または ALTER TABLE ADD PARTITION を使用して、パーティション情報をカタログにロードします。

Athena がサポートする形式でパーティションが保存されている場合は、MSCK REPAIR TABLE を実行してパーティションのメタデータをカタログに読み込みます。例えば、Year でパーティション化されたテーブルがある場合、Athena は次の例のように Amazon S3 パスでデータを検索することを想定しています。

  • s3://doc-example-bucket/athena/inputdata/year=2020/data.csv
  • s3://doc-example-bucket/athena/inputdata/year=2019/data.csv
  • s3://doc-example-bucket/athena/inputdata/year=2018/data.csv

データが Athena が想定する Amazon S3 パスにある場合は、次の例のようなコマンドを実行してテーブルを修復します。

CREATE EXTERNAL TABLE Employee (    Id INT,
    Name STRING,
    Address STRING
) PARTITIONED BY (year INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://doc-example-bucket/athena/inputdata/';

テーブルが作成されたら、パーティション情報をロードします。

MSCK REPAIR TABLE Employee;

データがロードされたら、次のクエリをもう一度実行します。

SELECT * FROM Employee;

Athena がサポートする形式でパーティションが保存されていない場合や、異なる Amazon S3 パスにある場合は、パーティションごとに ALTER TABLE ADD PARTITION を実行します。

例えば、データが次の Amazon S3 パスにあるとします。

  • s3://doc-example-bucket/athena/inputdata/2020/data.csv
  • s3://doc-example-bucket/athena/inputdata/2019/data.csv
  • s3://doc-example-bucket/athena/inputdata/2018/data.csv

これらのパスを使用して、次の例のようなコマンドを実行します。

ALTER TABLE Employee ADD    PARTITION (year=2020) LOCATION 's3://doc-example-bucket/athena/inputdata/2020/'
    PARTITION (year=2019) LOCATION 's3://doc-example-bucket/athena/inputdata/2019/'
    PARTITION (year=2018) LOCATION 's3://doc-example-bucket/athena/inputdata/2018/'

データがロードされたら、次のクエリをもう一度実行します。

SELECT * FROM Employee;

ハイブ隠しファイル

ファイル名がアンダースコア (\ _) またはピリオド (.) で始まっていないことを確認してください。

Athena はこれらのファイルをプレースホルダーと見なし、クエリを処理する際に無視します。詳細については、「Athena が隠しファイルを読み取れない」を参照してください。S3 パス内のすべてのファイルの名前がアンダースコアまたはピリオドで始まる場合、レコードはゼロになります。

**注:**S3 パスに、名前が異なる文字で始まるファイルのほかにプレースホルダーが含まれている場合、Athena はプレースホルダーのみを無視し、他のファイルにクエリを実行します。そのため、1 つ以上のレコードを取得できます。

例:

  • s3://doc-example-bucket/athena/inputdata/_file1
  • s3://doc-example-bucket/athena/inputdata/.file2

パーティションプロジェクション

パーティションプロジェクションの範囲外の値

パーティションプロジェクションに定義された範囲を超える値のクエリでは、エラーは返されません。代わりに、クエリはゼロ行を返します。

たとえば、データが 2020 年に開始され、projection.timestamp.range'='2020/01/01,NOW と定義されているとします。

このサンプルクエリを実行すると、クエリは正常に完了しますが 0 行が返されます。

SELECT * FROM table-name WHERE timestamp = '2019/02/02'

デフォルトのパーティションスキームに従っていないストレージテンプレート

Amazon S3 ファイルの場所が location pattern .../column=value... に従っていない場合は、カスタムの Amazon S3 パーティションスキームを指定する必要があります。カスタムスキームを定義しない場合、クエリはゼロレコードを返します。

カスタムテンプレートを使用する場合、テンプレートには各パーティション列のプレースホルダーが含まれている必要があります。カスタム S3 パーティションスキームを定義するには、「カスタム S3 ストレージの場所の指定」を参照してください。

カスタムストレージテンプレートが正しくありません

カスタムテンプレートを使用する場合は、そのテンプレートで Athena がパーティションの場所を構築できることを確認してください。また、各プレースホルダーと Amazon S3 パスの最後には 1 つのフォワードスラッシュが付いていることを確認してください。

たとえば、DDL ステートメント PARTITIOND BY (年文字列) を使用してパーティション列のを定義し、S3 ファイルの場所が** s3://doc-example-bucket/athena/inputdata/Year=2022/ であるとします。**この場所ではレコードは返されません。Amazon S3 のストレージロケーションを s3://doc-example-bucket/athena/inputdata/Year=${year} に更新します。

パーティションプロパティ

パーティション列が列挙型、整数、または日付型である場合は、パーティションのプロパティが正しく設定されていることを確認してください。この設定では、Athena が Amazon S3 上のデータ構造と一致するパーティションロケーションを構築できるようにする必要があります。

例えば、s3://doc-example-bucket/athena/inputdata/2022-01-01-01-00 という場所に、毎日午前 0 時から 1 時間後に送信される時間関連データがあるとします。

この例では、Athena テーブルは次のパーティションプロパティを使用します。

'projection.dt.format' = 'yyyy-MM-dd-HH-mm','projection.dt.range' = '2022-01-01-00-00,NOW',
'projection.dt.interval' = '1',
'projection.dt.interval.unit' = 'DAYS'

サンプルテーブルで実行されるクエリは、ゼロレコードを返します。これは、予測されるプロパティのファイルロケーションが深夜0時に対応しているためです s3://doc-example-bucket/athena/inputdata/2022-01-01-00-00。

この問題を解決するには、「**projection.dt.range」プロパティを「2022-01-01-01-00、NOW」**に設定します。

関連情報

Athena でのテーブルの作成

AWS Glue クローラの使用

パーティション射影のセットアップ

AWS公式
AWS公式更新しました 1年前