スキップしてコンテンツを表示

Athena テーブルにクエリを実行しても、レコードが取得されない理由を教えてください

所要時間2分
0

Amazon Athena で CREATE TABLE ステートメントを実行し、必要な列とそのデータ型を指定しました。しかし、SELECT* FROM テーブル名クエリを実行すると、"Zero records returned" という出力が表示されます。

解決策

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

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

AWS Glue パーティションのトラブルシューティング

クローラー設定を確認する

クローラーを使用する場合は、クローラーが特定のファイルではなく Amazon Simple Storage Service (Amazon S3) バケットを指していることを確認してください。例えば、s3://amzn-s3-demo-bucket/new/data.json の代わりに s3://amzn-s3-demo-bucket/new を使用します。

正しい LOCATION パスを使用する

入力データの Amazon S3 LOCATION パスが正しいことを確認します。また、S3 バケットパスにファイルまたはワイルドカードが含まれていないことを確認します。例えば、s3://amzn-s3-demo-bucket/new/data.json の代わりに s3://amzn-s3-demo-bucket/new LOCATION を使用します。

LOCATION パスには単一スラッシュを使用する

Athena では、二重スラッシュ (//) を含むテーブルロケーションパスは使用できません。例えば、次の LOCATION パスは空の結果を返します: s3://amzn-s3-demo-bucket/myprefix//input//

二重スラッシュのない場所にファイルをコピーするには、次の cp AWS CLI コマンドを実行します。

aws s3 cp s3://amzn-s3-demo-bucket/myprefix//input// s3://amzn-s3-demo-bucket/myprefix/input/ --recursive

注: amzn-s3-demo-bucket/myprefix//input// を現在のテーブルロケーションパスに置き換え、amzn-s3-demo-bucket/myprefix/input/ を新しいテーブルロケーションパスに置き換えてください。

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

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

テーブルごとに Amazon S3 プレフィックスを作成する

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

  • s3://amzn-s3-demo-bucket/table1.csv
  • s3://amzn-s3-demo-bucket/table2.csv

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

  • s3://amzn-s3-demo-bucket/table1/table1.csv
  • s3://amzn-s3-demo-bucket/table2/table2.csv

次に、次のクエリを実行してテーブルの場所を更新します。

ALTER TABLE table1 SET LOCATION 's3://amzn-s3-demo-bucket/table1';

注: amzn-s3-demo-bucket を実際のバケット名に、table1 をテーブル名に置き換えてください。

パーティションをロードする

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

Athena がパーティションのフォーマットをサポートしている場合は、MSCK REPAIR TABLE を実行してパーティションのメタデータをカタログにロードします。例えば、Year で分割されたテーブルがあるとします。この場合、Athena は次の例のような Amazon S3 パスでデータを見つけることを想定しています。

  • s3://amzn-s3-demo-bucket/athena/inputdata/year=2020/data.csv
  • s3://amzn-s3-demo-bucket/athena/inputdata/year=2019/data.csv
  • s3://amzn-s3-demo-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://amzn-s3-demo-bucket/athena/inputdata/';

Athena がテーブルを作成したら、次のコマンドを実行してパーティション情報をロードします。

MSCK REPAIR TABLE Employee;

Athena がデータをロードしたら、次のクエリを再度実行します。

SELECT * FROM Employee;

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

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

  • s3://amzn-s3-demo-bucket/athena/inputdata/2020/data.csv
  • s3://amzn-s3-demo-bucket/athena/inputdata/2019/data.csv
  • s3://amzn-s3-demo-bucket/athena/inputdata/2018/data.csv

前述のパスでは、次の例のようなコマンドを実行します。

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

Athena がデータをロードしたら、次のクエリを再度実行します。

SELECT * FROM Employee;

ファイル名を確認する

ファイル名がアンダースコアまたはピリオドで始まっていないことを確認します。

クエリを処理すると、Athena はこれらのファイルをプレースホルダーと見なし、無視します。Amazon S3 パス内のすべてのファイルの名前がアンダースコアまたはピリオドで始まる場合、レコードはゼロになります。

例えば、Amazon S3 パスに次のファイルを使用してクエリを処理した場合、レコードはゼロになります。

  • s3://amzn-s3-demo-bucket/athena/inputdata/_file1
  • s3://amzn-s3-demo-bucket/athena/inputdata/.file2

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

パーティション射影のトラブルシューティング

値が範囲内であることを確認する

値がパーティション射影で定義された範囲を超える場合、クエリで返される行はありません。

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

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

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

ストレージテンプレートのパーティションスキームを確認する

Amazon S3 の保存場所が**.../column=value...** ロケーションパターンを使用しない場合、カスタムの Amazon S3 パーティションスキームを指定する必要があります。カスタムスキームを定義しない場合、クエリが返すレコードはゼロになります。

正しいカスタムストレージテンプレートを使用する

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

例えば、PARTITIONED BY (年文字列) データ定義言語 (DDL) ステートメントを使用して year パーティション列を定義し、保存場所が s3://amzn-s3-demo-bucket/athena/inputdata/Year=2022/ であるとします。この場所で返されるレコードはゼロになります。この問題を解決するには、保存場所を s3://amzn-s3-demo-bucket/athena/inputdata/Year=${year} に更新します。

パーティションのプロパティを確認する

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

例えば、s3://amzn-s3-demo-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://amzn-s3-demo-bucket/athena/inputdata/2022-01-01-00-00 に対応しているため、レコードは返されません。

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

関連情報

Athena でテーブルを作成する

クローラーを使用してテーブルを追加する

パーティション射影を設定する

AWS公式更新しました 9ヶ月前
コメントはありません