

# Amazon Athena で SQL クエリを実行する
<a name="querying-athena-tables"></a>

AWS Glue Data Catalog に登録されているデータソース、および Hive メタストアや Amazon DocumentDB インスタンスなどの Athena の横串検索を使用して接続するデータソースで Amazon Athenaを使用して SQL クエリを実行できます。データソースの使用の詳細については、「[データソースに接続する](work-with-data-stores.md)」を参照してください。スキーマを変更するデータ定義言語 (DDL) クエリを実行すると、Athena がメタデータをデータソースに関連付けられたメタストアに書き込みます。さらに、`CREATE TABLE AS` や `INSERT INTO` などの一部のクエリは、データセットにレコードを書き込むことができます。例えば、CSV レコードを Simple Storage Service (Amazon S3) ロケーションに追加できます。

このセクションでは、さまざまな SQL ステートメントを使用して、一般的なデータソースとデータ型で Athena クエリを実行するためのガイダンスを提供します。一般的な構造と演算子での作業 (例えば、配列の使用、連結、フィルタリング、フラット化、および並べ替えなど) に対する一般的なガイダンスが提供されます。その他の例としては、ネスト化された構造とマッピングのテーブル内のデータのクエリ、JSON エンコード形式のデータセットに基づくテーブル、AWS CloudTrail ログや Amazon EMR ログなどの AWS のサービス に関連付けられたデータセットなどがあります。標準的な SQL の使用に関する包括的な説明は、このドキュメントの対象範囲外です。SQL の詳細については、[Trino](https://trino.io/docs/current/language.html) および [Presto](https://prestodb.io/docs/current/sql.html) の言語リファレンスを参照してください。

**Topics**
+ [クエリプランを表示する](query-plans.md)
+ [クエリ結果と最近のクエリを操作する](querying.md)
+ [Athena でクエリ結果を再利用する](reusing-query-results.md)
+ [クエリ統計を表示する](query-stats.md)
+ [ビューを使用する](views.md)
+ [保存されたクエリを使用する](saved-queries.md)
+ [パラメータ化されたクエリを使用する](querying-with-prepared-statements.md)
+ [コストベースオプティマイザーを使用する](cost-based-optimizer.md)
+ [S3 Express One Zone をクエリする](querying-express-one-zone.md)
+ [Amazon Glacier をクエリする](querying-glacier.md)
+ [スキーマの更新を処理する](handling-schema-updates-chapter.md)
+ [クエリ配列](querying-arrays.md)
+ [地理空間データをクエリする](querying-geospatial-data.md)
+ [JSON データをクエリする](querying-JSON.md)
+ [ML with Athena を使用する](querying-mlmodel.md)
+ [UDF を使用してクエリする](querying-udf.md)
+ [リージョン全体でクエリする](querying-across-regions.md)
+ [AWS Glue Data Catalog をクエリする](querying-glue-catalog.md)
+ [AWS のサービス ログをクエリする](querying-aws-service-logs.md)
+ [ウェブサーバーログをクエリする](querying-web-server-logs.md)

考慮事項と制限事項については、「[Amazon Athena での SQL クエリに関する考慮事項と制約事項](other-notable-limitations.md)」を参照してください。

# SQL クエリの実行プランを表示する
<a name="query-plans"></a>

Athena クエリエディタを使用して、クエリがどのように実行されるかについてのグラフィック表現を表示できます。エディタでクエリを入力して **[Explain]** オプションを選択すると、Athena はクエリで [EXPLAIN](athena-explain-statement.md) SQL ステートメントを使用して、分散実行プランと論理実行プランの 2 つの対応するグラフを作成します。クエリの分析、トラブルシューティング、および効率の向上のために、これらのグラフを使用できます。

**クエリの実行プランを表示するには**

1. Athena クエリエディタにクエリを入力し、**[Explain]** を選択します。  
![\[Athena クエリエディタで [Explain] を選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-plans-1.png)

   **[Distributed plan]** (分散プラン) タブには、分散環境でのクエリの実行プランが表示されます。分散プランには、処理フラグメントまたはステージがあります。各ステージには 0 ベースのインデックス番号があり、1 つまたは複数のノードによって処理されます。データはノード間で交換できます。  
![\[サンプルクエリの分散プランのグラフ。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-plans-2.png)

1. グラフを操作するには、次のオプションを使用します。
   + ズームインまたはズームアウトするには、マウスでスクロールするか、拡大アイコンを使用します。
   + 画面に合わせてグラフを調整するには、**[Zoom to fit]** (ズームして合わせる) アイコンを選択します。
   + グラフを移動するには、マウスポインタをドラッグします。

1. ステージの詳細を表示するには、ステージを選択します。  
![\[ステージを選択すると、そのステージの詳細が表示されます。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-plans-3.png)

1. ステージの詳細を全幅で表示するには、詳細ペインの右上にある拡大アイコンを選択します。

1. 詳細を表示するには、オペレーターツリーで 1 つ以上の項目を展開します。分散プランフラグメントの詳細については、「[EXPLAIN ステートメントの出力タイプ](athena-explain-statement-understanding.md#athena-explain-statement-understanding-explain-plan-types)」を参照してください。  
![\[分散クエリプランのステージ用の展開されたオペレーターツリー。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-plans-4.png)
**重要**  
現在、一部のパーティションフィルターは、Athena がクエリに適用しても、ネストされたオペレーターツリーグラフに表示されない場合があります。このようなフィルターの効果を検証するには、クエリで [EXPLAIN](athena-explain-statement.md#athena-explain-statement-syntax-athena-engine-version-2) または [EXPLAIN ANALYZE](athena-explain-statement.md#athena-explain-analyze-statement) を実行し、結果を表示します。

1. **[Logical plan]** (論理プラン) タブを選択します。グラフには、クエリを実行するための論理プランが表示されます。運用条件については、「[Athena EXPLAIN ステートメントの結果を理解する](athena-explain-statement-understanding.md)」を参照してください。  
![\[Athena の論理クエリプランのグラフ。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-plans-5.png)

1. プランを SVG または PNG 画像として、または JSON テキストとしてエクスポートするには、**[Export]** (エクスポート) を選択します。

## 追加リソース
<a name="query-plans-additional-resources"></a>

詳細については、以下のリソースを参照してください。

[Athena での EXPLAIN および EXPLAIN ANALYZE の使用](athena-explain-statement.md)

[Athena EXPLAIN ステートメントの結果を理解する](athena-explain-statement-understanding.md)

[完了したクエリの統計と実行の詳細を表示する](query-stats.md)

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/7JUyTqglmNU/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/7JUyTqglmNU)


# クエリ結果と最近のクエリを操作する
<a name="querying"></a>

Amazon Athena は、Amazon S3 で指定できる*クエリ結果の場所*に、実行される各クエリのクエリ結果とクエリ実行結果メタデータを自動的に保存します。必要に応じて、この場所にあるファイルにアクセスして操作できます。Athena コンソールからクエリ結果ファイルを直接ダウンロードすることもできます。

Athena では、クエリ結果を管理するための 2 つのオプションが提供されるようになりました。お客様がお持ちの S3 バケットを使用するか、マネージドクエリ結果機能を選択できます。独自のバケットを使用すると、ストレージ、アクセス許可、ライフサイクルポリシー、保持などを完全に制御できるため、最大限の柔軟性が得られますが、より多くの管理が必要になります。または、マネージドクエリ結果オプションを選択すると、ストレージとライフサイクルの管理は自動的にサービスで処理されるため、別の結果バケットを設定する必要がなくなり、事前定義された保持期間後に結果が自動的にクリーンアップされます。詳細については、「[マネージドクエリ結果](managed-results.md)」を参照してください。

Amazon S3 にクエリ結果の場所を初めてセットアップするときは、「[Athena コンソールを使用してクエリ結果の場所を指定する](query-results-specify-location-console.md)」を参照してください。

出力ファイルは、実行されるすべてのクエリに対して自動的に保存されます。Athena コンソールを使用してクエリ出力ファイルにアクセスして表示するには、IAM プリンシパル (ユーザーとロール) に、クエリ結果ロケーションに対する Amazon S3 の [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) アクションの許可と、Athenaの [GetQueryResults](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryResults.html) アクションの許可が必要です。クエリの結果の場所は暗号化できます。場所が暗号化されている場合、ユーザーには、クエリ結果の場所を暗号化および復号するための適切なキーアクセス許可が必要です。

**重要**  
クエリ結果の場所に対する Amazon S3 の `GetObject` アクションの許可を持つ IAM プリンシパルは、Athena の `GetQueryResults` アクションの許可が拒否された場合でも、Amazon S3 からクエリ結果を取得できます。

**注記**  
キャンセルされた、または失敗したクエリの場合、Athena が既に部分的な結果を Amazon S3 に書き込んでいる可能性があります。このような場合、Athena は結果が保存されている Amazon S3 プレフィックスから部分的な結果を削除しません。部分的な結果がある Amazon S3 プレフィックスを削除する必要があります。Athena は、Amazon S3 マルチパートアップロードを使用して Amazon S3 データを書き込みます。クエリが失敗した場合にはマルチパートアップロードを中止するように、バケットライフサイクルポリシーを設定することが推奨されます。詳細については、「*Amazon Simple Storage Service ユーザーガイド*」の「[マルチパートアップロードを使用したオブジェクトのアップロードとコピー](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html#mpu-abort-incomplete-mpu-lifecycle-config)」を参照してください。
特定の条件下では、Athena がクエリ実行を自動的に再試行することがあります。ほとんどの場合、これらのクエリは正常に完了し、クエリ ID は `Completed` とマークされます。これらのクエリは、最初の試行時に既に部分的な結果を書き込んでいる可能性があり、不完全なマルチパートアップロードになる恐れがあります。

**Topics**
+ [マネージドクエリ結果](managed-results.md)
+ [クエリ結果の場所を指定する](query-results-specify-location.md)
+ [Athena コンソールを使用してクエリ結果ファイルをダウンロードする](saving-query-results.md)
+ [Athena コンソールで最近のクエリを表示する](queries-viewing-history.md)
+ [複数の最近のクエリを CSV ファイルにダウンロードする](queries-downloading-multiple-recent-queries-to-csv.md)
+ [最近のクエリ表示オプションを設定する](queries-recent-queries-configuring-options.md)
+ [クエリ履歴を 45 日間よりも長く保持する](querying-keeping-query-history.md)
+ [Amazon S3 でクエリ出力ファイルを検索する](querying-finding-output-files.md)

# マネージドクエリ結果
<a name="managed-results"></a>

マネージドクエリ結果を使用することで、クエリ結果ストレージ用の Amazon S3 バケットを指定せずに SQL クエリを実行できるようになります。これにより、独自の S3 バケットをプロビジョニング、管理、アクセスの制御、クリーンアップする必要がなくなります。開始するには、新しいワークグループを作成するか、既存のワークグループを編集します。**[クエリ結果の設定]** で、**[Athena マネージド]** を選択します。

**主な特徴**
+ クエリを実行する前に S3 バケットの場所を選択する要件を削除することで、ワークフローを簡素化します。
+ マネージドクエリ結果の使用とクエリ結果の自動削除に追加のコストがかからないため、管理オーバーヘッドが削減され、個別の S3 バケットクリーンアッププロセスが不要になります。
+ 開始が簡単: マネージドクエリ結果を使用するように新規および既存のワークグループを簡単に設定できます。AWS アカウントで Athena マネージドクエリ結果とカスタマーマネージドクエリ結果を混在させることができます。
+ 個々のワークグループに関連付けられた `GetQueryResults` と `GetQueryResultsStream` を介して結果を読み取るアクセス許可で、IAM アクセス許可を合理化しました。
+ クエリ結果は、選択した AWS 所有キーまたはカスタマー所有キーで自動的に暗号化されます。

## 考慮事項と制限事項
<a name="managed-results-considerations"></a>

****
+ クエリ結果へのアクセスは、Athena のワークグループレベルで管理されます。そのため、特定のワークグループに対する `GetQueryResults` および `GetQueryResultsStream` IAM アクションへの明示的なアクセス許可が必要です。`GetQueryResults` アクションは、完了したクエリの結果をページ分割形式で取得できるユーザーを決定します。一方、`GetQueryResultsStream` アクションは、完了したクエリの結果をストリーミングできるユーザーを決定します (Athena ドライバーで一般的に使用されます)。
+ 200 MB を超えるクエリ結果ファイルをコンソールからダウンロードすることはできません。`UNLOAD` ステートメントを使用して、200 MB を超える結果を個別にダウンロードできる場所に書き込みます。
+ マネージドクエリ結果機能は、[クエリ結果の再利用](reusing-query-results.md)をサポートしていません。
+ クエリ結果は 24 時間利用できます。この期間中、クエリ結果は無償で保存されます。この期間を過ぎると、クエリ結果は自動的に削除されます。

## マネージドクエリ結果を使用してワークグループを作成または編集する
<a name="using-managed-query-results"></a>

コンソールからワークグループを作成したり、マネージドクエリ結果を使用して既存のワークグループを更新したりする方法

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/) で Athena コンソールを開きます。

1. 左側のナビゲーションから **[ワークグループ]** を選択します。

1. **[ワークグループを作成]** を選択して新しいワークグループを作成するか、リストから既存のワークグループを編集します。

1. **[クエリ結果の設定]**で、**[Athena マネージド]** を選択します。  
![\[クエリ結果の設定メニュー。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/athena-managed.png)

1. **クエリ結果を暗号化**する場合は、必要な暗号化オプションを選択します。詳細については、「[クエリ結果の暗号化を選択する](#managed-query-results-encryption-at-rest)」を参照してください。

1. その他の必要な詳細をすべて入力し、**[変更を保存]** を選択します。

## クエリ結果の暗号化を選択する
<a name="managed-query-results-encryption-at-rest"></a>

暗号化の設定には次の 2 つのオプションがあります。
+ **AWS 所有キーを使用して暗号化する** – マネージドクエリ結果を使用する場合のデフォルトのオプションです。クエリ結果を AWS 所有キーで暗号化する場合は、このオプションを選択します。
+ **カスタマーマネージドキーを使用して暗号化する** – カスタマーマネージドキーを使用してクエリ結果を暗号化および復号する場合は、このオプションを選択します。カスタマーマネージドキーを使用するには、キーポリシーセクションのプリンシパル要素に Athena サービスを追加します。詳細については、「[マネージドクエリ結果の AWS KMS キーポリシーを設定する](#managed-query-results-set-up)」を参照してください。クエリを正常に実行するには、クエリを実行しているユーザーに AWS KMS キーへのアクセス許可を付与する必要があります。

## マネージドクエリ結果の AWS KMS キーポリシーを設定する
<a name="managed-query-results-set-up"></a>

キーポリシーの `Principal` セクションでは、このキーを使用できるユーザーを指定します。マネージドクエリ結果機能には、`Principal` セクションで指定する必要があるプリンシパル `encryption.athena.amazonaws.com` が導入されています。このサービスプリンシパルは、Athena が所有していないキーへのアクセス専用です。また、マネージド結果にアクセスするために使用するキーポリシーに、`kms:Decrypt`、`kms:GenerateDataKey`、および `kms:DescribeKey` アクションを追加する必要があります。これらの 3 つのアクションは、許可された最小限のアクションです。

マネージドクエリの結果は、[暗号化コンテキスト](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)にワークグループ ARN を使用します。`Principal` セクションは AWS サービスであるため、キーポリシー条件に `aws:sourceArn` と `aws:sourceAccount` も追加する必要があります。次の例は、1 つのワークグループに対する最小限のアクセス許可を持つ AWS KMS キーポリシーを示しています。

```
 {
    "Sid": "Allow athena service principal to use the key",
    "Effect": "Allow",
    "Principal": {
        "Service": "encryption.athena.amazonaws.com"
    },
    "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey",
        "kms:DescribeKey"
      ],
    "Resource": "arn:aws:kms:us-east-1:{account-id}:key/{key-id}",
    "Condition": {
    "ArnLike": {
        "kms:EncryptionContext:aws:athena:arn": "arn:aws:athena:us-east-1:{account-id}:workgroup/{workgroup-name}",
        "aws:SourceArn": "arn:aws:athena:us-east-1:{account-id}:workgroup/{workgroup-name}"
    },
    "StringEquals": {
        "aws:SourceAccount": "{account-id}"
    }
}
```

次の AWS KMS キーポリシーの例では、同じアカウント *account-id* 内のすべてのワークグループに同じ AWS KMS キーの使用を許可します。

```
{
    "Sid": "Allow athena service principal to use the key",
    "Effect": "Allow",
    "Principal": {
        "Service": "encryption.athena.amazonaws.com"
    },
    "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey",
        "kms:DescribeKey"
    ],
    "Resource": "arn:aws:kms:us-east-1:account-id:key/{key-id}",
    "Condition": {
        "ArnLike": {
          "kms:EncryptionContext:aws:athena:arn": "arn:aws:athena:us-east-1:account-id:workgroup/*",
          "aws:SourceArn": "arn:aws:athena:us-east-1:account-id:workgroup/*"
        },
        "StringEquals": {
          "aws:SourceAccount": "account-id"
        }
    }
}
```

Athena および Amazon S3 のアクセス許可に加えて、`kms:GenerateDataKey` および `kms:Decrypt` アクションを実行するアクセス許可も取得する必要があります。詳細については、「[Amazon S3 の暗号化されたデータに対する許可](encryption.md#permissions-for-encrypting-and-decrypting-data)」を参照してください。

マネージドクエリ結果の暗号化の詳細については、[マネージドクエリ結果を暗号化する](encrypting-managed-results.md) を参照してください。

# マネージドクエリ結果を暗号化する
<a name="encrypting-managed-results"></a>

Athena は、[マネージドクエリ結果](managed-results.md) を暗号化するための以下のオプションを提供します。

## AWS 所有キーを使用した暗号化
<a name="encrypting-managed-results-aws-owned-key"></a>

これは、マネージドクエリ結果を使用する場合のデフォルトのオプションです。このオプションは、ユーザーが AWS 所有キーを使用してクエリ結果を暗号化することを示します。AWS 所有キーが AWS アカウントに保存されることはなく、AWS 所有の KMS キーのコレクションの一部となります。AWS 所有のキーを利用しても利用料はかからず、アカウントの AWS KMS クォータにもカウントされません。

## AWS KMS カスタマーマネージドキーを使用して暗号化する
<a name="encrypting-managed-results-customer-managed-key"></a>

カスタマーマネージドキーは、お客様が作成、所有、管理する AWS アカウントの KMS キーです。これらの KMS キーでは、キーポリシー、IAM ポリシー、権限の確立と管理、有効化と無効化、暗号化マテリアルのローテーション、タグの追加、KMS キーを参照するエイリアスの作成 、KMS キー削除のスケジューリングなどを含め、これらを完全に制御できます。詳細については、「[カスタマーマネージドキー](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)」を参照してください。

## Athena がカスタマーマネージドキーを使用して結果を暗号化する方法
<a name="encrypting-managed-results-how-ate-uses-cmk"></a>

カスタマーマネージドキーを指定すると、Athena はマネージドクエリ結果に保存されるときに、そのマネージドキーを使用してクエリ結果を暗号化します。`GetQueryResults` を呼び出すと、結果の復号に同じキーが使用されます。カスタマーマネージドキーの状態を無効に設定するか、マネージドキーの削除をスケジュールすると、Athena とすべてのユーザーがこのキーで結果を暗号化または復号できなくなります。

Athena は、エンベロープ暗号化とキー階層を使用してデータを暗号化します。AWS KMS 暗号化キーは、このキー階層のルートキーを生成および復号するために使用されます。

各結果は、暗号化時にワークグループで設定されたカスタマーマネージドキーを使用して暗号化されます。キーを別のカスタマーマネージドキーまたは AWS 所有キーに切り替えても、新しいキーで既存の結果を再暗号化することはありません。特定のカスタマーマネージドキーの削除と無効化は、そのキーで暗号化した結果の復号にのみ影響します。

Athena は、結果を暗号化および復号するための `kms:Decrypt`、`kms:GenerateDataKey`、および `kms:DescribeKey` オペレーションを実行するために、暗号化キーにアクセスする必要があります。詳細については、「[Amazon S3 の暗号化されたデータに対する許可](encryption.md#permissions-for-encrypting-and-decrypting-data)」を参照してください。

`StartQueryExecution` API を使用してクエリを送信し、`GetQueryResults` を使用して結果を読み取るプリンシパルには、Athena および Amazon S3 のアクセス許可に加えて、`kms:Decrypt`、`kms:GenerateDataKey`、および `kms:DescribeKey` オペレーションのカスタマーマネージドキーに対するアクセス許可も必要です。詳細については、「[AWS KMS のキーポリシー](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users)」を参照してください。

# クエリ結果の場所を指定する
<a name="query-results-specify-location"></a>

Athena が使用するクエリ結果の場所は、ワークグループの設定とクライアント側の設定の組み合わせによって決定されます。クライアント側の設定は、クエリの実行方法に基づいています。
+  Athena コンソールを使用してクエリを実行する場合は、ナビゲーションバーの **[Settings]** (設定) で入力した **[Query result location]** (クエリ結果の場所) がクライアント側の設定を決定します。
+ Athena API を使用してクエリを実行する場合は、[StartQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StartQueryExecution.html) アクションの `OutputLocation` パラメータがクライアント側の設定を決定します。
+ ODBC または JDBC ドライバーを使用してクエリを実行する場合、接続 URL で指定された `S3OutputLocation` プロパティによってクライアント側の設定が決まります。

**重要**  
API または ODBC または JDBC ドライバーを使用してクエリを実行する場合、コンソールの設定は適用されません。

各ワークグループ設定には、[[Override client-side settings (クライアント側設定の上書き)]](https://docs.aws.amazon.com/athena/latest/ug/workgroups-settings-override.html) オプションがあり、有効にできます。このオプションを有効にすると、そのワークグループに関連付けられている IAM プリンシパルがクエリを実行するときに、適切なクライアント側の設定よりもワークグループの設定が優先されます。

## 以前に作成されたデフォルトの場所について
<a name="query-results-specify-location-previous-defaults"></a>

これまで Athena では、**クエリ結果の場所**の値を指定せずにクエリを実行し、クエリ結果の場所の設定がワークグループによって上書きされなかった場合は、Athena がデフォルトの場所を作成していました。デフォルトの場所は `aws-athena-query-results-MyAcctID-MyRegion` でした。*MyAcctID* はクエリを実行した IAM プリンシパルの Amazon Web Services アカウント ID で、*MyRegion* はクエリが実行されたリージョン (`us-west-1` など) です。

今後は、以前に Athena を使用したことがないアカウントがあるリージョンで Athena クエリを実行する前に、クエリ結果の場所を指定するか、クエリ結果の場所の設定を上書きするワークグループを使用しなければならなくなります。Athena はデフォルトのクエリ結果の場所を作成しなくなりましたが、以前に作成されたデフォルトの `aws-athena-query-results-MyAcctID-MyRegion` の場所は引き続き有効で、使用を継続できます。

**Topics**
+ [以前に作成されたデフォルトの場所について](#query-results-specify-location-previous-defaults)
+ [Athena コンソールを使用してクエリ結果の場所を指定する](query-results-specify-location-console.md)
+ [ワークグループを使用してクエリ結果の場所を指定する](query-results-specify-location-workgroup.md)

# Athena コンソールを使用してクエリ結果の場所を指定する
<a name="query-results-specify-location-console"></a>

クエリを実行する前に、Amazon S3 のクエリ結果バケットの場所を指定しておく、または指定されたバケットがあり、その設定がクライアント設定を上書きするワークグループを使用する必要があります。

**Athena コンソールを使用してクライアント側の設定のクエリ結果の場所を指定する**

1. クエリ結果の場所を指定するワークグループに[切り替えます](switching-workgroups.md)。デフォルトのワークグループの名前は **primary** です。

1. ナビゲーションバーから **[Settings]** (設定) を選択します。

1. ナビゲーションバーで **[Manage]** (管理) を選択します。

1. **[Manage settings]** (設定の管理) で、以下のいずれかを実行します。
   + **[Location of query result]** (クエリ結果の場所) ボックスで、クエリ結果のために Amazon S3 に作成したバケットへのパスを入力します。パスの先頭に `s3://` を付けます。
   + **[Browse S3]** (S3 をブラウズ) をクリックし、現在のリージョンで作成した Amazon S3 バケットを選択した上で、**[Choose]** (選択) をクリックします。
**注記**  
ワークグループのすべてのユーザーに対してクエリ結果の場所を指定するワークグループを使用している場合、クエリ結果の場所を変更するオプションは使用できません。

1. (オプション) **[View lifecycle configuration]** (ライフサイクル設定を表示) を選択すると、クエリ結果バケットの [[Amazon S3 lifecycle rules]](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html) (Amazon S3 ライフサイクルルール) を表示および設定できます。作成する Amazon S3 ライフサイクルルールは、有効期限ルールまたは移行ルールのいずれでも可能です。有効期限ルールでは、一定の時間が経過するとクエリ結果は自動的に削除されます。移行ルールは別の Amazon S3 ストレージ階層に移動します。詳細については、Amazon Simple Storage Service ユーザーガイドの「[バケットのライフサイクル設定の指定](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html)」を参照してください。

1. (オプション) **[Expected bucket owner]** (想定されるバケット所有者) に、出力ロケーションバケットの所有者になると想定されている AWS アカウント の ID を入力します。これは追加のセキュリティ対策です。バケット所有者のアカウント ID がここで指定した ID と一致しない場合、バケットに出力できません。詳細については、「*Amazon S3 ユーザーガイド*」の「[バケット所有者条件によるバケット所有者の確認](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html)」を参照してください。
**注記**  
予期されるバケット所有者の設定は、Athena クエリの結果の出力先として指定した Amazon S3 内の場所にのみ適用されます。これは、外部 Simple Storage Service (Amazon S3) バケット内のデータソースの場所、`CTAS` や `INSERT INTO` の書き込み先のテーブルの場所、`UNLOAD` ステートメントの出力場所、串刺検索のバケットのスピルオペレーション、別のアカウントのテーブルに対して実行される `SELECT` クエリなど、他の Amazon S3 ロケーションには適用されません。

1. (オプション) Simple Storage Service (Amazon S3) に保存されているクエリ結果を暗号化するには、**[Encrypt query results]** (クエリ結果の暗号化) を選択します。Athena の暗号化に関する詳細については、[保管中の暗号化](encryption.md) を参照してください。

1. (オプション) クエリ結果バケットの [ACL が有効になっている](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)ときに、バケット所有者にクエリ結果に対するフルコントロールアクセスを割り当てるには、**[Assign bucket owner full control over query results]** (クエリ結果に対する完全なコントロールをバケット所有者に付与する) を選択します。たとえば、クエリ結果の場所を別のアカウントが所有している場合に、クエリ結果の所有権とフルコントロールを他のアカウントに付与することができます。詳細については、「*Amazon S3 ユーザーガイド*」の「[オブジェクトの所有権のコントロールとバケットに対する ACL の無効化](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)」を参照してください。

1. **[Save]** (保存) を選択します。

# ワークグループを使用してクエリ結果の場所を指定する
<a name="query-results-specify-location-workgroup"></a>

AWS マネジメントコンソール、AWS CLI、または Athena API を使用して、ワークグループ設定でクエリ結果の場所を指定します。

AWS CLI を使用する場合、[https://docs.aws.amazon.com/cli/latest/reference/athena/create-work-group.html](https://docs.aws.amazon.com/cli/latest/reference/athena/create-work-group.html) または [https://docs.aws.amazon.com/cli/latest/reference/athena/update-work-group.html](https://docs.aws.amazon.com/cli/latest/reference/athena/update-work-group.html) コマンドを実行するときに `--configuration` オプションの `OutputLocation` パラメータを使用してクエリ結果の場所を指定します。

**Athena コンソールを使用してワークグループのクエリ結果の場所を指定する**

1. コンソールのナビゲーションペインが表示されない場合は、左側の展開メニューをクリックします。  
![\[展開メニューを選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/nav-pane-expansion.png)

1. ナビゲーションペインで、**[Workgroups]** (ワークグループ) を選択します。

1. ワークグループのリストで、編集するワークグループのリンクを選択します。

1. **[編集]** を選択します。

1. **クエリ結果の場所と暗号化**については、次のいずれかを実行します。
   + **[Location of query result]** (クエリ結果の場所) ボックスに、クエリ結果のために Amazon S3 のバケットへのパスを入力します。パスの先頭に `s3://` を付けます。
   + **[Browse S3]** (S3 のブラウズ) で、使用する現在のリージョン用の Amazon S3 バケットを選択し、**[Choose]** (選択) を選択します。

1. (オプション) **[Expected bucket owner]** (想定されるバケット所有者) に、出力ロケーションバケットの所有者になると想定されている AWS アカウント の ID を入力します。これは追加のセキュリティ対策です。バケット所有者のアカウント ID がここで指定した ID と一致しない場合、バケットに出力できません。詳細については、「*Amazon S3 ユーザーガイド*」の「[バケット所有者条件によるバケット所有者の確認](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html)」を参照してください。
**注記**  
予期されるバケット所有者の設定は、Athena クエリの結果の出力先として指定した Amazon S3 内の場所にのみ適用されます。これは、外部 Simple Storage Service (Amazon S3) バケット内のデータソースの場所、`CTAS` や `INSERT INTO` の書き込み先のテーブルの場所、`UNLOAD` ステートメントの出力場所、串刺検索のバケットのスピルオペレーション、別のアカウントのテーブルに対して実行される `SELECT` クエリなど、他の Amazon S3 ロケーションには適用されません。

1. (オプション) Simple Storage Service (Amazon S3) に保存されているクエリ結果を暗号化するには、**[Encrypt query results]** (クエリ結果の暗号化) を選択します。Athena の暗号化に関する詳細については、[保管中の暗号化](encryption.md) を参照してください。

1. (オプション) クエリ結果バケットの [ACL が有効になっている](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)ときに、バケット所有者にクエリ結果に対するフルコントロールアクセスを割り当てるには、**[Assign bucket owner full control over query results]** (クエリ結果に対する完全なコントロールをバケット所有者に付与する) を選択します。たとえば、クエリ結果の場所を別のアカウントが所有している場合に、クエリ結果の所有権とフルコントロールを他のアカウントに付与することができます。

   バケットの S3 オブジェクトの所有権の設定が **[Bucket owner preferred]** (バケット所有者推奨) となっている場合、バケット所有者は、このワークグループから書き込まれたすべてのクエリ結果オブジェクトも所有します。たとえば、外部アカウントのワークグループでこのオプションが有効になっており、そのクエリ結果の場所がアカウントの Simple Storage Service (Amazon S3) バケットに設定されている場合に、このバケットの S3 オブジェクトの所有権が **[Bucket owner preferred]** (バケット所有者推奨) と設定されていると、外部ワークグループのクエリ結果を所有し、フルコントロールアクセスを持つことになります。

   クエリ結果バケットの S3 オブジェクトの所有権設定が **[Bucket owner enforced]** (バケット所有者の強制) となっているときにこのプションを選択しても、効果はありません。詳細については、「*Amazon S3 ユーザーガイド*」の「[オブジェクトの所有権のコントロールとバケットに対する ACL の無効化](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)」を参照してください。

1. 指定したクエリ結果の場所を使用するようにワークグループのすべてのユーザーに要求する場合は、**[Settings]** (設定) セクションまで下にスクロールして、**[Override client-side settings ]** (クライアント側設定の上書き) を選択します。

1. **[Save changes]** (変更の保存) を選択します。

# Athena コンソールを使用してクエリ結果ファイルをダウンロードする
<a name="saving-query-results"></a>

クエリを実行した直後に、クエリペインからクエリ結果の CSV ファイルをダウンロードできます。最近のクエリ結果も、**[Recent queries]** (最近のクエリ) タブからダウンロードできます。

**注記**  
Athena クエリ結果ファイルは、個々のユーザーによって設定できる情報を含むデータファイルです。このデータの読み込みと分析を行うプログラムの一部は、データの一部をコマンドと解釈する可能性があります (CSV インジェクション)。このため、クエリ結果の CSV データをスプレッドシートプログラムにインポートすると、そのプログラムから、セキュリティ上の問題について警告を受ける場合があります。システムを安全に保つには、ダウンロードされたクエリ結果からリンクまたはマクロを無効にするように常に選択する必要があります。

**クエリを実行してクエリ結果をダウンロードするには**

1. クエリエディタにクエリを入力し、**[Run]** (実行) をクリックします。

   クエリの実行が終了すると、[**Results (結果)**] ペインにクエリ結果が表示されます。

1. クエリ結果の CSV ファイルをダウンロードするには、クエリ結果ペインの上にある **[Download results]** (結果のダウンロード) を選択します。ブラウザとブラウザの設定によっては、ダウンロードの確認が必要になる場合があります。  
![\[Athena コンソールでクエリ結果を .csv ファイルに保存します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/getting-started-query-results-download-csv.png)

**以前のクエリのクエリ結果ファイルをダウンロードするには**

1. **[Recent queries]** (最近のクエリ) を選択します。  
![\[[Recent queries] (最近のクエリ) をクリックして以前のクエリを表示します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/getting-started-recent-queries.png)

1. 検索ボックスを使用してクエリを見つけ、クエリを選択してから、**[Download results]** (結果のダウンロード) を選択します。
**注記**  
**[Download results]** (結果のダウンロード) オプションを使用して、手動で削除されたクエリ結果を取得したり、Amazon S3 [ライフサイクルルール](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html)によって削除または別の場所に移動されたクエリ結果を取得したりすることはできません。  
![\[(最近のクエリ) を選択して、以前のクエリ結果を検索してダウンロードします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-recent-queries-tab-download.png)

# Athena コンソールで最近のクエリを表示する
<a name="queries-viewing-history"></a>

Athena コンソールを使用して、成功したクエリと失敗したクエリの表示、および失敗したクエリのエラー詳細の表示を行うことができます。Athena では、クエリ履歴が 45 日間保持されます。

**Athena コンソールで最近のクエリを表示するには**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. **[Recent queries]** (最近のクエリ) を選択します。**[Recent queries]** (最近のクエリ) タブには、実行された各クエリに関する情報が表示されます。

1. クエリエディタでクエリステートメントを開くには、クエリの実行 ID を選択します。  
![\[クエリの実行 ID を選択してクエリエディタで表示します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-view-query-statement.png)

1. 失敗したクエリの詳細を表示するには、クエリの **[Failed]** (失敗) リンクを選択します。  
![\[クエリの [Failed] (失敗) リンクを選択して、失敗に関する情報を表示します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-view-query-failure-details.png)

# 複数の最近のクエリを CSV ファイルにダウンロードする
<a name="queries-downloading-multiple-recent-queries-to-csv"></a>

Athena コンソールの **[Recent queries]** (最近のクエリ) タブを使用すると、1 つ以上の最近のクエリを CSV ファイルにエクスポートして、表形式で表示できます。ダウンロードしたファイルには、クエリ結果ではなく、SQL クエリ文字列自体とクエリに関するその他の情報が含まれています。エクスポートされるフィールドには、実行 ID、クエリ文字列のコンテンツ、クエリの開始時間、ステータス、実行時間、スキャンされたデータ量、使用されたクエリエンジンのバージョン、および暗号化方法が含まれます。最近のクエリを最大 500 個、または検索ボックスに入力した条件を使用してフィルター処理をした最大 500 個のクエリをエクスポートできます。

**1 つ以上の最近のクエリを CSV ファイルにエクスポートするには**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. **[Recent queries]** (最近のクエリ) を選択します。

1. (オプション) 検索ボックスを使用して、ダウンロードする最近のクエリを絞り込みます。

1. **[CSV のダウンロード]** を選択します。  
![\[[CSV のダウンロード] を選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-recent-queries-csv.png)

1. ファイル保存のプロンプトで、**[Save]** (保存) を選択します。デフォルトのファイル名は、タイムスタンプによって続く `Recent Queries` です (例: `Recent Queries 2022-12-05T16 04 27.352-08 00.csv`)

# 最近のクエリ表示オプションを設定する
<a name="queries-recent-queries-configuring-options"></a>

表示する列やテキストの折り返しなど、**[Recent queries]** (最近のクエリ) タブのオプションを設定できます。

****[Recent queries]** (最近のクエリ) タブのオプションを設定するには**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. **[Recent queries]** (最近のクエリ) を選択します。

1. オプションボタン (歯車のアイコン) を選択します。  
![\[最近のクエリの表示を設定するには、オプションボタンをクリックします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-recent-queries-options.png)

1. **[Preferences ]** (設定) ダイアログボックスで、ページあたりの行数、行折り返しの動作、および表示する列を選択します。  
![\[最近のクエリの表示の設定。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-recent-queries-preferences.png)

1. **[確認]** を選択します。

# クエリ履歴を 45 日間よりも長く保持する
<a name="querying-keeping-query-history"></a>

クエリ履歴を 45 日より長く保持する場合は、クエリ履歴を取得して、Amazon S3 などのデータストアに履歴を保存できます。このプロセスを自動化するには、Athena および Amazon S3 の API アクションと CLI コマンドを使用できます。以下の手順は、これらのステップをまとめたものです。

**クエリ履歴をプログラムで取得して保存するには**

1. Athena の [ListQueryExecutions](https://docs.aws.amazon.com/athena/latest/APIReference/API_ListQueryExecutions.html) API アクション、または [list-query-executions](https://docs.aws.amazon.com/cli/latest/reference/athena/list-query-executions.html) CLI コマンドを使用して、クエリ ID を取得します。

1. Athena の [GetQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryExecution.html) API アクション、または [get-query-execution](https://docs.aws.amazon.com/cli/latest/reference/athena/get-query-execution.html) CLI コマンドを使用して、ID に基づいた各クエリに関する情報を取得します。

1. Simple Storage Service (Amazon S3) の [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) API アクション、または [put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) CLI コマンドを使用して、その情報を Amazon S3 に保存します。

# Amazon S3 でクエリ出力ファイルを検索する
<a name="querying-finding-output-files"></a>

ワークグループでクエリが発生し、そのワークグループの設定がクライアント側の設定よりも優先される場合でない限り、クエリ出力ファイルは次のパスパターンで Amazon S3 サブフォルダに保存されます。ワークグループの設定がクライアント側の設定よりも優先される場合、クエリはワークグループによって指定された結果パスを使用します。

```
QueryResultsLocationInS3/[QueryName|Unsaved/yyyy/mm/dd/]
```
+ *QueryResultsLocationInS3* は、ワークグループ設定またはクライアント側設定で指定されたクエリ結果の場所です。詳細については、このドキュメントで後述する「[クエリ結果の場所を指定する](query-results-specify-location.md)」を参照してください。
+ 次のサブフォルダは、ワークグループ設定が結果パスよりも優先されていないコンソールから実行されるクエリに対してのみ作成されます。AWS CLI から実行されるクエリまたは Athena API を使用して実行されるクエリは、*QueryResultsLocationInS3* に直接保存されます。
  + *QueryName* は結果を保存するクエリの名前です。クエリが実行されたものの、保存されなかった場合は、`Unsaved` が使用されます。
  + *yyyy/mm/dd* は、クエリが実行された日付です。

`CREATE TABLE AS SELECT` クエリに関連付けられたファイルは、上記のパターンの `tables` サブフォルダに保存されます。

## クエリ出力ファイルを識別する
<a name="querying-identifying-output-files"></a>

ファイルは、クエリの名前、クエリ ID、およびクエリが実行された日付に基づいて、Amazon S3 のクエリ結果の場所に保存されます。各クエリのファイルは *QueryID* を使用して命名されます。QueryID は、クエリの実行時に Athena が各クエリに割り当てる一意の識別子です。

次のファイルタイプが保存されます。


| ファイルタイプ | ファイル命名パターン | 説明 | 
| --- | --- | --- | 
|  **クエリ結果ファイル**  |  `QueryID.csv` `QueryID.txt`  |  DML クエリ結果ファイルはカンマ区切り値 (CSV) 形式で保存されます。 DDL クエリ結果は、プレーンテキストファイルとして保存されます。 結果ファイルは、コンソールの使用時には [**Results**] (結果) ペインから、またはクエリの [**History**] (履歴) からダウンロードできます。詳細については、「[Athena コンソールを使用してクエリ結果ファイルをダウンロードする](saving-query-results.md)」を参照してください。  | 
|  **クエリメタデータファイル**  |  `QueryID.csv.metadata` `QueryID.txt.metadata`  |  DML および DDL クエリメタデータファイルはバイナリ形式で保存され、人間が読めるものではありません。ファイル拡張子は、関連するクエリ結果ファイルに対応しています。Athena は、`GetQueryResults` アクションを使用してクエリ結果を読み込むときに、メタデータを使用します。これらのファイルは削除できますが、クエリに関する重要な情報が失われるため、お勧めしません。  | 
|  **データマニフェストファイル**  |  `QueryID-manifest.csv`  |  データマニフェストファイルは、[INSERT INTO](insert-into.md) クエリの実行時に Athena が Simple Storage Service (Amazon S3) データソースの場所に作成するファイルを追跡するために生成されます。クエリが失敗した場合、マニフェストはクエリが書き込むことを意図したファイルも追跡します。マニフェストは、失敗したクエリの結果として孤立したファイルを識別するのに役立ちます。  | 

## AWS CLI を使用して、クエリ出力の場所とファイルを特定する
<a name="querying-finding-output-files-cli"></a>

AWS CLI を使用してクエリ出力の場所と結果ファイルを特定するには、次の例のように、`aws athena get-query-execution` コマンドを実行します。*abc1234d-5efg-67hi-jklm-89n0op12qr34* をクエリ ID に置き換えます。

```
aws athena get-query-execution --query-execution-id abc1234d-5efg-67hi-jklm-89n0op12qr34
```

このコマンドにより、以下のような出力が返されます。各出力パラメータの説明については、*AWS CLI コマンドリファレンス*の「[get-query-execution](https://docs.aws.amazon.com/cli/latest/reference/athena/get-query-execution.html)」を参照してください。

```
{
    "QueryExecution": {
        "Status": {
            "SubmissionDateTime": 1565649050.175,
            "State": "SUCCEEDED",
            "CompletionDateTime": 1565649056.6229999
        },
        "Statistics": {
            "DataScannedInBytes": 5944497,
            "DataManifestLocation": "s3://amzn-s3-demo-bucket/athena-query-results-123456789012-us-west-1/MyInsertQuery/2019/08/12/abc1234d-5efg-67hi-jklm-89n0op12qr34-manifest.csv",
            "EngineExecutionTimeInMillis": 5209
        },
        "ResultConfiguration": {
            "EncryptionConfiguration": {
                "EncryptionOption": "SSE_S3"
            },
            "OutputLocation": "s3://amzn-s3-demo-bucket/athena-query-results-123456789012-us-west-1/MyInsertQuery/2019/08/12/abc1234d-5efg-67hi-jklm-89n0op12qr34"
        },
        "QueryExecutionId": "abc1234d-5efg-67hi-jklm-89n0op12qr34",
        "QueryExecutionContext": {},
        "Query": "INSERT INTO mydb.elb_log_backup SELECT * FROM mydb.elb_logs LIMIT 100",
        "StatementType": "DML",
        "WorkGroup": "primary"
    }
}
```

# Athena でクエリ結果を再利用する
<a name="reusing-query-results"></a>

Athena でクエリを再実行する場合、オプションで最後に保存されたクエリ結果を再利用することを選択できます。このオプションにより、パフォーマンスが向上し、スキャンされるバイト数によりコストが削減されます。クエリの結果を再利用することは、たとえば、特定の時間枠内で結果に変化がないことがわかっている場合に役立ちます。クエリの結果を再利用できる最大有効期間を指定できます。Athena では、指定した経過日数を超えない限り、保存された結果を使用します。詳細については、*AWS Big Data Blog* の「[Reduce cost and improve query performance with Amazon Athena](https://aws.amazon.com/blogs/big-data/reduce-cost-and-improve-query-performance-with-amazon-athena-query-result-reuse/)」を参照してください。

## 主な特徴
<a name="reusing-query-results-key-features"></a>

クエリの結果の再利用を有効にすると、Athena は同じワークグループ内で以前に実行されたクエリを検索します。Athena は、一致を検出すると実行をバイパスし、前の一致する実行のクエリ結果を返します。クエリの結果の再利用はクエリごとに有効にできます。

次の条件がすべて満たされた場合、Athena は最後のクエリ結果を再利用します。
+ Athena による決定に従ってクエリ文字列が一致する。
+ データベースとカタログ名が一致する。
+ 前の結果の有効期限が切れていない。
+ クエリ結果設定が前回の実行のクエリ結果設定と一致する。
+ クエリで参照されているすべてのテーブルにアクセスできる。
+ 前回の結果が保存されている S3 ファイルの場所にアクセスできる。

これらの条件のいずれかが満たされない場合、Athena はキャッシュされた結果を使用せずにクエリを実行します。

## 考慮事項と制限事項
<a name="reusing-query-results-considerations-and-limitations"></a>

クエリ結果の再利用機能を使用する場合は、次の点に注意してください。
+ Athena は同じワークグループ内でのみクエリ結果を再利用します。
+ クエリ結果の再利用機能は、ワークグループの設定を優先します。クエリの結果の設定をオーバーライドすると、この機能は無効になります。
+ Amazon S3 で結果セットを生成するクエリのみがサポートされます。`SELECT` と `EXECUTE` 以外のステートメントはサポートされません。
+ AWS Glue で登録された Apache Hive テーブル、Apache Hudi テーブル、Apache Iceberg テーブル、および Linux Foundation Delta Lake テーブルがサポートされています。外部 Hive メタストアはサポートされていません。
+ フェデレーションカタログ、または外部の Hive メタストアを参照するクエリはサポートされていません。
+ Lake Formation の管理対象テーブルでは、クエリ結果の再利用はサポートされていません。
+ テーブルソースの Amazon S3 の場所が Lake Formation のデータの場所として登録されている場合、クエリ結果の再利用はサポートされません。
+ 行と列のアクセス許可を持つテーブルはサポートされていません。
+ きめ細かいアクセス制御 (列や行のフィルタリングなど) があるテーブルはサポートされていません。
+ サポートされていないテーブルを参照するクエリでは、クエリ結果の再利用は対象外です。
+ 以前に生成された出力ファイルを再利用するには、Athena では Amazon S3 の読み込みアクセス許可が必要です。
+ クエリ結果の再利用機能は、以前の結果の内容が変更されていないことを前提としています。Athena では以前の結果を使用する前にその結果の整合性をチェックしません。
+ 前回の実行でのクエリ結果が削除されているか、Amazon S3 の別の場所に移動されている場合、同じクエリを次に実行してもクエリ結果は再利用されません。
+ 古い結果が返される可能性があります。Athena では指定した最大再利用期間に達するまで、ソースデータの変更を確認しません。
+ 複数の結果を再利用できる場合、Athena は最新の結果を使用します。
+ `rand()` または `shuffle()` のような確定的ではない演算子または関数を使用するクエリは、キャッシュされた結果を使用しません。たとえば、`ORDER BY` を持たない `LIMIT` は非決定論的でキャッシュされませんが、`ORDER BY` を持たない `LIMIT` は決定論的でキャッシュされます。
+ JDBC でクエリ結果の再利用機能を使用するには、最低限必要なドライバーバージョンは 2.0.34.1000 です。ODBC に最低限必要なドライバー バージョンは 1.1.19.1002 です。ドライバーのダウンロード情報については、「[ODBC および JDBC ドライバーを使用して Amazon Athena に接続する](athena-bi-tools-jdbc-odbc.md)」を参照してください。
+ 複数のデータカタログを使用するクエリでは、クエリ結果の再利用はサポートされません。
+  20 を超えるテーブルが含まれるクエリでは、クエリ結果の再利用はサポートされません。
+ サイズが 100 KB 未満のクエリ文字列の場合、コメントと空白の違いは無視され、`INNER JOIN` と `JOIN` は結果を再利用するために同等として扱われます。100 KB を超えるクエリ文字列は、結果を再利用するために完全に一致している必要があります。
+ クエリ結果は、指定の最大有効期間を超過した場合、または最大有効期間が指定されていない場合はデフォルトの 60 分を超過した場合に、期限切れと見なされます。クエリの結果を再利用できる最大期間は、分数、時間数、または日数で指定できます。指定可能な最大期間は、使用する時間単位に関係なく、同様に 7 日間です。
+ [マネージドクエリ結果](https://docs.aws.amazon.com/athena/latest/ug/managed-results.html)はサポートされていません。

## Athena コンソールでクエリ結果を再利用する方法
<a name="reusing-query-results-athena-console"></a>

この機能を使用するには、Athena クエリエディタの **[Reuse query results]** (クエリ結果を再利用) オプションを有効にします。

![\[Athena クエリエディタで、[Reuse query results] (クエリ結果の再利用) を有効にします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/reusing-query-results-1.png)


**クエリ結果の再利用機能を設定するには**

1. Athena クエリエディタの **[Reuse query results]** (クエリ結果を再利用) オプションで、**[up to 60 minutes ago]** (最大 60 分前まで) の横にある編集アイコンを選択します。

1. **[Edit reuse time]** (再利用時間の編集) ダイアログボックスの右側のボックスから、時間の単位 (分、時間、または日) を選択します。

1. 左側のボックスで、指定する時間の単位数を入力または選択します。入力できる最大時間は、選択した時間の単位に関係なく 7 日間分に相当します。  
![\[クエリ結果を再利用するための最大有効期間を設定します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/reusing-query-results-2.png)

1. **[確認]** を選択します。

   設定の変更を確認するバナーが表示され、**[Reuse query results]** (クエリ結果を再使用) オプションに新しい設定が表示されます。

# 完了したクエリの統計と実行の詳細を表示する
<a name="query-stats"></a>

クエリを実行した後、処理された入力データと出力データに関する統計を取得し、クエリの各フェーズに要した時間のグラフィック表現を表示し、実行の詳細をインタラクティブに調べることができます。

**完了したクエリのクエリ統計を表示するには**

1. Athena クエリエディタでクエリを実行した後、**[Query stats]** (クエリ統計) タブを選択します。  
![\[[Query stats] (クエリ統計) を選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-stats-1.png)

   **[Query stats]** (クエリの統計) タブには、次の情報が表示されます。
   + **[Data processed]** (処理されたデータ) – 処理された入力行とバイト数、および出力された行数とバイト数を表示します。
   + **[The Total runtime]** (合計実行時間) – クエリの実行に要した合計時間と、その時間のうち、キュー、計画、実行、およびサービス処理に費やされた時間のグラフィック表現を表示します。
**注記**  
Lake Formation で行レベルのフィルターがクエリに定義されている場合、ステージレベルの入出力行数とデータサイズの情報は表示されません。

1. クエリの実行方法に関する情報をインタラクティブに調べるには、**[Execution details]** (実行の詳細) を選択します。  
![\[[Execution details] (実行の詳細) を選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-stats-2.png)

   **[Execution details]** (実行の詳細) ページには、クエリの実行 ID と、クエリのゼロベースのステージのグラフが表示されます。ステージは、下から開始順に並べられます。各ステージのラベルは、ステージの実行に要した時間を示します。
**注記**  
クエリの合計実行時間と実行ステージ時間は、大きく異なることがよくあります。たとえば、合計実行時間が分単位になっているクエリが、ステージの実行時間を時間単位で表示する場合があります。ステージは、多数のタスク全体で並列実行される計算の論理ユニットであるため、ステージの実行時間は、そのタスクすべての実行時間を集約したものになります。このような相違はあるものの、ステージ実行時間は、クエリのどのステージが最も計算集約的かを示す相対的な指標として役立つ場合があります。  
![\[実行の詳細ページ。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-stats-3.png)

   グラフを操作するには、次のオプションを使用します。
   + ズームインまたはズームアウトするには、マウスでスクロールするか、拡大アイコンを使用します。
   + 画面に合わせてグラフを調整するには、**[Zoom to fit]** (ズームして合わせる) アイコンを選択します。
   + グラフを移動するには、マウスポインタをドラッグします。

1. ステージの詳細を表示するには、ステージを選択します。右側のステージ詳細ペインには、入力と出力の行数とバイト数、およびオペレーターツリーが表示されます。  
![\[ステージの詳細ペイン。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-stats-4.png)

1. ステージの詳細を全幅で表示するには、詳細ペインの右上にある拡大アイコンを選択します。

1. ステージの各部分に関する情報を取得するには、オペレーターツリーで 1 つ以上の項目を展開します。  
![\[オペレーターツリーが展開されました。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/query-stats-5.png)

実行の詳細については、「[Athena EXPLAIN ステートメントの結果を理解する](athena-explain-statement-understanding.md)」を参照してください。

## その他のリソース
<a name="query-stats-additional-resources"></a>

詳細については、以下のリソースを参照してください。

[SQL クエリの実行プランを表示する](query-plans.md)

[Athena での EXPLAIN および EXPLAIN ANALYZE の使用](athena-explain-statement.md)

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/7JUyTqglmNU/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/7JUyTqglmNU)


# ビューを使用する
<a name="views"></a>

Amazon Athena のビューは、物理的なテーブルではなく、論理的なテーブルです。ビューを定義するクエリは、1 つのクエリでビューが参照されるたびに実行されます。`SELECT` クエリからビューを作成でき、今後のクエリでこのビューを参照できます。

Athena では、Athena ビューと AWS Glue Data Catalog ビューという 2 種類のビューを使用できます。

## Athena ビューを使用すべき場合
<a name="when-to-use-views"></a>

Athena ビューを作成すると、次のようなことが可能になります: 
+ **データのサブセットをクエリする** – 例えば、元のテーブルの列のサブセットを含むビューを作成して、データのクエリを簡素化できます。
+ **テーブルを組み合わせる** – ビューを使用して、複数のテーブルを組み合わせて 1 つのクエリにすることができます。複数のテーブルを持ち、それらを `UNION ALL`と組み合わせる場合は、その式でビューを作成して、結合テーブルに対するクエリを簡素化できます。
+ **複雑さを非表示にする** – ビューを使用して、既存の基本クエリの複雑さを非表示にし、ユーザーが実行するクエリを簡素化します。基本クエリには、テーブル間の結合、列リストの表現や他の SQL 構文が含まれていることより、その理解とデバッグが困難なことがよくあります。複合型を解消して、クエリを単純化するビューを作成できます。
+ **クエリを最適化する** – 最適化されたクエリを作成するために、ビューを使用して最適化手法を実験できます。たとえば、`WHERE` 条件、`JOIN` 順序、あるいはベストパフォーマンスを示す他の表現の組み合わせを見つけた場合には、これらの句および表現でビューを作成することができます。こうして、アプリケーションはこのビューに対して比較的な単純なクエリを実行できます。後に、元のクエリを最適化するためのより良い方法を見つけた場合には、ビューを再作成するときに、すべてのアプリケーションは最適化された基本クエリを即時に採用します。
+ **基になる名前を非表示にする** – ビューを使用して基になるテーブル名と列名を非表示にし、名前が変更された場合のメンテナンスの問題を最小限に抑えることができます。名前が変更された場合は、単に新しい名前を使用してビューを再作成します。テーブルではなく、このビューを使用するクエリは、変更なしで実行を直接続けます。

  詳細については、「[Athena ビューを使用する](views-console.md)」を参照してください。

## AWS Glue Data Catalog ビューを使用すべき場合
<a name="when-to-use-views-gdc"></a>

Amazon Athena や Amazon Redshift などの AWS のサービス 全体で 1 つの共通ビューが必要な場合は AWS Glue Data Catalog ビューを使用します。データカタログビューでは、アクセス許可はビューをクエリするユーザーではなく、ビューを作成したユーザーによって定義されます。この権限の付与方法は、definer セマンティクスと呼ばれます。

以下のユースケースは、データカタログビューの使用例です。
+ **アクセスコントロールの強化** — ユーザーが必要とするアクセス許可のレベルに基づいてデータアクセスを制限するビューを作成します。例えば、データカタログビューを使用して、人事 (HR) 部門に属さない従業員が個人を特定できる情報を表示できないようにすることができます。
+ **完全なレコードを確保** — データカタログビューに特定のフィルターを適用することで、データカタログビューのデータレコードを常に完全な状態にすることができます。
+ **セキュリティの強化** — データカタログビューでビューを作成するには、ビューを作成するクエリ定義をそのまま維持する必要があります。これにより、データカタログビューは悪意のある行為者からの SQL コマンドの影響を受けにくくなります。
+ **基礎となるテーブルへのアクセスを防ぐ** — Definer セマンティクスにより、ユーザーは基礎となるテーブルを利用できるようにしなくてもビューにアクセスすることができます。ビューを定義したユーザーのみがテーブルにアクセスする必要があります。

データカタログビュー定義は AWS Glue Data Catalog に保存されます。つまり、AWS Lake Formation を使用して、リソース許可、列付与、またはタグベースのアクセスコントロールを通じてアクセスを許可できます。Lake Formation でのアクセス権の付与と取り消しについての詳細は、「AWS Lake Formation デベロッパーガイド」の「[Data Catalog リソースに対する許可の付与と取り消し](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)」を参照してください。

詳細については、「[Athena でデータカタログビューを使用する](views-glue.md)」を参照してください。

# Athena ビューを使用する
<a name="views-console"></a>

Athena ビューは、Athena コンソールで簡単に作成、更新、管理できます。

## ビューを作成する
<a name="creating-views"></a>

Athena コンソールでテンプレートを使用するか、既存のクエリを実行して、ビューを作成できます。

**テンプレートを使用してビューを作成するには**

1. Athena コンソールで、**[Tables and views]** (テーブルとビュー) の横にある **[Create]** (作成) を選択してから、**[Create view]** (ビューの作成) を選択します。  
![\[ビューの作成\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/create-view.png)

   このアクションにより、編集可能なビューテンプレートがクエリエディタに配置されます。

1. 要件に応じてビューテンプレートを編集します。ステートメントにビューの名前を入力するときは、ビュー名にアンダースコア `(_)` 以外の特殊文字を含めることはできません。「[データベース、テーブル、列に名前を付ける](tables-databases-columns-names.md)」を参照してください。ビューの名前に [クエリで予約キーワードをエスケープする](reserved-words.md) を使用しないようにします。

   ビューの作成の詳細については、「[CREATE VIEW および CREATE PROTECTED MULTI DIALECT VIEW](create-view.md)」および「[Athena ビューの例](views-examples.md)」を参照してください。

1. **[Run]** (実行) をクリックしてビューを作成します。Athena コンソールのビューのリストにビューが表示されます。

**既存のクエリからビューを作成するには**

1. Athena クエリエディタを使用して、既存のクエリを実行します。

1. クエリエディタウィンドウで、**[Create]** (作成) を選択してから、**[View from query]** (クエリから表示する) を選択します。  
![\[[Create] (作成)、[View from query] (クエリから表示する) を選択します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/create-view-from-query.png)

1. **[Create View]** (ビューの作成) ダイアログボックスにビュー名を入力し、**[Create]** (作成) を選択します。ビュー名にはアンダースコア `(_)` 以外の特殊文字は使用できません。「[データベース、テーブル、列に名前を付ける](tables-databases-columns-names.md)」を参照してください。ビューの名前に [クエリで予約キーワードをエスケープする](reserved-words.md) を使用しないようにします。

   Athena はコンソール内のビューのリストにビューを追加し、クエリエディタのビューの `CREATE VIEW` ステートメントを表示します。

**注意事項**
+ テーブルの基になるテーブルを削除してからそのビューの実行を試みると、Athena がエラーメッセージを表示します。
+ ネストされたビューを作成することができます。これは、既存のビューの上にあるビューです。Athena は、それ自体を参照する再帰的なビューの実行を妨げます。

# Athena ビューの例
<a name="views-examples"></a>

ビュークエリの構文を表示するには、[SHOW CREATE VIEW](show-create-view.md) を使用します。

**Example 例 1**  
次の 2 つのテーブルを考えてみます。2 つの列 (`employees` と `id`) がある `name` テーブルと 2 つの列 (`salaries` と `id`) がある `salary` テーブルです。  
この例では、`name_salary` という名前のビューを `SELECT` テーブル および `employees` テーブルから給料にマッピングされた ID のリストを取得する `salaries` クエリとして作成します。  

```
CREATE VIEW name_salary AS
SELECT
 employees.name, 
 salaries.salary 
FROM employees, salaries 
WHERE employees.id = salaries.id
```

**Example 例 2**  
次の例では、`view1` という名前のビューを作成して、複合型のクエリ構文を非表示にします。  
このビューは 2 つのテーブル (`table1` および `table2`) の上部で実行され、各テーブルは異なる `SELECT` クエリです。このビューは、`table1` からの列を選択し、結果を `table2` に結合します。この結合は、両方のテーブルにある `a` 列に基づいています。  

```
CREATE VIEW view1 AS
WITH
  table1 AS (
         SELECT a, 
         MAX(b) AS the_max 
         FROM x 
         GROUP BY a
         ),
  table2 AS (
         SELECT a, 
         AVG(d) AS the_avg 
         FROM y 
         GROUP BY a)
SELECT table1.a, table1.the_max, table2.the_avg
FROM table1
JOIN table2 
ON table1.a = table2.a;
```

フェデレーティッドビューの詳細については、「[フェデレーテッドビューをクエリする](running-federated-queries.md#running-federated-queries-federated-views)」を参照してください。

# Athena ビューを管理する
<a name="views-managing"></a>

Athena コンソールでは、以下を実行することができます。
+ 左側のペインで、テーブルがリストされているすべてのビューを見つける。
+ ビューをフィルタリングする。
+ ビューをプレビューしてそのプロパティを表示し、編集または削除する。

**ビューのアクションを表示するには**

ビューは、既に作成してある場合にのみコンソールに表示されます。

1. Athena コンソールで **[Views]** (ビュー) を選択し、ビューを選択して展開し、ビュー内の列を表示します。

1. ビューの横にある 3 つの縦のドットを選択して、ビューのアクションのリストを表示します。  
![\[ビューのアクションメニュー。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/view-options.png)

1. アクションを選択して、ビューのプレビュー、クエリエディタへのビュー名の挿入、ビューの削除、ビューのプロパティの表示、またはクエリエディタでのビューの表示と編集を行います。

## Athena ビューでサポートされている DDL アクション
<a name="views-supported-actions"></a>

Athena は、ビューで次の管理アクションをサポートします。


| ステートメント | 説明 | 
| --- | --- | 
| [CREATE VIEW および CREATE PROTECTED MULTI DIALECT VIEW](create-view.md) |  指定する `SELECT` クエリから新しいビューを作成します。詳細については、「[ビューを作成する](views-console.md#creating-views)」を参照してください。 オプションの `OR REPLACE` 句は、既存のビューを更新して置き換えます。  | 
| [DESCRIBE VIEW](describe-view.md) |  名前が付けられたビューの列のリストを表示します。これにより、複合型のビューの属性を確認できます。  | 
| [DROP VIEW](drop-view.md) |  既存のビューを削除します。オプションの `IF EXISTS` 句は、ビューが存在しない場合に、エラーを抑制します。  | 
| [SHOW CREATE VIEW](show-create-view.md) |  指定するビューを作成する SQL ステートメントを表示します。  | 
| [SHOW VIEWS](show-views.md) |  指定するデータベース、あるいは、データベース名を省略する場合の現在のデータベースのビューのリスト。オプションの `LIKE` 句を正規表現で使用して、ビュー名のリストを制限します。コンソールの左ペインでビューのリストを表示することもできます。  | 
| [SHOW COLUMNS](show-columns.md) |  ビュー用のスキーマの列を一覧表示します。  | 

# Athena ビューに関する考慮事項と制限
<a name="considerations-limitations-views"></a>

Athena ビューには次の考慮事項と制限があります。

## 考慮事項
<a name="considerations-views"></a>

Athena でビューを作成して使用する場合は、次の考慮事項が適用されます。
+ Athena では、Athena コンソール、AWS Glue Data Catalog、または同じカタログに接続されている Amazon EMR クラスターで実行されている Presto で作成されたビューをプレビューして使用できます。
+ データカタログで Athena ビューを作成した場合、データカタログはビューをテーブルとして扱います。データカタログでテーブルレベルのきめ細かなアクセスコントロールを使用して、これらのビューへの[アクセスを制限](fine-grained-access-to-glue-resources.md)できます。
+  Athena は再帰的なビューの実行を妨げ、そのような場合にはエラーメッセージを表示します。再帰的なビューとは、Athena 自体を参照するビュークエリです。
+ Athena は、古いビューを検出するとエラーメッセージを表示します。以下のいずれかが発生すると、古いビューが報告されます。
  + このビューは、存在しないテーブルまたはデータベースを参照します。
  + スキーマまたはメタデータの変更は、参照されるテーブルで行われます。
  + 参照されるテーブルは削除され、異なるスキーマまたは設定で再度作成されます。
+ ネストされたビューのクエリが有効であり、テーブルおよびデータベースが存在する限り、ネストされたビューを作成して実行できます。

## 制限事項
<a name="limitations-views"></a>
+ Athena ビューの名前には、アンダースコア `(_)` 以外の特殊文字を使用できません。詳細については、「[データベース、テーブル、列に名前を付ける](tables-databases-columns-names.md)」を参照してください。
+ ビューの名前に予約キーワードを使用しないようにします。予約キーワードを使用している場合、ビューでのクエリでは予約キーワードを二重引用符で囲みます。「[クエリで予約キーワードをエスケープする](reserved-words.md)」を参照してください。
+ Athena で作成したビューを外部 Hive メタストア、UDF で使用することはできません。Hive で外部で作成したビューを使用する方法については、「[Hive ビューを使用する](hive-views.md)」を参照してください。
+ 地理空間関数ではビューを使用できません。
+ Amazon S3 のデータに対するアクセスコントロールを管理するためにビューを使用することはできません。ビューをクエリするには、Amazon S3 に保存されているデータにアクセスするためのアクセス許可が必要です。詳細については、「[Athena から Amazon S3 へのアクセスを制御する](s3-permissions.md)」を参照してください。
+ アカウント間でのビューのクエリは Athena エンジンバージョン 3 でサポートされていますが、クロスアカウント AWS Glue Data Catalogを含むビューを作成することはできません。クロスアカウントデータカタログへのアクセスについては、「[AWS Glue データカタログへのクロスアカウントアクセスを構成する](security-iam-cross-account-glue-catalog-access.md)」を参照してください。
+ Hive または Iceberg の非表示メタデータ列 `$bucket`、`$file_modified_time`、`$file_size`、および `$partition` は Athena のビューでサポートされていません。Athena の `$path`メタデータ列の使用方法については「[Amazon S3 内にあるソースデータのファイルの場所の取得](select.md#select-path)」を参照してください。

# Athena でデータカタログビューを使用する
<a name="views-glue"></a>

Amazon Athena でデータカタログビューを作成するには、特別な `CREATE VIEW` ステートメントが必要です。それらのデータカタログビューのクエリでは、従来の SQL `SELECT` 構文を使用します。データカタログビューは、*マルチダイアレクト*ビュー、または MDV とも呼ばれます。

## データカタログビューを作成する
<a name="views-glue-creating-a-data-catalog-view"></a>

Athena でデータカタログビューを作成するには、次の構文を使用します。

```
CREATE [ OR REPLACE ] PROTECTED MULTI DIALECT VIEW view_name 
SECURITY DEFINER 
[ SHOW VIEW JSON ]
AS athena-sql-statement
```

**注記**  
`SHOW VIEW JSON` オプションはデータカタログビューにのみ適用され、Athena ビューには適用されません。`SHOW VIEW JSON` オプションを使用すると、入力を検証する「ドライラン」が実行され、検証が成功すると、ビューを表す AWS Glue テーブルオブジェクトの JSON が返されます。実際のビューは作成されません。`SHOW VIEW JSON` オプションを指定しない場合、検証が完了し、ビューはデータカタログに通常どおり作成されます。

次の例は、`Definer` ロールのユーザーが `orders_by_date` データカタログビューを作成する方法を示しています。この例では、`Definer` ロールが `default` データベース内の `orders` テーブルに対するすべての `SELECT` 権限を持っていることを前提としています。

```
CREATE PROTECTED MULTI DIALECT VIEW orders_by_date 
SECURITY DEFINER 
AS 
SELECT orderdate, sum(totalprice) AS price 
FROM orders 
WHERE order_city = 'SEATTLE' 
GROUP BY orderdate
```

構文については、「[CREATE PROTECTED MULTI DIALECT VIEW](create-view.md#create-protected-multi-dialect-view)」を参照してください。

## データカタログビューをクエリする
<a name="views-glue-querying-a-data-catalog-view"></a>

ビューが作成されると、`Lake Formation` 管理者は、データカタログビューに対する `Invoker` 許可を `SELECT` プリンシパルに付与できます。その後、`Invoker` プリンシパルは、ビューが参照する基になるベーステーブルにアクセスしなくてもビューをクエリできます。以下は `Invoker` クエリの例です。

```
SELECT * from orders_by_date where price > 5000
```

## 考慮事項と制限事項
<a name="views-glue-limitations"></a>

次に示すデータカタログビューの制限の大部分は、Athena に固有のものです。他のサービスにも適用されるデータカタログビューの他の制限については、Lake Formation ドキュメントを参照してください。
+ データカタログビューは、他のビュー、データベースリソースリンク、テーブルリソースリンクのいずれも参照できません。
+ ビュー定義では最大 10 個のテーブルを参照できます。
+ Lake Formation のテーブルには `IAMAllowedPrincipals` データレイクのアクセス許可を付与してはいけません。付与されている場合は、Multi Dialect views may only reference tables without IAMAllowedPrincipals permissions というエラーが表示されます。
+ テーブルの Amazon S3 の場所は、Lake Formation データレイクの場所として登録する必要があります。テーブルがこのように登録されていない場合、Multi Dialect views may only reference Lake Formation managed tables というエラーが表示されます。Lake Formation で Amazon S3 の場所を登録する方法については、「*AWS Lake Formation Developer Guide*」の「[Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)」を参照してください。
+ AWS Glue [GetTables](https://docs.aws.amazon.com/glue/latest/webapi/API_GetTables.html) および [SearchTables](https://docs.aws.amazon.com/glue/latest/webapi/API_SearchTables.html) API コールは、`IsRegisteredWithLakeFormation` パラメータを更新しません。パラメータの正しい値を表示するには、AWS Glue [GetTable](https://docs.aws.amazon.com/glue/latest/webapi/API_GetTable.html) API を使用します。詳細については、「*AWS Lake Formation Developer Guide*」の「[GetTables and SearchTables APIs do not update the value for the IsRegisteredWithLakeFormation parameter](https://docs.aws.amazon.com/lake-formation/latest/dg/limitations.html#issue-GetTables-value)」を参照してください。
+ `DEFINER` プリンシパルは IAM ロールのみにできます。
+ `DEFINER` ロールには、基礎となるテーブルに対する完全な `SELECT` (付与可能な) 権限が必要です。
+ `UNPROTECTED` データカタログビューはサポートされていません。
+ ユーザー定義関数 (UDF) は、ビュー定義ではサポートされていません。
+ Athena 統合データソースはデータカタログビューでは使用できません。
+ Data Catalog ビューは外部 Hive メタストアではサポートされていません。
+ Athena は、古いビューを検出するとエラーメッセージを表示します。以下のいずれかが発生すると、古いビューが報告されます。
  + このビューは、存在しないテーブルまたはデータベースを参照します。
  + スキーマまたはメタデータの変更は、参照されるテーブルで行われます。
  + 参照されるテーブルは削除され、異なるスキーマまたは設定で再度作成されます。

## アクセス許可
<a name="views-glue-permissions"></a>

データカタログビューには `Lake Formation Admin`、`Definer`、`Invoker` の 3 つのロールが必要です。
+ **`Lake Formation Admin`** — すべてのLake Formation 権限を設定するためのアクセス権があります。
+ **`Definer`** — データカタログビューを作成します。`Definer` ロールには、ビュー定義が参照するすべての基礎となるテーブルに対して付与可能で完全な `SELECT` 権限が必要です。
+ **`Invoker`** — データカタログビューにクエリを実行したり、そのメタデータを確認したりできます。クエリの呼び出し元を表示するには、`invoker_principal()` DML 関数を使用できます。詳細については、「[invoker\$1principal()](functions-env3.md#functions-env3-invoker-principal)」を参照してください。

`Definer` ロールの信頼関係によって、AWS Glue と Lake Formation のサービスプリンシパルに対する `sts:AssumeRole` アクションを許可する必要があります。詳細については、「AWS Lake Formation デベロッパーガイド」の「[Prerequisites for creating views](https://docs.aws.amazon.com/lake-formation/latest/dg/working-with-views.html#views-prereqs)」を参照してください。

Athena にアクセスするための IAM アクセス許可も必要です。詳細については、「[AWSAmazon Athena の 管理ポリシー](security-iam-awsmanpol.md)」を参照してください。

# データカタログビューを管理する
<a name="views-glue-managing"></a>

DDL コマンドを使用して、データカタログビューを更新および管理できます。

## データカタログビューを更新する
<a name="views-glue-updating-a-data-catalog-view"></a>

`Lake Formation` 管理者または定義者は、`ALTER VIEW UPDATE DIALECT` 構文を使用してビュー定義を更新できます。次の例では、ビュー定義を変更して、`orders` テーブルではなく `returns` テーブルから列を選択します。

```
ALTER VIEW orders_by_date UPDATE DIALECT
AS
SELECT return_date, sum(totalprice) AS price
FROM returns
WHERE order_city = 'SEATTLE'
GROUP BY orderdate
```

## AWS Glue Data Catalog ビューでサポートされている DDL アクション
<a name="views-glue-supported-actions"></a>

Athena は、AWS Glue Data Catalog ビューで次のアクションをサポートします。


| ステートメント | 説明 | 
| --- | --- | 
| [ALTER VIEW DIALECT](alter-view-dialect.md) |  エンジンダイアレクトを追加するか、既存のエンジンダイアレクトを更新または削除して、データカタログビューを更新します。  | 
| [CREATE PROTECTED MULTI DIALECT VIEW](create-view.md#create-protected-multi-dialect-view) |  指定された `SELECT` クエリからデータカタログビューを作成します。詳細については、「[CREATE PROTECTED MULTI DIALECT VIEW](create-view.md#create-protected-multi-dialect-view)」を参照してください。 オプションの `OR REPLACE` 句は、既存のビューを更新して置き換えます。  | 
| [DESCRIBE VIEW](describe-view.md) |  名前が付けられたビューの列のリストを表示します。これにより、複合型のビューの属性を確認できます。  | 
| [DROP VIEW](drop-view.md) |  既存のビューを削除します。オプションの `IF EXISTS` 句は、ビューが存在しない場合に、エラーを抑制します。  | 
| [SHOW CREATE VIEW](show-create-view.md) |  指定するビューを作成する SQL ステートメントを表示します。  | 
| [SHOW VIEWS](show-views.md) |  指定するデータベース、あるいは、データベース名を省略する場合の現在のデータベースのビューのリスト。オプションの `LIKE` 句を正規表現で使用して、ビュー名のリストを制限します。コンソールの左ペインでビューのリストを表示することもできます。  | 
| [SHOW COLUMNS](show-columns.md) |  ビュー用のスキーマの列を一覧表示します。  | 

# 保存されたクエリを使用する
<a name="saved-queries"></a>

Athena クエリエディタで作成したクエリを保存、編集、実行、名前変更、および削除するには、Athena コンソールを使用することができます。

## 考慮事項と制限事項
<a name="saved-queries-considerations-and-limitations"></a>
+ 保存したクエリの名前、説明、およびクエリテキストを更新できます。
+ 自分のアカウントのクエリのみを更新できます。
+ クエリが属するワークグループまたはデータベースを変更することはできません。
+ Athena にクエリの変更履歴は保存されません。特定のバージョンのクエリを保持する必要がある場合は、別の名前で保存してください。

**注記**  
Amazon Athena リソースに Amazon SageMaker Unified Studio (プレビュー) 内でアクセスできるようになりました。これにより、組織のデータにアクセスし、最適なツールで対処することができます。保存されたクエリの Athena ワークグループから SageMaker Unified Studio プロジェクトへの移行、既存の Athena ワークグループでのプロジェクトの設定、IAM ロールの更新を介した必要なアクセス許可の維持が可能です。詳細については、「[Migrating Amazon Athena resources to Amazon SageMaker Unified Studio (プレビュー)](https://github.com/aws/Unified-Studio-for-Amazon-Sagemaker/tree/main/migration/athena)」を参照してください。

**Topics**
+ [考慮事項と制限事項](#saved-queries-considerations-and-limitations)
+ [名前を付けてクエリを保存する](saved-queries-name.md)
+ [保存されたクエリを実行する](saved-queries-run.md)
+ [保存されたクエリを編集する](saved-queries-edit.md)
+ [保存したクエリの名前を変更するか、または削除する](saved-queries-rename-or-delete.md)
+ [表示されていない保存済みクエリの名前を変更する](saved-queries-rename-not-displayed.md)
+ [表示されていない保存済みクエリを削除する](saved-queries-delete-not-displayed.md)
+ [Athena API を使用して保存されたクエリを更新する](saved-queries-update-with-api.md)

# 名前を付けてクエリを保存する
<a name="saved-queries-name"></a>

**クエリを保存して名前を付けるには**

1. Athena コンソールのクエリエディタで、クエリを入力するか実行します。

1. クエリエディタウィンドウの上にあるクエリのタブで 3 つの縦のドットを選択し、**[Save as]** (名前を付けて保存) を選択します。

1. **[Save query]** (クエリの保存) ダイアログボックスに、クエリの名前と任意で説明を入力します。展開できる **[Preview SQL query]** (SQL クエリのプレビュー) ウィンドウを使用して、クエリを保存する前にクエリの内容を確認します。

1. **[Save query]** (クエリの保存) を選択します。

   クエリエディタでは、クエリのタブに指定した名前が表示されます。

# 保存されたクエリを実行する
<a name="saved-queries-run"></a>

**保存されたクエリを実行するには**

1. Athena コンソールを開き、**[Saved queries]** (保存されたクエリ) タブを選択します。

1. **[Saved queries]** (保存されたクエリ) リストで、実行するクエリの ID を選択します。

   クエリエディタに、選択したクエリが表示されます。

1. **[Run]** (実行) を選択します。

# 保存されたクエリを編集する
<a name="saved-queries-edit"></a>

**保存されたクエリを編集するには**

1. Athena コンソールを開き、**[Saved queries]** (保存されたクエリ) タブを選択します。

1. **[Saved queries]** (保存されたクエリ) リストで、編集するクエリの ID を選択します。

1. クエリエディタでクエリを編集します。

1. 次のいずれかのステップを実行します。
   + クエリを実行するには、**[Run]** (実行) を選択します。
   + クエリを保存するには、クエリのタブで、3 つの縦のドットを選択し、**[Save]** (保存) を選択します。
   + 別の名前でクエリを保存するには、クエリのタブで、**[Save as]** (名前を付けて保存) を選択します。

# 保存したクエリの名前を変更するか、または削除する
<a name="saved-queries-rename-or-delete"></a>

**クエリエディタに既に表示されている保存済みのクエリの名前を変更またはクエリを削除するには**

1. クエリのタブにある 3 つの縦のドットを選択し、**[Rename]** (名前の変更) または **[Delete]** (削除) を選択します。

1. プロンプトに従って、クエリの名前を変更またはクエリを削除します。

# 表示されていない保存済みクエリの名前を変更する
<a name="saved-queries-rename-not-displayed"></a>

**クエリエディタに表示されていない保存済みクエリの名前を変更するには**

1. Athena コンソールを開き、**[Saved queries]** (保存されたクエリ) タブを選択します。

1. 名前を変更するクエリのチェックボックスを選択します。

1. [**名前の変更**] を選択します。

1. **[Rename query]** (クエリの名前変更) ダイアログボックスで、クエリ名とクエリの説明を編集します。展開できる **[Preview SQL query]** (SQL クエリのプレビュー) ウィンドウを使用して、クエリ名を変更する前にクエリの内容を確認します。

1. **[Rename query]** (クエリの名前変更) を選択します。

   名前を変更したクエリが **[Saved queries]** (保存されたクエリ) リストに表示されます。

# 表示されていない保存済みクエリを削除する
<a name="saved-queries-delete-not-displayed"></a>

**クエリエディタに表示されていない保存済みクエリを削除するには**

1. Athena コンソールを開き、**[Saved queries]** (保存されたクエリ) タブを選択します。

1. 削除するクエリのチェックボックスを 1 つ以上選択します。

1. **[削除]** を選択します。

1. 確認プロンプトで、**[Delete]** (削除) を選択します。

   1 つ以上のクエリが、**[Saved queries]** (保存されたクエリ) リストから削除されます。

# Athena API を使用して保存されたクエリを更新する
<a name="saved-queries-update-with-api"></a>

Athena API を使用して保存されたクエリを更新する方法の詳細については、Athena API リファレンスの [UpdateNamedQuery](https://docs.aws.amazon.com/athena/latest/APIReference/API_UpdateNamedQuery.html) アクションを参照してください。

# パラメータ化されたクエリを使用する
<a name="querying-with-prepared-statements"></a>

Athena のパラメータ化されたクエリを使用して、実行時に同じクエリを異なるパラメータ値で再実行し、SQL インジェクション攻撃を防ぐことができます。Athena では、パラメータ化されたクエリは、任意の DML クエリまたは SQL プリペアドステートメントの実行パラメータの形式をとることができます。
+ 実行パラメータを持つクエリは 1 つのステップで実行でき、ワークグループ固有ではありません。パラメータ化する値の DML クエリには、疑問符を付けます。クエリを実行するときは、実行パラメータ値を順番に宣言します。パラメータの宣言とパラメータへの値の割り当ては、同じクエリで、しかし分離された方法で行えます。プリペアドステートメントとは異なり、実行パラメータを含むクエリを送信するときにワークグループを選択できます。
+ プリペアドステートメントには、`PREPARE` と `EXECUTE` の 2 つの別個の SQL ステートメントが必要です。まず、`PREPARE` ステートメントでパラメータを定義します。その後、定義したパラメータの値を指定する `EXECUTE` ステートメントを実行します。プリペアドステートメントはワークグループ固有です。それらが属するワークグループのコンテキスト外では実行できません。

## 考慮事項と制限事項
<a name="querying-with-prepared-statements-considerations-and-limitations"></a>
+ パラメータ化されたクエリは、Athena エンジンバージョン 2 以降でサポートされています。Athena エンジンバージョンの詳細については、「[Athena エンジンのバージョニング](engine-versions.md)」を参照してください。
+ 現在、パラメータ化されたクエリは、`SELECT`、`INSERT INTO`、`CTAS`および `UNLOAD` ステートメントでのみサポートされています。
+ パラメータ化されたクエリでは、パラメータは位置パラメータであり、`?` で示されます。パラメータには、クエリ内の順序によって値が割り当てられます。名前が挙げられているパラメータはサポートされていません。
+ 現在、`?` パラメータは `WHERE` 句にのみ配置できます。`SELECT ? FROM table` のような構文はサポートされていません。
+ 疑問符パラメータを二重引用符または一重引用符で囲むことはできません (つまり、`'?'` および `"?"` は有効な構文ではありません)。
+ SQL 実行パラメータを文字列として扱うには、二重引用符ではなく一重引用符で囲む必要があります。
+ 必要に応じて、パラメータ化された条件に値を入力するときに `CAST` 関数を使用できます。たとえば、クエリでパラメータ化した `date` 型の列があり、データ `2014-07-05` をクエリする場合は、パラメータ値に `CAST('2014-07-05' AS DATE)` を入力すると結果が返されます。
+ 準備済みステートメントはワークグループ固有であり、準備済みステートメント名はワークグループ内で一意である必要があります。
+ 準備済みステートメントには IAM 許可が必要です。詳細については、「[準備済みステートメントへのアクセスを構成する](security-iam-athena-prepared-statements.md)」を参照してください。
+ Athena コンソールの実行パラメータを持つクエリでは、疑問符の数が最大 25 個に制限されます。

**Topics**
+ [考慮事項と制限事項](#querying-with-prepared-statements-considerations-and-limitations)
+ [実行パラメータを使用する](querying-with-prepared-statements-querying-using-execution-parameters.md)
+ [プリペアドステートメントを使用する](querying-with-prepared-statements-querying.md)
+ [その他のリソース](querying-with-prepared-statements-additional-resources.md)

# 実行パラメータを使用する
<a name="querying-with-prepared-statements-querying-using-execution-parameters"></a>

DML クエリで疑問符のプレースホルダーを使用すると、先にプリペアドステートメントを作成しなくても、パラメータ化されたクエリを作成できます。これらのクエリを実行するには、Athena コンソールを使用するか、AWS CLI または AWS SDK を使用して、`execution-parameters` 引数で変数を宣言します。

**Topics**
+ [Athena コンソールを使用する](querying-with-prepared-statements-running-queries-with-execution-parameters-in-the-athena-console.md)
+ [AWS CLI の使用](querying-with-prepared-statements-running-queries-with-execution-parameters-using-the-aws-cli.md)

# Athena コンソールで実行パラメータを使用してクエリを実行する
<a name="querying-with-prepared-statements-running-queries-with-execution-parameters-in-the-athena-console"></a>

Athena コンソールで実行パラメータ (疑問符) を含むパラメータ化されたクエリを実行すると、クエリで疑問符が出現する順序で値の入力を求められます。

**実行パラメータを持つクエリを実行するには**

1. 次の例のように、疑問符のプレースホルダーを含むクエリを Athena エディタで入力します。

   ```
   SELECT * FROM "my_database"."my_table"
   WHERE year = ? and month= ? and day= ?
   ```

1. **[Run]** (実行) を選択します。

1. **[Enter parameters]** (パラメータを入力) ダイアログボックスで、クエリ内の各疑問符について順番に値を入力します。  
![\[クエリパラメータの値を順番に入力する\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-with-prepared-statements-1.png)

1. パラメータの入力が終了したら、**[Run]** (実行) を選択します。エディタには、入力したパラメータ値のクエリ結果が表示されます。

この時点で、次のいずれかを実行できます。
+ 同じクエリに異なるパラメータ値を入力してから、**[Run again]** (再度実行) を選択します。
+ 入力したすべての値を一度にクリアするには、**[Clear]** (クリア) を選択します。
+ クエリを直接編集するには (たとえば、疑問符を追加または削除するには)、最初に **[Enter parameters]** (パラメータを入力) ダイアログボックスを閉じます。
+ パラメータ化されたクエリを後で使用するために保存するには、**[Save]** (保存) または **[Save as]** (名前を付けて保存) を選択し、クエリに名前を付けます。保存されるクエリの使用に関する詳細については、「[保存されたクエリを使用する](saved-queries.md)」を参照してください。

便宜のため、**[Enter parameters]** (パラメータを入力) ダイアログボックスでは、クエリエディタで同じタブを使用する限り、クエリ用に以前に入力した値が記憶されます。

# AWS CLI と実行パラメータを使用してクエリを実行する
<a name="querying-with-prepared-statements-running-queries-with-execution-parameters-using-the-aws-cli"></a>

AWS CLI で実行パラメータを使用してクエリを実行するには、`start-query-execution` コマンドを使用して、`query-string` 引数でパラメータ化されたクエリを指定します。その後、`execution-parameters` 引数で実行パラメータの値を指定します。以下に示しているのはこの手法の例です。

```
aws athena start-query-execution 
--query-string "SELECT * FROM table WHERE x = ? AND y = ?"
--query-execution-context "Database"="default" 
--result-configuration "OutputLocation"="s3://amzn-s3-demo-bucket;/..."
--execution-parameters "1" "2"
```

# プリペアドステートメントを使用する
<a name="querying-with-prepared-statements-querying"></a>

準備済みステートメントを使用して、異なるクエリパラメータを使用して同じクエリを繰り返し実行できます。準備済みステートメントにはパラメータプレースホルダが含まれており、それらの値は実行時に提供されます。

**注記**  
ワークグループ内の準備済みステートメントの最大数は 1,000 です。

**Topics**
+ [SQL 構文](querying-with-prepared-statements-sql-statements.md)
+ [Athena コンソールを使用する](querying-with-prepared-statements-executing-prepared-statements-without-the-using-clause-athena-console.md)
+ [AWS CLI の使用](querying-with-prepared-statements-cli-section.md)

# プリペアドステートメントの SQL 構文
<a name="querying-with-prepared-statements-sql-statements"></a>

Athena コンソールのクエリエディタでのパラメータ化されたクエリの実行には、`PREPARE`、`EXECUTE`、および `DEALLOCATE PREPARE` の SQL ステートメントを使用できます。

 
+ 通常はリテラル値を使用する箇所にパラメータを指定するには、`PREPARE` ステートメントで疑問符を使用します。
+ クエリの実行時にパラメータを値に置き換えるには、`EXECUTE` ステートメントで `USING` 句を使用します。
+ ワークグループ内の準備済みステートメントから準備済みステートメントを削除するには、`DEALLOCATE PREPARE` ステートメントを使用します。

以下のセクションでは、これらの各ステートメントをさらに詳しく説明します。

**Topics**
+ [PREPARE](querying-with-prepared-statements-prepare.md)
+ [EXECUTE](querying-with-prepared-statements-execute.md)
+ [DEALLOCATE PREPARE](querying-with-prepared-statements-deallocate-prepare.md)

# PREPARE
<a name="querying-with-prepared-statements-prepare"></a>

後ほど実行されるステートメントを準備します。準備済みステートメントは、ユーザー指定の名前で現在のワークグループに保存されます。ステートメントには、リテラルの代わりに、クエリの実行時に置き換えられるパラメータを含められます。値に置き換えられるパラメータは、疑問符で表されます。

## 構文
<a name="querying-with-prepared-statements-prepare-syntax"></a>

```
PREPARE statement_name FROM statement
```

以下の表は、これらのパラメータの説明です。


****  

| パラメータ | 説明 | 
| --- | --- | 
| statement\$1name | 準備されるステートメントの名前です。この名前は、ワークグループ内で一意である必要があります。 | 
| ステートメント | SELECT、CTAS、または INSERT INTO クエリです。 | 

## PREPARE の例
<a name="querying-with-prepared-statements-prepare-examples"></a>

以下の例では、`PREPARE` ステートメントを使用しています。疑問符は、クエリの実行時に `EXECUTE` ステートメントによって提供される値を表します。

```
PREPARE my_select1 FROM
SELECT * FROM nation
```

```
PREPARE my_select2 FROM
SELECT * FROM "my_database"."my_table" WHERE year = ?
```

```
PREPARE my_select3 FROM
SELECT order FROM orders WHERE productid = ? and quantity < ?
```

```
PREPARE my_insert FROM
INSERT INTO cities_usa (city, state)
SELECT city, state
FROM cities_world
WHERE country = ?
```

```
PREPARE my_unload FROM
UNLOAD (SELECT * FROM table1 WHERE productid < ?)
TO 's3://amzn-s3-demo-bucket/'
WITH (format='PARQUET')
```

# EXECUTE
<a name="querying-with-prepared-statements-execute"></a>

準備済みステートメントを実行します。`USING` 句にパラメータの値を指定しています。

## 構文
<a name="querying-with-prepared-statements-execute-syntax"></a>

```
EXECUTE statement_name [USING value1 [ ,value2, ... ] ]
```

*statement\$1name* は、準備済みステートメントの名前です。*value1* と *value2* は、ステートメント内のパラメータに指定される値です。

## EXECUTE の例
<a name="querying-with-prepared-statements-execute-examples"></a>

以下の例では、パラメータが含まれない `my_select1` 準備済みステートメントを実行しています。

```
EXECUTE my_select1
```

次の例では、単一のパラメータを含む `my_select2` 準備済みステートメントを実行しています。

```
EXECUTE my_select2 USING 2012
```

次の例では、2 つのパラメータを含む `my_select3` 準備済みステートメントを実行しています。

```
EXECUTE my_select3 USING 346078, 12
```

以下の例は、準備済みステートメント `my_insert` 内のパラメータに対する文字列値を提供します。

```
EXECUTE my_insert USING 'usa'
```

次の例では、準備済みステートメント `my_unload` 内の `productid` パラメータの数値を提供しています。

```
EXECUTE my_unload USING 12
```

# DEALLOCATE PREPARE
<a name="querying-with-prepared-statements-deallocate-prepare"></a>

現在のワークグループの準備済みステートメントのリストから、指定された名前を持つ準備済みステートメントを削除します。

## 構文
<a name="querying-with-prepared-statements-deallocate-prepare-syntax"></a>

```
DEALLOCATE PREPARE statement_name
```

*statement\$1name* は、削除される準備済みステートメントの名前です。

## 例
<a name="querying-with-prepared-statements-deallocate-prepare-examples"></a>

以下の例では、現在のワークグループから `my_select1` 準備済みステートメントを削除しています。

```
DEALLOCATE PREPARE my_select1
```

# Athena コンソールでインタラクティブなプリペアドステートメントを実行する
<a name="querying-with-prepared-statements-executing-prepared-statements-without-the-using-clause-athena-console"></a>

クエリエディタで構文 `EXECUTE` *prepared\$1statement* を使用して既存のプリペアドステートメントを実行すると、Athena は **[Enter parameters]** (パラメータを入力) ダイアログボックスを開き、`EXECUTE ... USING` ステートメントの `USING` 句に通常含まれる値を入力できるようにします。

****[Enter parameters]** (パラメータを入力) ダイアログボックスを使用してプリペアドステートメントを実行するには**

1. クエリエディタでは、構文 `EXECUTE prepared_statement USING` *value1*`,` *value2* ` ...` を使用する代わりに、構文 `EXECUTE` *prepared\$1statement* を使用します。

1. **[Run]** (実行) を選択します。**[Enter parameters]** (パラメータを入力) ダイアログボックスが表示されます。  
![\[Athena コンソールでプリペアドステートメントのパラメータ値を入力します。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-with-prepared-statements-2.png)

1. **[Execution parameters]** (実行パラメータ) ダイアログボックスに値を順番に入力します。クエリの元のテキストは表示されないため、各位置パラメータの意味を覚えておくか、プリペアドステートメントを参照できるようにしておく必要があります。

1. **[Run]** (実行) を選択します。

# AWS CLI を使用して、プリペアドステートメントを作成、実行、一覧表示する
<a name="querying-with-prepared-statements-cli-section"></a>

AWS CLI を使用して、プリペアドステートメントを作成、実行、一覧表示できます。

**Topics**
+ [作成](querying-with-prepared-statements-creating-prepared-statements-using-the-aws-cli.md)
+ [Execute](querying-with-prepared-statements-cli-executing-prepared-statements.md)
+ [リスト](querying-with-prepared-statements-listing.md)

# AWS CLI を使用して、プリペアドステートメントを作成する
<a name="querying-with-prepared-statements-creating-prepared-statements-using-the-aws-cli"></a>

AWS CLI を使用してプリペアドステートメントを作成するには、次のいずれかの `athena` コマンドを使用できます。
+ `create-prepared-statement` コマンドを使用して、実行パラメータを持つクエリステートメントを指定します。
+ `start-query-execution` コマンドを使用して、`PREPARE` 構文を使用するクエリ文字列を指定します。

## create-prepared-statement を使用する
<a name="querying-with-prepared-statements-cli-using-create-prepared-statement"></a>

次の例のように、`create-prepared-statement` コマンドにおいて、`query-statement` 引数でクエリテキストを定義します。

```
aws athena create-prepared-statement 
--statement-name PreparedStatement1 
--query-statement "SELECT * FROM table WHERE x = ?" 
--work-group athena-engine-v2
```

## start-query-execution および PREPARE 構文を使用する
<a name="querying-with-prepared-statements-cli-using-start-query-execution-and-the-prepare-syntax"></a>

`start-query-execution` コマンドを使用します。次の例のように、`PREPARE` ステートメントを `query-string` 引数に含めます。

```
aws athena start-query-execution 
--query-string "PREPARE PreparedStatement1 FROM SELECT * FROM table WHERE x = ?" 
--query-execution-context '{"Database": "default"}' 
--result-configuration '{"OutputLocation": "s3://amzn-s3-demo-bucket/..."}'
```

# AWS CLI を使用して、プリペアドステートメントを実行する
<a name="querying-with-prepared-statements-cli-executing-prepared-statements"></a>

AWS CLI を使用してプリペアドステートメントを実行するために、次のいずれかの方法を使用してパラメータの値を指定できます。
+ `execution-parameters` 引数を使用します。
+ `query-string` 引数で `EXECUTE ... USING` SQL 構文を使用します。

## 実行パラメータ引数を使用する
<a name="querying-with-prepared-statements-cli-using-the-execution-parameters-argument"></a>

このアプローチでは、`start-query-execution` コマンドを使用して、`query-string` 引数で既存のプリペアドステートメントの名前を指定します。その後、`execution-parameters` 引数で実行パラメータの値を指定します。次の例は、この方法を示しています。

```
aws athena start-query-execution 
--query-string "Execute PreparedStatement1" 
--query-execution-context "Database"="default" 
--result-configuration "OutputLocation"="s3://amzn-s3-demo-bucket/..."
--execution-parameters "1" "2"
```

## EXECUTE ... を使用する USING SQL 構文の使用
<a name="querying-with-prepared-statements-cli-using-the-execute-using-sql-syntax"></a>

`EXECUTE ... USING` 構文を使用して既存のプリペアドステートメントを実行するには、次の例のように、`start-query-execution` コマンドを使用して、プリペアドステートメントの名前とパラメータ値の両方を `query-string` 引数に含めます。

```
aws athena start-query-execution 
--query-string "EXECUTE PreparedStatement1 USING 1"
--query-execution-context '{"Database": "default"}' 
--result-configuration '{"OutputLocation": "s3://amzn-s3-demo-bucket/..."}'
```

# AWS CLI を使用して、プリペアドステートメントを一覧表示する
<a name="querying-with-prepared-statements-listing"></a>

特定のワークグループの準備済みステートメントをリスト表示するには、Athena の AWS CLI コマンド [list-prepared-statements](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/athena/list-prepared-statements.html) または Athena API のアクション [ListPreparedStatements](https://docs.aws.amazon.com/athena/latest/APIReference/API_ListPreparedStatements.html) を使用できます。`--work-group` パラメータは必須です。

```
aws athena list-prepared-statements --work-group primary
```

# その他のリソース
<a name="querying-with-prepared-statements-additional-resources"></a>

「AWS ビッグデータブログ」の次の関連記事を参照してください。
+ [Improve reusability and security using Amazon Athena parameterized queries](https://aws.amazon.com/blogs/big-data/improve-reusability-and-security-using-amazon-athena-parameterized-queries/) (Amazon Athena のパラメータ化されたクエリを使用して、再利用性とセキュリティを向上させる) 
+ [Use Amazon Athena parameterized queries to provide data as a service](https://aws.amazon.com/blogs/big-data/use-amazon-athena-parameterized-queries-to-provide-data-as-a-service/) (Amazon Athena のパラメータ化されたクエリを使用して、Data as a Service (DaaS) を提供する) 

# コストベースオプティマイザーを使用する
<a name="cost-based-optimizer"></a>

Athena SQL のコストベースオプティマイザー (CBO) 機能を使用してクエリを最適化できます。オプションとして、Athena がテーブルを収集するようにリクエストするか、AWS Glue にあるいずれかのテーブルの列レベル統計を収集するようにリクエストできます。クエリのすべてのテーブルに統計がある場合、Athena はその統計を使用して最もパフォーマンスが高いと判断した実行プランを作成します。クエリオプティマイザーは、統計モデルに基づいて代替プランを計算し、クエリを最も速く実行できると思われるプランを選択します。

AWS Glue テーブルの統計は収集されて AWS Glue Data Catalog に保存され、Athena で利用可能になるため、クエリプランニングおよび実行が改善されます。これらの統計は、Parquet、ORC、JSON、ION、CSV、XML などのファイルタイプの、null 値、最大値、最小値といった個別の値の個数などの列レベル統計です。Amazon Athena は、クエリ処理のできるだけ早い段階で最も制限の厳しいフィルタを適用することにより、これらの統計を使用してクエリを最適化します。このフィルタリングにより、メモリ使用量、ならびにクエリ結果を配信するために読み取る必要のあるレコード数が制限されます。

CBO と併せて、Athena はルールベースオプティマイザー (RBO) と呼ばれる機能を使用します。RBO は、クエリのパフォーマンス向上が期待されるルールを自動的に適用します。RBO の変換はクエリプランの簡略化を目的としているため、一般的にメリットがあります。ただし、RBO はコスト計算やプラン比較を行わないため、クエリが複雑になると RBO が最適なプランを作成することが難しくなります。

このため、Athena は RBO および CBO の両方を使用してクエリを最適化します。Athena はクエリ実行を改善する機会を特定した後、最適なプランを作成します。実行プラン内容の詳細については、「[SQL クエリの実行プランを表示する](query-plans.md)」を参照してください。CBO の仕組みについての詳しい内容については、AWS Big Data Blog 記事「[Speed up queries with the cost-based optimizer in Amazon Athena](https://aws.amazon.com/blogs/big-data/speed-up-queries-with-cost-based-optimizer-in-amazon-athena/)」を参照してください。

AWS Glue Catalog テーブルの統計を生成するには、Athena コンソール、AWS Glue コンソール、AWS Glue API を使用できます。Athena は AWS Glue Catalog と統合されているため、Amazon Athena からクエリを実行すると、対応するクエリパフォーマンスが自動的に向上します。

## 考慮事項と制限事項
<a name="cost-based-optimizer-considerations-and-limitations"></a>
+ **テーブルタイプ** — 現在、Athena の CBO 機能は AWS Glue Data Catalog に含まれている Hive テーブルおよび Iceberg テーブルのみをサポートしています。
+ **Athena for Spark** — CBO 機能は Athena for Spark では利用できません。
+ **料金** — 料金の詳細については、「[AWS Glue 料金表ページ](https://aws.amazon.com/glue/pricing)」を参照してください。

## Athena コンソールを使用してテーブル統計を生成する
<a name="cost-based-optimizer-generating-table-statistics-using-the-athena-console"></a>

このセクションでは、Athena コンソールを使用してテーブルまたは AWS Glue のテーブルに列レベル統計を生成する方法について説明します。AWS Glue を使用してテーブル統計を生成する詳細については、「AWS Glue デベロッパーガイド」の「[列統計の使用](https://docs.aws.amazon.com/glue/latest/dg/column-statistics.html)」を参照してください。

**Athena コンソールを使用してテーブルの統計を生成する方法**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. Athena クエリエディタの **[テーブル]** リストで、目的のテーブルにある縦 3 つの点を選択し、**[統計の生成]** を選択します。  
![\[Athena クエリエディタのテーブルのコンテキストメニュー。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cost-based-optimizer-1.png)

1. **[統計の生成]** ダイアログボックスで、**[すべての列]** を選択してテーブルにあるすべての列の統計を生成するか、**[選択した列]** を選択して特定の列を選択します。**[全ての列]** がデフォルト設定です。  
![\[[統計の生成] ダイアログボックス。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cost-based-optimizer-2.png)

1. **[AWS Glue サービスロール]** については、既存のサービスロールを作成または選択し、AWS Glue が統計を生成する許可を付与します。AWS Glue サービスロールには、テーブルのデータを含む Amazon S3 バケットへの [https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) 権限も必要です。  
![\[AWS Glue サービスロールの選択。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cost-based-optimizer-3.png)

1. **[統計の生成]** を選択します。**[*table\$1name* の統計を生成中]** 通知バナーがタスクステータスを表示します。  
![\[[統計生成中] 通知バナー。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cost-based-optimizer-4.png)

1. AWS Glue コンソールに詳細を表示するには、**[Glue で表示]** を選択します。

   AWS Glue コンソールで統計の表示に関する詳細については、「AWS Glue デベロッパーガイド」の「[列の統計の表示](https://docs.aws.amazon.com/glue/latest/dg/view-column-stats.html)」を参照してください。

1. 統計が生成された後、次の画像のように、統計を含むテーブルと列には括弧内に **[統計]** という単語が表示されます。  
![\[Athena クエリエディタに表示される統計アイコンを示すテーブル。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cost-based-optimizer-5.png)

クエリを実行すると、Athena は統計が生成されたテーブルおよび列に対し、コストベースの最適化が実行されるようになりました。

## テーブル統計を有効または無効にする
<a name="cost-based-optimizer-enabling-iceberg-table-statistics"></a>

前のセクションのステップに従って Iceberg テーブルのテーブル統計を生成すると、Glue テーブルプロパティ `use_iceberg_statistics` が AWS Glue Data Catalog の Iceberg テーブルに自動的に追加され、デフォルトで **[true]** に設定されます。このプロパティを削除するか **[false]** に設定すると、統計が Glue によって生成された場合でも、CBO はクエリの実行中にクエリプランを最適化しようとしたときに Iceberg テーブル統計を使用しません。テーブル統計を生成する方法の詳細については、「[Athena コンソールを使用してテーブル統計を生成する](#cost-based-optimizer-generating-table-statistics-using-the-athena-console)」を参照してください。

対照的に、Glue データカタログの Hive テーブルには、CBO のテーブル統計の使用を有効または無効にする同様のテーブルプロパティはありません。その結果、CBO は Hive テーブルのクエリプランを最適化しようとするときに、常に Glue によって生成されたテーブル統計を使用します。

## その他のリソース
<a name="cost-based-optimizer-additional-resources"></a>

その他の情報については、次のリソースを参照してください。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/zUHEXJdHUxs?si=rMAhJj3I5IlhN-1R/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/zUHEXJdHUxs?si=rMAhJj3I5IlhN-1R)


# S3 Express One Zone データをクエリする
<a name="querying-express-one-zone"></a>

Amazon S3 Express One Zone ストレージクラスは、1 桁のミリ秒単位の応答時間を実現する高性能の Amazon S3 ストレージクラスです。そのため、1 秒あたり数十万のリクエストを実行してデータに頻繁にアクセスするアプリケーションに役立ちます。

S3 Express One Zone は、同じアベイラビリティーゾーン内でデータをレプリケートして保存し、速度とコストを最適化します。これは、AWS リージョン 内の 3 つ以上の AWS アベイラビリティーゾーンにデータを自動的にレプリケートする Amazon S3 リージョンストレージクラスとは異なります。

詳細については、「Amazon S3 ユーザーガイド」の「[What is S3 Express One Zone?](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-one-zone.html)」を参照してください。

## 前提条件
<a name="querying-express-one-zone-prerequisites"></a>

開始する前に、以下の条件が満たされていることを確認してください。
+ **Athena エンジンバージョン 3** — Athena SQL で S3 Express One Zone を使用するには、Athena エンジンバージョン 3 を使用するようにワークグループを設定する必要があります。
+ **S3 Express One ゾーンのアクセス許可** — S3 Express One Zone が Amazon S3 オブジェクトに対して `GET`、`LIST`、`PUT` などのアクションを呼び出すと、ストレージクラスがユーザーに代わって `CreateSession` を呼び出します。このため、IAM ポリシーでは `s3express:CreateSession` アクションを許可する必要があります。これにより、Athena は対応する API オペレーションを呼び出すことができます。

## 考慮事項と制限事項
<a name="querying-express-one-zone-considerations-and-limitations"></a>

Athena で S3 Express 1 Zone をクエリする際は、以下の点を考慮してください。
+ S3 Express One Zone バケットは `SSE_S3` と `SSE-KMS` の暗号化をサポートします。Athena のクエリ結果は、ワークグループ設定で選択したクエリ結果を暗号化するオプションに関係なく、`SSE_S3` 暗号化を使用して書き込まれます。この制限には、`CREATE TABLE AS` (CTAS) や `INSERT INTO` ステートメントなど、Athena が S3 Express One Zone バケットにデータを書き込むすべてのシナリオが含まれます。
+ S3 Express One Zone のデータにテーブルを作成する場合、AWS Glue クローラーはサポートされていません。
+ `MSCK REPAIR TABLE` ステートメントはサポートされていません。回避方法として、[ALTER TABLE ADD PARTITION](alter-table-add-partition.md) を使用します。
+ S3 Express One Zone では、Apache Iceberg のテーブルを変更するための DDL ステートメント (つまり `ALTER TABLE` ステートメント) はサポートされていません。
+ Lake Formation は S3 Express One Zone バケットではサポートされていません。
+ 次のファイルおよびテーブル形式はサポートされていないか、サポートが制限されています。リストにないが、Athena でサポートされているフォーマット (Parquet、ORC、JSON など) であれば、S3 Express One Zone ストレージでの使用もサポートされています。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-express-one-zone.html)

## はじめに
<a name="querying-express-one-zone-getting-started"></a>

Athena を使用すると、S3 Express One Zone のデータを簡単にクエリすることができます。使用を開始するには、以下の手順を実行します。

**Athena SQL を使用して S3 Express One Zone のデータをクエリするには**

1. データを S3 Express One Zone のストレージに移行します。詳細については、「Amazon S3 ユーザーガイド」の「[オブジェクトのストレージクラスを設定](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html#sc-howtoset)」を参照してください。

1. Athena の [CREATE TABLE](create-table.md) ステートメントを使用して AWS Glue Data Catalog でデータをカタログ化します。Athena でのテーブルの作成に関する詳細については、「[Athena でテーブルを作成する](creating-tables.md)」と [CREATE TABLE](create-table.md) ステートメントを参照してください。

1. (オプション) Amazon S3 ディレクトリバケットを使用するように Athena ワークグループのクエリ結果の場所を設定します。Amazon S3 ディレクトリバケットは一般的なバケットよりもパフォーマンスが高く、一貫した 1 桁ミリ秒のレイテンシーを必要とするワークロードまたはパフォーマンス重視のアプリケーション向けに設計されています。詳細については、「Amazon S3 ユーザーガイド」の「[Directory buckets overview](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html)」を参照してください。

# 復元された Amazon Glacier オブジェクトをクエリする
<a name="querying-glacier"></a>

Amazon Athena を使用して、Amazon Glacier Flexible Retrieval (以前の Glacier) と Amazon Glacier Deep Archive [Amazon S3 ストレージクラス](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html#sc-glacier)から復元されたオブジェクトをクエリできます。この機能はテーブルごとに有効にする必要があります。クエリを実行する前にテーブルでこの機能を有効にしない場合、Athena はクエリ実行中にテーブルの Amazon Glacier Flexible Retrieval オブジェクトと Amazon Glacier Deep Archive オブジェクトをすべてスキップします。

## 考慮事項と制約事項
<a name="querying-glacier-considerations-and-limitations"></a>
+  復元された Amazon Glacier オブジェクトのクエリは、Athena エンジンバージョン 3 でのみサポートされています。
+  この機能は Apache Hive テーブルでのみサポートされています。
+  Athena はオブジェクトを復元しないため、データをクエリする前にオブジェクトを復元する必要があります。

## 復元されたオブジェクトを使用するようにテーブルを設定する
<a name="querying-glacier-configuring-a-table-to-use-restored-objects"></a>

 復元されたオブジェクトをクエリに含めるように Athena テーブルを設定するには、`read_restored_glacier_objects` テーブルプロパティを `true` に設定する必要があります。これを行うには、Athena クエリエディタまたは AWS Glue コンソールを使用できます。また、[AWS Glue CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glue/update-table.html)、[AWS Glue API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-tables.html#aws-glue-api-catalog-tables-UpdateTable)、または [AWS Glue SDK](https://docs.aws.amazon.com/glue/latest/dg/sdk-general-information-section.html) も使用できます。

### Athena クエリエディタを使用する
<a name="querying-glacier-using-the-athena-query-editor"></a>

 Athena では、次の例のように、[ALTER TABLE SET TBLPROPERTIES](alter-table-set-tblproperties.md) コマンドを使用してテーブルプロパティを設定できます。

```
ALTER TABLE table_name SET TBLPROPERTIES ('read_restored_glacier_objects' = 'true')
```

### AWS Glue コンソールを使用する
<a name="querying-glacier-using-the-aws-glue-console"></a>

 AWS Glue コンソールで、次の手順を実行して、`read_restored_glacier_objects` テーブルプロパティを追加します。

**AWS Glue コンソールでテーブルプロパティを設定するには**

1. AWS マネジメントコンソール にサインインし、AWS Glue コンソール ([https://console.aws.amazon.com/glue/](https://console.aws.amazon.com/glue/)) を開きます。

1. 次のいずれかを行います。
   + **[データカタログに移動]** を選択します。
   + ナビゲーションペインで、**[データカタログログテーブル]** を選択します。

1. **[テーブル]** ページのテーブルのリストで、編集するテーブルのリンクを選択します。

1. **[Actions]** (アクション)、**[Edit table]** (テーブルの編集) の順に選択します。

1. **[テーブルを編集]** ページの **[テーブルプロパティ]** セクションで、以下のキーと値のペアを追加します。
   + **[Key]** (キー)に、`read_restored_glacier_objects` を追加します。
   + **[Value]** (値) に「`true`」と入力します。

1. **[保存]** を選択します。

### AWS CLI の使用
<a name="querying-glacier-using-the-aws-cli"></a>

 AWS CLI では、テーブルを再定義するために AWS Glue [update-table](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glue/update-table.html) コマンドとその `--table-input` 引数を使用でき、そうすることで `read_restored_glacier_objects` プロパティが追加されます。`--table-input` 引数では、`Parameters` の構造を使用して `read_restored_glacier_objects` プロパティと `true` の値を指定します `--table-input` の引数にはスペースがあってはならず、二重引用符をエスケープするにはバックスラッシュを使用する必要があることに注意してください。以下の例では、*my\$1database* および *my\$1table* を独自のデータベース名とテーブル名に置き換えます。

```
aws glue update-table \
   --database-name my_database \
   --table-input={\"Name\":\"my_table\",\"Parameters\":{\"read_restored_glacier_objects\":\"true\"}}
```

**重要**  
AWS Glue `update-table` コマンドは上書きモードで動作します。これは、このコマンドが既存のテーブル定義を `table-input` パラメータ指定の新しい定義に置き換えることを意味します。このため、`read_restored_glacier_objects` プロパティを追加するときは、テーブルに含めるすべてのフィールドも `table-input` パラメータ内に指定するようにしてください。

# スキーマの更新を処理する
<a name="handling-schema-updates-chapter"></a>

このセクションでは、さまざまなデータ形式に対するスキーマ更新の処理に関するガイダンスを提供します。Athena はスキーマオンリード (schema-on-read) のクエリエンジンです。これは、Athena でテーブルを作成する場合、Athena がデータの読み込み時にスキーマを適用することを意味します。基盤となるデータに変更または書き直しが行われることはありません。

テーブルスキーマの変更が予想される場合は、ニーズに適したデータ形式で作成することを検討します。目的は、進化するスキーマに対して既存の Athena クエリを再利用し、パーティションがあるテーブルをクエリするときのスキーマの不一致エラーを回避することです。

これらの目的を達成するには、次のトピックの表に基づいてテーブルのデータ形式を選択してください。

**Topics**
+ [サポートされているスキーマ更新オペレーション (データ形式別)](#summary-of-updates)
+ [Apache ORC と Apache Parquet のインデックスアクセスを理解する](#index-access)
+ [スキーマを更新する](make-schema-updates.md)
+ [パーティションを使用してテーブルを更新する](updates-and-partitions.md)

## サポートされているスキーマ更新オペレーション (データ形式別)
<a name="summary-of-updates"></a>

以下の表は、データストレージ形式と、それらがサポートするスキーマ操作をまとめたものです。この表を使用して、スキーマがいずれは変更されるとしても、Athena クエリを引き続き使用できるようにする形式を選択するために役立ててください。

この表では、Parquet と ORC の列形式が、列へのデフォルトのアクセス方法が異なるものであることに注意してください。デフォルトで、Parquet は名前で列にアクセスし、ORC はインデックス (序数値) で列にアクセスします。このため、Athena はテーブルの作成時に定義される SerDe プロパティを提供して、列へのデフォルトのアクセス方法を切り替えます。これによって、スキーマの進化における柔軟性が大きく向上します。

Parquet では、`parquet.column.index.access` プロパティを `true` に設定することができます。これは、列の序数を使用するように列へのアクセス方法を設定します。このプロパティを `false` に設定すると、列へのアクセス方法が列名を使用するように変更されます。同様に、ORC では `orc.column.index.access` プロパティを使用して列へのアクセス方法を制御します。詳細については、「[Apache ORC と Apache Parquet のインデックスアクセスを理解する](#index-access)」を参照してください。

CSV と TSV を使用すると、列の並べ替えやテーブルの先頭に列を追加する以外のすべてのスキーマ操作を実行できます。例えば、スキーマの変更で列の名前を変更するだけで、列の名前を削除する必要がない場合は、CSV または TSV でテーブルを作成することができます。列を削除する必要がある場合は、CSV または TSV を使用せず、その他のサポートされている形式のいずれか (できれば、Parquet または ORC などの列形式) を使用します。


**Athena におけるスキーマ更新とデータ形式**  

| 予想されるスキーマ更新のタイプ | 概要 | CSV (ヘッダー有りまたはヘッダーなし) および TSV | JSON | AVRO | PARQUET: 名前で読み込む (デフォルト) | PARQUET: インデックスで読み込む | ORC: インデックスで読み込む (デフォルト) | ORC: 名前で読み込む | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
|  [列の名前変更](updates-renaming-columns.md) | データを CSV および TSV に保存するか、ORC および Parquet でインデックスに読み込んだ場合に保存します。 | Y | N | N | N  | Y | Y | N | 
|  [テーブルの先頭または中間に列を追加する](updates-add-columns-beginning-middle-of-table.md) | データを JSON、AVRO に保存するか、Parquet および ORC で名前に読み込んだ場合に保存します。CSV や TSV を使用しないでください。 | N | Y | Y | Y | N | N | Y | 
|  [テーブルの末尾に列を追加する](updates-add-columns-end-of-table.md) | CSV または TSV、JSON、AVRO、ORC、または Parquet 形式でデータを保存します。 | Y | Y | Y | Y | Y | Y | Y | 
| [列の削除](updates-removing-columns.md) |  データを JSON、AVRO に保存するか、Parquet および ORC で名前に読み込んだ場合に保存します。CSV や TSV を使用しないでください。 | N | Y | Y | Y | N | N | Y | 
| [列の順序変更](updates-reordering-columns.md) | データを AVRO、JSON に保存するか、ORC および Parquet で名前に読み込んだ場合に保存します。 | N | Y | Y | Y | N | N | Y | 
| [列のデータ型の変更](updates-changing-column-type.md) | 任意の形式でデータを保存します。ただし、Athena でクエリをテストして、データ型に互換性があることを確認するようにしてください。Parquet および ORC のデータ型を変更した場合は、パーティションされたテーブルでのみ機能します。 | Y | Y | Y | Y | Y | Y | はい | 

## Apache ORC と Apache Parquet のインデックスアクセスを理解する
<a name="index-access"></a>

PARQUET および ORC は、インデックス引または名前で読み込み可能な列データストレージ形式です。これらの形式のいずれかでデータを保存すると、スキーマですべてのオペレーションを実行し、スキーマの不一致エラーを生じることなく Athena でクエリを実行できるようになります。
+ Athena は、`SERDEPROPERTIES ( 'orc.column.index.access'='true')` で定義されているように、*デフォルトでインデックスによる ORC* の読み込みを行います。詳細については、「[ORC: インデックスで読み込む](#orc-read-by-index)」を参照してください。
+ Athena は、`SERDEPROPERTIES ( 'parquet.column.index.access'='false')` で定義されているとおり、*デフォルトで名前による Parquet* の読み込みを行います。詳細については、「[Parquet: 名前で読み込む](#parquet-read-by-name)」を参照してください。

これらはデフォルトであるため、これらの SerDe プロパティを `CREATE TABLE` クエリで使用するのはオプションで、暗黙的に使用されます。これらを使用すると、、他のオペレーションを防ぎながら、スキーマの更新オペレーションを実行することができます。これらのオペレーションを有効にするには、別の `CREATE TABLE` クエリを実行し、SerDe の設定を変更します。

**注記**  
SerDe のプロパティは、各パーティションに自動的に伝播*されません*。各パーティションに SerDe プロパティを設定するには、`ALTER TABLE ADD PARTITION` ステートメントを使用します。このプロセスを自動化するには、`ALTER TABLE ADD PARTITION` ステートメントを実行するスクリプトを記述します。

以下のセクションで、これらのケースについて詳しく説明します。

### ORC: インデックスで読み込む
<a name="orc-read-by-index"></a>

ORC 内のテーブルは、*デフォルトでインデックスで読み取られます*。これは、次の構文で定義されます。

```
WITH SERDEPROPERTIES ( 
  'orc.column.index.access'='true')
```

*インデックスで読み込むと*、列の名前を変更できます。ただし、列の削除やテーブルの中間での追加ができなくなります。

ORC を名前で読み込み、テーブルの中間に列を追加したり、ORC の列を削除したりするには、`orc.column.index.access` ステートメントで、SerDe プロパティ `false` を `CREATE TABLE` に設定します。この設定では、列の名前を変更する機能が失われます。

**注記**  
Athena エンジンバージョン 2 では、ORC テーブルが名前で読み込むように設定されている場合、Athena では ORC ファイル内のすべての列の名前を小文字にする必要があります。Apache Spark は ORC ファイルを生成するときにフィールド名を小文字にしないため、生成されたデータを Athena で読み込むことができない可能性があります。この問題を回避するためには、列の名前を小文字に変更するか、Athena エンジンバージョン 3 を使用します。

次の例は、ORC を変更して名前で読み込む方法を示しています。

```
CREATE EXTERNAL TABLE orders_orc_read_by_name (
   `o_comment` string,
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderpriority` string, 
   `o_orderstatus` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_orderdate` string
) 
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
WITH SERDEPROPERTIES ( 
  'orc.column.index.access'='false') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/orders_orc/';
```

### Parquet: 名前で読み込む
<a name="parquet-read-by-name"></a>

*Parquet のテーブルはデフォルトで名前で読み取られます*。これは、次の構文で定義されます。

```
WITH SERDEPROPERTIES ( 
  'parquet.column.index.access'='false')
```

*名前で読み込む*と、テーブルの中間に列を追加したり、列を削除したりできます。ただし、列の名前を変更することができなくなります。

Parquet にインデックスで読み取らせて列の名前を変更できるようにするには、 `parquet.column.index.access` SerDe プロパティを `true` に設定してテーブルを作成する必要があります。

# スキーマを更新する
<a name="make-schema-updates"></a>

このトピックでは、実際にデータを変更せずに `CREATE TABLE` ステートメントのスキーマに加えられるいくつかの変更について説明します。スキーマを更新するには、`ALTER TABLE` コマンドを使用できる場合もあれば、既存のテーブルを実際に変更しない場合もあります。代わりに、元の `CREATE TABLE` テートメントで使用したスキーマを変更する新しい名前のテーブルを作成します。

期待されるスキーマの進化方法に応じて、Athena クエリの使用を継続するために互換性のあるデータ形式を選択します。

CSV および Parquet の 2 つの形式で存在する `orders` テーブルからの注文情報を読み取るアプリケーションを考えます。

以下の例では、Parquet でテーブルを作成します。

```
CREATE EXTERNAL TABLE orders_parquet (
   `orderkey` int, 
   `orderstatus` string, 
   `totalprice` double, 
   `orderdate` string, 
   `orderpriority` string, 
   `clerk` string, 
   `shippriority` int
) STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_ parquet/';
```

以下の例では、CSV で同じテーブルを作成します。

```
CREATE EXTERNAL TABLE orders_csv (
   `orderkey` int, 
   `orderstatus` string, 
   `totalprice` double, 
   `orderdate` string, 
   `orderpriority` string, 
   `clerk` string, 
   `shippriority` int
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://amzn-s3-demo-bucket/orders_csv/';
```

次のトピックでは、これらのテーブルの更新が Athena クエリにどのように影響するかを示します。

**Topics**
+ [テーブルの先頭または中間に列を追加する](updates-add-columns-beginning-middle-of-table.md)
+ [テーブルの末尾に列を追加する](updates-add-columns-end-of-table.md)
+ [列の削除](updates-removing-columns.md)
+ [列の名前変更](updates-renaming-columns.md)
+ [列の順序変更](updates-reordering-columns.md)
+ [列のデータ型を変更する](updates-changing-column-type.md)

# テーブルの先頭または中間に列を追加する
<a name="updates-add-columns-beginning-middle-of-table"></a>

列の追加は最も頻繁なスキーマの変更の 1 つです。たとえば、新しいデータでテーブルをエンリッチ化するために、新しい列を追加することがあります。または、既存の列のソースが変更された場合に新しい列を追加し、この列の以前のバージョンを保持してそれに依存するアプリケーションを調整することもあります。

テーブルの先頭または中間に列を追加し、既存のテーブルに対してクエリを実行するには、SerDe プロパティが名前で読み取るように設定されている場合は、AVRO、JSON、および Parquet と ORC を使用します。詳細については、「[Apache ORC と Apache Parquet のインデックスアクセスを理解する](handling-schema-updates-chapter.md#index-access)」を参照してください。

これらの形式は順序に依存するため、CSV および TSV のテーブルの先頭または中間に列を追加しないでください。このような場合に列を追加すると、パーティションのスキーマが変更されたときにスキーマの不一致エラーが発生します。

 次の例では、JSON データに基づいてテーブルの中央に `o_comment` 列を追加する新しいテーブルを作成します。

```
CREATE EXTERNAL TABLE orders_json_column_addition (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_comment` string, 
   `o_totalprice` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/orders_json/';
```

# テーブルの末尾に列を追加する
<a name="updates-add-columns-end-of-table"></a>

Parquet、ORC、Avro、JSON、CSV、および TSV などの Athena がサポートする形式のいずれかでテーブルを作成する場合は、`ALTER TABLE ADD COLUMNS` ステートメントを使用して、既存の列の後、かつパーティション列の前の位置に列を追加できます。

次の例では、パーティション `comment` 列の前の `orders_parquet` テーブルの末尾に列を追加します。

```
ALTER TABLE orders_parquet ADD COLUMNS (comment string)
```

**注記**  
`ALTER TABLE ADD COLUMNS` を実行した後で Athena クエリエディタに新しいテーブル列を表示するには、エディタのテーブルリストを手動で更新してから、テーブルをもう一度展開します。

# 列の削除
<a name="updates-removing-columns"></a>

列に含まれるデータがなくなった場合、あるいは列に含まれているデータへのアクセスを制限する場合に、これらの列を削除する必要があることがあります。
+ 名前で読み込まれている場合、JSON、Avro、および Parquet、ORC でテーブルから列を削除することができます。詳細については、「[Apache ORC と Apache Parquet のインデックスアクセスを理解する](handling-schema-updates-chapter.md#index-access)」を参照してください。
+ 既に Athena で作成したテーブルを保持する場合は、CSV および TSV のテーブルから列を削除することは推奨されません。列を削除するとスキーマが壊れ、削除された列がない状態でテーブルを再作成しなければならなくなります。

この例では、Parquet のテーブルから ``totalprice`` 列を削除して、クエリを実行します。Athena では、デフォルトで Parquet の読み取りが名前で行われます。名前での読み取りを指定する SERDEPROPERTIES 設定が省略されているのはこのためです。スキーマを変更しても、次のクエリは成功することに注意してください。

```
CREATE EXTERNAL TABLE orders_parquet_column_removed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

# 列の名前変更
<a name="updates-renaming-columns"></a>

綴りを修正する、列名をより分かりやすくする、または列の順序変更を回避するために、テーブルで列の名前変更が必要となる場合があります。

データを CSV および TSV に保存する場合は列の名前を変更できます。また、インデックスで読み取るように設定されている場合は、Parquet および ORC に保存できます。詳細については、「[Apache ORC と Apache Parquet のインデックスアクセスを理解する](handling-schema-updates-chapter.md#index-access)」を参照してください。

Athena は CSV と TSV のデータをスキーマの列順に読み取り、それらを同じ順序で返します。Athena は、列にデータをマップするために列名を使用しません。Athena クエリを破損することなく CSV または TSV で列名を変更できるのはこのためです。

列名を変更する戦略の 1 つは、同じ基盤データに基づく新しいテーブルを、新しい列名を使用して作成することです。以下の例は、`orders_parquet_column_renamed` という名前の新しい `orders_parquet` テーブルを作成します。この例は、列 ``o_totalprice`` の名前を ``o_total_price`` に変更してから、Athena でクエリを実行します。

```
CREATE EXTERNAL TABLE orders_parquet_column_renamed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_total_price` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

Parquet テーブルの場合、次のクエリは実行されますが、列がインデックスではなく名前でアクセスされているため (Parquet のデフォルト)、名前が変更された列にはデータが表示されません。

```
SELECT * 
FROM orders_parquet_column_renamed;
```

CSV のテーブルでのクエリも類似しています。

```
CREATE EXTERNAL TABLE orders_csv_column_renamed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_total_price` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://amzn-s3-demo-bucket/orders_csv/';
```

CSV テーブルの場合、次のクエリを実行すると、名前が変更された列を含むすべての列でデータが表示されます。

```
SELECT * 
FROM orders_csv_column_renamed;
```

# 列の順序変更
<a name="updates-reordering-columns"></a>

デフォルトで名前で読み取る JSON や Parquet など、名前で読み取る形式のデータを含むテーブルの列の順序を変更できます。必要に応じて、ORC を名前で読み取ることもできます。詳細については、「[Apache ORC と Apache Parquet のインデックスアクセスを理解する](handling-schema-updates-chapter.md#index-access)」を参照してください。

次の例では、列の順序が違う新しいテーブルを作成します。

```
CREATE EXTERNAL TABLE orders_parquet_columns_reordered (
   `o_comment` string,
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderpriority` string, 
   `o_orderstatus` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_orderdate` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

# 列のデータ型を変更する
<a name="updates-changing-column-type"></a>

既存のタイプでは必要な量の情報を保持できなくなった場合は、別の列タイプを使用することをお勧めします。例えば、ID 列の値が `INT` データ型のサイズを超えているため、その `BIGINT` データ型を使用する必要があります。

## 考慮事項
<a name="updates-changing-column-type-considerations"></a>

列に別のデータ型を使用するときは、以下の点を考慮してください。
+ ほとんどの場合、列のデータ型を直接変更することはできません。代わりに、Athena テーブルを再作成し、新しいデータ型で列を定義します。
+ 一部のデータ型のみを他のデータ型として読み取ることができます。扱えるデータ型については、このセクションの表を参照してください。
+ Parquet および ORC のデータでは、テーブルがパーティション分割されていない場合、列に異なるデータ型を使用することはできません。
+ Parquet および ORC のパーティション分割されたテーブルでは、パーティションの列タイプが別のパーティションの列タイプと異なる場合があり、可能な場合は、Athena が望ましいタイプに `CAST` します。詳細については、「[パーティションがあるテーブルについて、スキーマ不一致エラーを回避する](updates-and-partitions.md#partitions-dealing-with-schema-mismatch-errors)」を参照してください。
+ [LazySimpleSerDE](lazy-simple-serde.md) のみを使用して作成されたテーブルでは、`ALTER TABLE REPLACE COLUMNS` ステートメントを使用して既存の列を別のデータ型に置き換えることができますが、保持したい既存の列もすべてステートメントに再定義する必要があります。これを行わないと、削除されます。詳細については、「[ALTER TABLE REPLACE COLUMNS](alter-table-replace-columns.md)」を参照してください。
+ Apache Iceberg テーブルの場合のみ、[ALTER TABLE CHANGE COLUMN](querying-iceberg-alter-table-change-column.md) ステートメントを使用して列のデータ型を変更できます。 `ALTER TABLE REPLACE COLUMNS` は Iceberg テーブルではサポートされていません。詳細については、「[Iceberg テーブルスキーマを進化させる](querying-iceberg-evolving-table-schema.md)」を参照してください。

**重要**  
データ型の変換を実行する前に、クエリをテストして検証することを強くお勧めします。Athena がターゲットのデータ型を使用できない場合、`CREATE TABLE` クエリは失敗する可能性があります。

## 互換性のあるデータ型を使用する
<a name="updates-changing-column-type-use-compatible-data-types"></a>

可能な場合は常に、互換性のあるデータ型を使用します。次の表は、他のデータ型として扱うことができるデータ型の一覧です。


| 元のデータ型 | 使用可能なターゲットデータ型 | 
| --- | --- | 
| STRING | BYTE, TINYINT, SMALLINT, INT, BIGINT | 
| BYTE | TINYINT, SMALLINT, INT, BIGINT | 
| TINYINT | SMALLINT, INT, BIGINT | 
| SMALLINT | INT, BIGINT | 
| INT | BIGINT | 
| FLOAT | DOUBLE | 

次の例では、元の `orders_json` テーブルの `CREATE TABLE` ステートメントを使用して、`orders_json_bigint` という新しいテーブルを作成します。新しいテーブルでは、``o_shippriority`` 列のデータ型として `INT` の代わりに `BIGINT` が使用されます。

```
CREATE EXTERNAL TABLE orders_json_bigint (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_totalprice` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` BIGINT
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/orders_json';
```

次のクエリは、元の `SELECT` クエリと同様に、データ型が変更される前に正常に実行されます。

```
Select * from orders_json 
LIMIT 10;
```

# パーティションを使用してテーブルを更新する
<a name="updates-and-partitions"></a>

Athena では、テーブルとそのパーティションが同じデータ形式を使用する必要がありますが、スキーマは異なる場合があります。新しいパーティションを作成するとき、このパーティションは通常テーブルのスキーマを継承します。時間の経過とともに、このスキーマが変わり始める場合があります。その理由には次のようなものがあります。
+ テーブルのスキーマの場合、パーティションのスキーマはテーブルのスキーマと同期するために更新されません。
+ AWS Glue クローラでは、異なるスキーマのパーティションからデータを検出することができます。これは、AWS Glue を使って Athena でテーブルを作成する場合、クローラの処理が終了した後で、テーブルのスキーマとそのパーティションのスキーマが異なる場合があることを意味します。
+ AWS API を使用して、直接パーティションを追加した場合。

Athena は、テーブルが以下の制約を満たす場合に、パーティションがあるテーブルを正常に処理します。これらの制約が満たされない場合、Athena は「HIVE\$1PARTITION\$1SCHEMA\$1MISMATCH」エラーを発行します。
+ 各パーティションのスキーマがテーブルのスキーマと互換性があること。
+ テーブルのデータ形式が実行する更新のタイプを許可すること (追加、削除、列の順序変更あるいは列のデータ型の変更)。

  たとえば、CSV および TSV 形式では列の名前変更、新しい列のテーブル末尾への追加および型に互換性がある場合の列のデータ型の変更のみを行うことができ、列を削除することはできません。その他の形式では、列の追加あるいは削除、型に互換性がある場合の列のデータ型の別への変更ができます。詳細については、「[概要: Athena における更新とデータ形式](handling-schema-updates-chapter.md#summary-of-updates)」を参照してください。

## パーティションがあるテーブルについて、スキーマ不一致エラーを回避する
<a name="partitions-dealing-with-schema-mismatch-errors"></a>

Athena は、クエリの実行開始時に、各列のデータ型にテーブルとパーティション間での互換性があることをチェックすることによってテーブルのスキーマを検証します。
+ Parquet および ORC のデータストレージタイプの場合、Athena は列名に依存し、列名ベースのスキーマ検証のためにそれらを使用します。これにより、Parquet および ORC のパーティションがあるテーブルの `HIVE_PARTITION_SCHEMA_MISMATCH` エラーが解消されます。(ORC では、名前でインデックスにアクセスするように SerDe プロパティが設定されている (`orc.column.index.access=FALSE`) 場合にこれが機能します。Parquet はデフォルトで、名前によるインデックスの読み取りを行います)。
+ CSV、JSON、および Avro の場合、Athena はインデックスベースのスキーマ検証を使用します。これは、スキーマの不一致エラーが発生した場合、スキーマの不一致の原因となっているパーティションをドロップして作成し直し、Athena で失敗なくクエリを実行できるようにする必要があることを意味します。

 Athena は、テーブルのスキーマとパーティションのスキーマを比較します。Athena の AWS Glue クローラで CSV、JSON、および AVRO でテーブルを作成した場合、クローラの処理が終了すると、テーブルのスキーマとそのパーティションは異なる場合があります。テーブルのスキーマとパーティションのスキーマ間に不一致がある場合、Athena でのクエリは、「'crawler\$1test.click\$1avro' is declared as type 'string', but partition 'partition\$10=2017-01-17' declared column 'col68' as type 'double'."」に似たスキーマ検証エラーが原因で失敗します。

このようなエラーを回避する一般的な対処法は、エラーの原因となるパーティションを削除して、再作成することです。詳細については、「[ALTER TABLE DROP PARTITION](alter-table-drop-partition.md)」および「[ALTER TABLE ADD PARTITION](alter-table-add-partition.md)」を参照してください。

# クエリ配列
<a name="querying-arrays"></a>

Amazon Athena では、配列の作成、連結、異なるデータ型への変換を実行して、その後それらをフィルタリング、フラット化、および並び替えることができます。

**Topics**
+ [配列を作成する](creating-arrays.md)
+ [文字列と配列を連結する](concatenating-strings-and-arrays.md)
+ [配列のデータ型を変換する](converting-array-data-types.md)
+ [配列の長さを検索する](finding-lengths.md)
+ [配列要素にアクセスする](accessing-array-elements.md)
+ [ネストされた配列をフラット化する](flattening-arrays.md)
+ [サブクエリから配列を作成する](creating-arrays-from-subqueries.md)
+ [配列をフィルタリングする](filtering-arrays.md)
+ [ソート配列](sorting-arrays.md)
+ [配列での集計関数を使用する](arrays-and-aggregation.md)
+ [配列を文字列に変換する](converting-arrays-to-strings.md)
+ [配列を使用してマップを作成する](arrays-create-maps.md)
+ [複合型を含む配列をクエリする](rows-and-structs.md)

# 配列を作成する
<a name="creating-arrays"></a>

Athena で配列リテラルを構築するには、角括弧 `[ ]` が後に続く `ARRAY` キーワードを使用し、カンマで区切られた配列要素を含めます。

## 例
<a name="examples"></a>

次のクエリでは、4 つの要素を持つ 1 つの配列を作成します。

```
SELECT ARRAY [1,2,3,4] AS items
```

返される結果は次のとおりです。

```
+-----------+
| items     |
+-----------+
| [1,2,3,4] |
+-----------+
```

次のクエリでは 2 つの配列を作成します。

```
SELECT ARRAY[ ARRAY[1,2], ARRAY[3,4] ] AS items
```

返される結果は次のとおりです。

```
+--------------------+
| items              |
+--------------------+
| [[1, 2], [3, 4]]   |
+--------------------+
```

互換性のある複数のタイプ間で選択した列から配列を作成するには、次の例に示すように、クエリを使用します。

```
WITH
dataset AS (
  SELECT 1 AS x, 2 AS y, 3 AS z
)
SELECT ARRAY [x,y,z] AS items FROM dataset
```

このクエリは以下を返します。

```
+-----------+
| items     |
+-----------+
| [1,2,3]   |
+-----------+
```

次の例では、2 つの配列を選択し、ウェルカムメッセージとして返します。

```
WITH
dataset AS (
  SELECT
    ARRAY ['hello', 'amazon', 'athena'] AS words,
    ARRAY ['hi', 'alexa'] AS alexa
)
SELECT ARRAY[words, alexa] AS welcome_msg
FROM dataset
```

このクエリは以下を返します。

```
+----------------------------------------+
| welcome_msg                            |
+----------------------------------------+
| [[hello, amazon, athena], [hi, alexa]] |
+----------------------------------------+
```

キーと値のペアの配列を作成するには、次の例に示すように、`MAP` 演算子を使用してキーの配列に続けて値の配列を使用します。

```
SELECT ARRAY[
   MAP(ARRAY['first', 'last', 'age'],ARRAY['Bob', 'Smith', '40']),
   MAP(ARRAY['first', 'last', 'age'],ARRAY['Jane', 'Doe', '30']),
   MAP(ARRAY['first', 'last', 'age'],ARRAY['Billy', 'Smith', '8'])
] AS people
```

このクエリは以下を返します。

```
+-----------------------------------------------------------------------------------------------------+
| people                                                                                              |
+-----------------------------------------------------------------------------------------------------+
| [{last=Smith, first=Bob, age=40}, {last=Doe, first=Jane, age=30}, {last=Smith, first=Billy, age=8}] |
+-----------------------------------------------------------------------------------------------------+
```

# 文字列と配列を連結する
<a name="concatenating-strings-and-arrays"></a>

文字列の連結と配列の連結では、同様の手法が使用されます。

## 文字列を連結する
<a name="concatenating-strings"></a>

2 つの文字列を連結するには、以下の例にあるように、二重パイプ `||` 演算子を使用することができます。

```
SELECT 'This' || ' is' || ' a' || ' test.' AS Concatenated_String
```

このクエリは以下を返します。


****  

| \$1 | Concatenated\$1String | 
| --- | --- | 
| 1 |  `This is a test.`  | 

`concat()` 関数を使って同じ結果を得ることが可能です。

```
SELECT concat('This', ' is', ' a', ' test.') AS Concatenated_String
```

このクエリは以下を返します。


****  

| \$1 | Concatenated\$1String | 
| --- | --- | 
| 1 |  `This is a test.`  | 

`concat_ws()` 関数を使用して、最初の引数で指定された区切り文字で文字列を連結できます。

```
SELECT concat_ws(' ', 'This', 'is', 'a', 'test.') as Concatenated_String
```

このクエリは以下を返します。


****  

| \$1 | Concatenated\$1String | 
| --- | --- | 
| 1 |  `This is a test.`  | 

文字列データ型の 2 つの列をドットで連結するには、二重引用符を使用して 2 つの列を参照し、そのドットをハードコーディングされた文字列として一重引用符で囲みます。列が文字列データ型ではない場合、`CAST("column_name" as VARCHAR)` を使用して最初に列をキャストできます。

```
SELECT "col1" || '.' || "col2" as Concatenated_String
FROM my_table
```

このクエリは以下を返します。


****  

| \$1 | Concatenated\$1String | 
| --- | --- | 
| 1 |  `col1_string_value.col2_string_value`  | 

## 配列を連結する
<a name="concatenating-arrays"></a>

同じテクニックを使用して配列を連結できます。

複数の配列を連結するには、二重パイプ `||` 演算子を使用します。

```
SELECT ARRAY [4,5] || ARRAY[ ARRAY[1,2], ARRAY[3,4] ] AS items
```

このクエリは以下を返します。


****  

| \$1 | 項目 | 
| --- | --- | 
| 1 |  `[[4, 5], [1, 2], [3, 4]]`  | 

複数の配列を単一の配列に統合するには、二重パイプ演算子、または `concat()` 関数を使用します。

```
WITH
dataset AS (
  SELECT
    ARRAY ['Hello', 'Amazon', 'Athena'] AS words,
    ARRAY ['Hi', 'Alexa'] AS alexa
)
SELECT concat(words, alexa) AS welcome_msg
FROM dataset
```

このクエリは以下を返します。


****  

| \$1 | welcome\$1msg | 
| --- | --- | 
| 1 |  `[Hello, Amazon, Athena, Hi, Alexa]`  | 

`concat()` とその他の文字列関数の詳細については、Trino ドキュメントの「[String Functions and Operators](https://trino.io/docs/current/functions/string.html)」(文字列関数と演算子) を参照してください。

# 配列のデータ型を変換する
<a name="converting-array-data-types"></a>

配列内のデータをサポートされているデータ型に変換するには、`CAST` 演算子を `CAST(value AS type)` のように使用します。Athena は、すべてのネイティブ Presto データ型をサポートします。

```
SELECT
   ARRAY [CAST(4 AS VARCHAR), CAST(5 AS VARCHAR)]
AS items
```

このクエリは以下を返します。

```
+-------+
| items |
+-------+
| [4,5] |
+-------+
```

次の例では、キーと値のペアの要素を持つ配列を 2 つ作成し、この 2 つの配列を JSON に変換して連結します。

```
SELECT
   ARRAY[CAST(MAP(ARRAY['a1', 'a2', 'a3'], ARRAY[1, 2, 3]) AS JSON)] ||
   ARRAY[CAST(MAP(ARRAY['b1', 'b2', 'b3'], ARRAY[4, 5, 6]) AS JSON)]
AS items
```

このクエリは以下を返します。

```
+--------------------------------------------------+
| items                                            |
+--------------------------------------------------+
| [{"a1":1,"a2":2,"a3":3}, {"b1":4,"b2":5,"b3":6}] |
+--------------------------------------------------+
```

# 配列の長さを検索する
<a name="finding-lengths"></a>

`cardinality` 関数は、次の例に示すように、配列の長さを返します。

```
SELECT cardinality(ARRAY[1,2,3,4]) AS item_count
```

このクエリは以下を返します。

```
+------------+
| item_count |
+------------+
| 4          |
+------------+
```

# 配列要素にアクセスする
<a name="accessing-array-elements"></a>

配列要素にアクセスするには、`[]` 演算子を使用します。次の例のように、1 に最初の要素、2 に 2 番目の要素を指定し、以下同様に指定します。

```
WITH dataset AS (
SELECT
   ARRAY[CAST(MAP(ARRAY['a1', 'a2', 'a3'], ARRAY[1, 2, 3]) AS JSON)] ||
   ARRAY[CAST(MAP(ARRAY['b1', 'b2', 'b3'], ARRAY[4, 5, 6]) AS JSON)]
AS items )
SELECT items[1] AS item FROM dataset
```

このクエリは以下を返します。

```
+------------------------+
| item                   |
+------------------------+
| {"a1":1,"a2":2,"a3":3} |
+------------------------+
```

配列の特定の位置 (インデックス位置) にある要素にアクセスするには、`element_at()` 関数を使用して配列名とインデックス位置を指定します。
+ インデックスが 0 より大きい場合は、配列の先頭から末尾へカウントした位置の要素が`element_at()` から返されます。これは `[]` 演算子の動作と同じです。
+ インデックスが 0 より小さい場合は、配列の末尾から先頭へカウントした位置の要素が `element_at()` から返されます。

次のクエリでは、配列 `words` を作成し、この配列の最初の要素 `hello` を `first_word`、2 番目の要素 `amazon` (配列の末尾からカウント) を `middle_word`、3 番目の要素 `athena` を `last_word` として選択します。

```
WITH dataset AS (
  SELECT ARRAY ['hello', 'amazon', 'athena'] AS words
)
SELECT
  element_at(words, 1) AS first_word,
  element_at(words, -2) AS middle_word,
  element_at(words, cardinality(words)) AS last_word
FROM dataset
```

このクエリは以下を返します。

```
+----------------------------------------+
| first_word  | middle_word | last_word  |
+----------------------------------------+
| hello       | amazon      | athena     |
+----------------------------------------+
```

# ネストされた配列をフラット化する
<a name="flattening-arrays"></a>

ネストされた配列を使用する場合、必要に応じて、ネストされた配列の要素を単一の配列に展開したり、配列を複数の行に展開したりすることがあります。

## フラット化関数を使用する
<a name="flattening-arrays-flatten-function"></a>

ネストされた配列の要素を単一の値配列にフラット化するには、`flatten` 関数を使用します。次のクエリは、配列の要素ごとに行を返します。

```
SELECT flatten(ARRAY[ ARRAY[1,2], ARRAY[3,4] ]) AS items
```

このクエリは以下を返します。

```
+-----------+
| items     |
+-----------+
| [1,2,3,4] |
+-----------+
```

## CROSS JOIN と UNNEST を使用する
<a name="flattening-arrays-cross-join-and-unnest"></a>

配列を複数の行にフラット化するには、次の例に示すように、`CROSS JOIN` 演算子を `UNNEST` 演算子と組み合わせて使用します。

```
WITH dataset AS (
  SELECT
    'engineering' as department,
    ARRAY['Sharon', 'John', 'Bob', 'Sally'] as users
)
SELECT department, names FROM dataset
CROSS JOIN UNNEST(users) as t(names)
```

このクエリは以下を返します。

```
+----------------------+
| department  | names  |
+----------------------+
| engineering | Sharon |
+----------------------|
| engineering | John   |
+----------------------|
| engineering | Bob    |
+----------------------|
| engineering | Sally  |
+----------------------+
```

キーと値のペアの配列をフラット化するには、次の例に示すように、選択したキーを列に入れ替えます。

```
WITH
dataset AS (
  SELECT
    'engineering' as department,
     ARRAY[
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Bob', 'Smith', '40']),
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Jane', 'Doe', '30']),
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Billy', 'Smith', '8'])
     ] AS people
  )
SELECT names['first'] AS
 first_name,
 names['last'] AS last_name,
 department FROM dataset
CROSS JOIN UNNEST(people) AS t(names)
```

このクエリは以下を返します。

```
+--------------------------------------+
| first_name | last_name | department  |
+--------------------------------------+
| Bob        | Smith     | engineering |
| Jane       | Doe       | engineering |
| Billy      | Smith     | engineering |
+--------------------------------------+
```

従業員の一覧から、総合スコアが最も高い従業員を選択します。`UNNEST` は、デフォルトの結合演算子で暗黙的に指定されるため、`FROM` 句において先行 `CROSS JOIN` なしで使用できます。

```
WITH
dataset AS (
  SELECT ARRAY[
    CAST(ROW('Sally', 'engineering', ARRAY[1,2,3,4]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
    CAST(ROW('John', 'finance', ARRAY[7,8,9]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
    CAST(ROW('Amy', 'devops', ARRAY[12,13,14,15]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER)))
  ] AS users
),
users AS (
 SELECT person, score
 FROM
   dataset,
   UNNEST(dataset.users) AS t(person),
   UNNEST(person.scores) AS t(score)
)
SELECT person.name, person.department, SUM(score) AS total_score FROM users
GROUP BY (person.name, person.department)
ORDER BY (total_score) DESC
LIMIT 1
```

このクエリは以下を返します。

```
+---------------------------------+
| name | department | total_score |
+---------------------------------+
| Amy  | devops     | 54          |
+---------------------------------+
```

従業員の一覧から、個別のスコアが最も高い従業員を選択します。

```
WITH
dataset AS (
 SELECT ARRAY[
   CAST(ROW('Sally', 'engineering', ARRAY[1,2,3,4]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
   CAST(ROW('John', 'finance', ARRAY[7,8,9]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
   CAST(ROW('Amy', 'devops', ARRAY[12,13,14,15]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER)))
 ] AS users
),
users AS (
 SELECT person, score
 FROM
   dataset,
   UNNEST(dataset.users) AS t(person),
   UNNEST(person.scores) AS t(score)
)
SELECT person.name, score FROM users
ORDER BY (score) DESC
LIMIT 1
```

このクエリは以下を返します。

```
+--------------+
| name | score |
+--------------+
| Amy  | 15    |
+--------------+
```

### CROSS JOIN と UNNEST に関する考慮事項
<a name="flattening-arrays-cross-join-and-unnest-considerations"></a>

`UNNEST` がクエリ内の 1 つ以上の配列で使用され、配列の 1 つが `NULL` である場合、クエリは行を返しません。空の文字列の配列に `UNNEST` を使用すると、空の文字列が返されます。

例えば、次のクエリでは、2 番目の配列が Null であるため、クエリは行を返しません。

```
SELECT 
    col1, 
    col2 
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY []) AS t(col2)
```

次の例では、2 番目の配列が空の文字列を含むように変更されています。クエリは各行について、`col1` の値を返し、`col2` の値では空の文字列を返します。1 番目の配列の値を返すには、2 番目の配列の空の文字列が必要です。

```
SELECT 
    col1, 
    col2 
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY ['']) AS t(col2)
```

# サブクエリから配列を作成する
<a name="creating-arrays-from-subqueries"></a>

行のコレクションから配列を作成します。

```
WITH
dataset AS (
  SELECT ARRAY[1,2,3,4,5] AS items
)
SELECT array_agg(i) AS array_items
FROM dataset
CROSS JOIN UNNEST(items) AS t(i)
```

このクエリは以下を返します。

```
+-----------------+
| array_items     |
+-----------------+
| [1, 2, 3, 4, 5] |
+-----------------+
```

行のセットから一意の値の配列を作成するには、`distinct` キーワードを使用します。

```
WITH
dataset AS (
  SELECT ARRAY [1,2,2,3,3,4,5] AS items
)
SELECT array_agg(distinct i) AS array_items
FROM dataset
CROSS JOIN UNNEST(items) AS t(i)
```

このクエリは次の結果を返します。順序は保証されないことに注意してください。

```
+-----------------+
| array_items     |
+-----------------+
| [1, 2, 3, 4, 5] |
+-----------------+
```

`array_agg` 関数の使用方法の詳細については「Trino ドキュメント」の「[集計関数](https://trino.io/docs/current/functions/aggregate.html)」を参照してください。

# 配列をフィルタリングする
<a name="filtering-arrays"></a>

フィルタ条件に一致する行のコレクションから配列を作成します。

```
WITH
dataset AS (
  SELECT ARRAY[1,2,3,4,5] AS items
)
SELECT array_agg(i) AS array_items
FROM dataset
CROSS JOIN UNNEST(items) AS t(i)
WHERE i > 3
```

このクエリは以下を返します。

```
+-------------+
| array_items |
+-------------+
| [4, 5]      |
+-------------+
```

配列の各要素に特定の値 (2 など) が含まれているかどうかに基づいて配列をフィルタ処理します。次に例を示します。

```
WITH
dataset AS (
  SELECT ARRAY
  [
    ARRAY[1,2,3,4],
    ARRAY[5,6,7,8],
    ARRAY[9,0]
  ] AS items
)
SELECT i AS array_items FROM dataset
CROSS JOIN UNNEST(items) AS t(i)
WHERE contains(i, 2)
```

このクエリは以下を返します。

```
+--------------+
| array_items  |
+--------------+
| [1, 2, 3, 4] |
+--------------+
```

## `filter` 関数を使用する
<a name="filtering-arrays-filter-function"></a>

```
 filter(ARRAY [list_of_values], boolean_function)
```

`ARRAY` 式で `filter` 関数を使用して、*boolean\$1function* が true となっている *list\$1of\$1values* 内の項目のサブセットである新しい配列を作成できます。`filter` 関数は、*UNNEST* 関数を使用できない場合に役立ちます。

次の例では、配列 `[1,0,5,-1]` 内のゼロより大きい値をフィルタリングします。

```
SELECT filter(ARRAY [1,0,5,-1], x -> x>0)
```

**結果**  
`[1,5]`

次の例では、配列 `[-1, NULL, 10, NULL]` 内の null 以外の値をフィルタリングします。

```
SELECT filter(ARRAY [-1, NULL, 10, NULL], q -> q IS NOT NULL)
```

**結果**  
`[-1,10]`

# ソート配列
<a name="sorting-arrays"></a>

行のセットから、一意の値の並び替えられた配列を作成するには、以下の例にあるように、[array\$1sort](https://prestodb.io/docs/current/functions/array.html#array_sort) 関数を使用することができます。

```
WITH
dataset AS (
  SELECT ARRAY[3,1,2,5,2,3,6,3,4,5] AS items
)
SELECT array_sort(array_agg(distinct i)) AS array_items
FROM dataset
CROSS JOIN UNNEST(items) AS t(i)
```

このクエリは以下を返します。

```
+--------------------+
| array_items        |
+--------------------+
| [1, 2, 3, 4, 5, 6] |
+--------------------+
```

配列を複数の行に拡張する方法については、「[ネストされた配列をフラット化する](flattening-arrays.md)」(ネストされた配列を平坦化する) を参照してください。

# 配列での集計関数を使用する
<a name="arrays-and-aggregation"></a>
+ 配列内の値を加算するには、次の例のように `SUM` を使用します。
+ 配列内の複数の行を集計するには、`array_agg` を使用します。詳細については、[サブクエリから配列を作成する](creating-arrays-from-subqueries.md) を参照してください。

**注記**  
`ORDER BY` は、Athena エンジンバージョン 2 以降の集約関数でサポートされています。

```
WITH
dataset AS (
  SELECT ARRAY
  [
    ARRAY[1,2,3,4],
    ARRAY[5,6,7,8],
    ARRAY[9,0]
  ] AS items
),
item AS (
  SELECT i AS array_items
  FROM dataset, UNNEST(items) AS t(i)
)
SELECT array_items, sum(val) AS total
FROM item, UNNEST(array_items) AS t(val)
GROUP BY array_items;
```

最後の `SELECT` ステートメントでは、`sum()` と `UNNEST` を使用する代わりに、`reduce()` を使用して処理時間とデータ転送を短縮できます。次に例を示します。

```
WITH
dataset AS (
  SELECT ARRAY
  [
    ARRAY[1,2,3,4],
    ARRAY[5,6,7,8],
    ARRAY[9,0]
  ] AS items
),
item AS (
  SELECT i AS array_items
  FROM dataset, UNNEST(items) AS t(i)
)
SELECT array_items, reduce(array_items, 0 , (s, x) -> s + x, s -> s) AS total
FROM item;
```

いずれのクエリも次の結果を返します。返される結果の順序は保証されません。

```
+----------------------+
| array_items  | total |
+----------------------+
| [1, 2, 3, 4] | 10    |
| [5, 6, 7, 8] | 26    |
| [9, 0]       | 9     |
+----------------------+
```

# 配列を文字列に変換する
<a name="converting-arrays-to-strings"></a>

配列を 1 つの文字列に変換するには、`array_join` 関数を使用します。以下のスタンドアロン例は、`words` という名前のエイリアス化された配列を含む、`dataset` という名前のテーブルを作成します。クエリは、`words` の配列要素を結合するために `array_join` を使用し、それらをスペースで区切って、結果として得られた文字列を `welcome_msg` という名前のエイリアス化された列内に返します。

```
WITH
dataset AS (
  SELECT ARRAY ['hello', 'amazon', 'athena'] AS words
)
SELECT array_join(words, ' ') AS welcome_msg
FROM dataset
```

このクエリは以下を返します。

```
+---------------------+
| welcome_msg         |
+---------------------+
| hello amazon athena |
+---------------------+
```

# 配列を使用してマップを作成する
<a name="arrays-create-maps"></a>

マップは、Athena で利用できるデータ型で構成されるキー/値ペアです。マップを作成するには、`MAP` 演算子を使用して 2 つの配列を渡します。最初の配列は列 (キー) 名、2 つ目の配列は値です。配列のすべての値は、同じ型にする必要があります。マップの値配列のいずれかの要素を別の型にする必要がある場合は、後で変換できます。

## 例
<a name="examples"></a>

次の例では、データセットからユーザーを選択します。`MAP` 演算子を使用して 2 つの配列を渡します。最初の配列には、値として「first」、「last」、「age」などの列名が含まれています。2 番目の配列は、これらの各列の値として「Bob」、「Smith」、「35」などで構成されます。

```
WITH dataset AS (
  SELECT MAP(
    ARRAY['first', 'last', 'age'],
    ARRAY['Bob', 'Smith', '35']
  ) AS user
)
SELECT user FROM dataset
```

このクエリは以下を返します。

```
+---------------------------------+
| user                            |
+---------------------------------+
| {last=Smith, first=Bob, age=35} |
+---------------------------------+
```

`Map` 値を取得するには、次の例に示すように、フィールド名に続けて `[key_name]` を選択します。

```
WITH dataset AS (
 SELECT MAP(
   ARRAY['first', 'last', 'age'],
   ARRAY['Bob', 'Smith', '35']
 ) AS user
)
SELECT user['first'] AS first_name FROM dataset
```

このクエリは以下を返します。

```
+------------+
| first_name |
+------------+
| Bob        |
+------------+
```

# 複合型とネストされた構造を含む配列をクエリする
<a name="rows-and-structs"></a>

ソースデータには、複雑なデータ型とネスト構造を持つ配列が含まれている場合があります。このセクションの例は、Athena クエリを使用して要素のデータ型を変更し、配列内の要素を見つけて、キーワードを検索する方法を示しています。

**Topics**
+ [`ROW` を作成する](creating-row.md)
+ [`CAST` を使用して配列内のフィールド名を変更する](changing-row-arrays-with-cast.md)
+ [`.` 表記を使用して配列をフィルタリングする](filtering-with-dot.md)
+ [ネストされた値を持つ配列をフィルタリングする](filtering-nested-with-dot.md)
+ [`UNNEST` を使用して配列をフィルタリングする](filtering-with-unnest.md)
+ [`regexp_like` を使用して配列内でのキーワードを検索する](filtering-with-regexp.md)

# `ROW` を作成する
<a name="creating-row"></a>

**注記**  
このセクションの例では、使用するサンプルデータの作成手段として `ROW` を使用します。Athena 内のテーブルをクエリするときは、`ROW` データ型がデータソースから既に作成されているため、改めて作成する必要はありません。`CREATE_TABLE` を使用すると、Athena によって `STRUCT` が定義され、データが入力されて、データセット内の行ごとに `ROW` データ型が作成されます。基となる `ROW` データ型は、サポートされている SQL データ型の名前付きフィールドで構成されます。

```
WITH dataset AS (
 SELECT
   ROW('Bob', 38) AS users
 )
SELECT * FROM dataset
```

このクエリは以下を返します。

```
+-------------------------+
| users                   |
+-------------------------+
| {field0=Bob, field1=38} |
+-------------------------+
```

# `CAST` を使用して配列内のフィールド名を変更する
<a name="changing-row-arrays-with-cast"></a>

`ROW` 値が含まれている配列のフィールド名を変更するには、`CAST` 宣言を `ROW` できます。

```
WITH dataset AS (
  SELECT
    CAST(
      ROW('Bob', 38) AS ROW(name VARCHAR, age INTEGER)
    ) AS users
)
SELECT * FROM dataset
```

このクエリは以下を返します。

```
+--------------------+
| users              |
+--------------------+
| {NAME=Bob, AGE=38} |
+--------------------+
```

**注記**  
上の例では、`name` を `VARCHAR` として宣言しています。Presto での型に合わせるためです。この `STRUCT` を `CREATE TABLE` ステートメント内で宣言する場合は、`String` 型を使用します。Hive では、このデータ型を `String` として定義するためです。

# `.` 表記を使用して配列をフィルタリングする
<a name="filtering-with-dot"></a>

次の例では、ドット `accountId` 表記を使用して、`userIdentity` ログの AWS CloudTrail 列から `.` フィールドを選択します。詳細については、「[AWS CloudTrail ログのクエリ](cloudtrail-logs.md)」を参照してください。

```
SELECT
  CAST(useridentity.accountid AS bigint) as newid
FROM cloudtrail_logs
LIMIT 2;
```

このクエリは以下を返します。

```
+--------------+
| newid        |
+--------------+
| 112233445566 |
+--------------+
| 998877665544 |
+--------------+
```

値の配列にクエリを実行するには、次のクエリを発行します。

```
WITH dataset AS (
  SELECT ARRAY[
    CAST(ROW('Bob', 38) AS ROW(name VARCHAR, age INTEGER)),
    CAST(ROW('Alice', 35) AS ROW(name VARCHAR, age INTEGER)),
    CAST(ROW('Jane', 27) AS ROW(name VARCHAR, age INTEGER))
  ] AS users
)
SELECT * FROM dataset
```

次の結果が返されます。

```
+-----------------------------------------------------------------+
| users                                                           |
+-----------------------------------------------------------------+
| [{NAME=Bob, AGE=38}, {NAME=Alice, AGE=35}, {NAME=Jane, AGE=27}] |
+-----------------------------------------------------------------+
```

# ネストされた値を持つ配列をフィルタリングする
<a name="filtering-nested-with-dot"></a>

大きな配列にはネスト構造が含まれている場合があり、ネスト構造内の値をフィルタ処理または検索する必要があります。

ネストされた `BOOLEAN` 値を含む値配列のデータセットを定義するには、次のクエリを発行します。

```
WITH dataset AS (
  SELECT
    CAST(
      ROW('aws.amazon.com', ROW(true)) AS ROW(hostname VARCHAR, flaggedActivity ROW(isNew BOOLEAN))
    ) AS sites
)
SELECT * FROM dataset
```

次の結果が返されます。

```
+----------------------------------------------------------+
| sites                                                    |
+----------------------------------------------------------+
| {HOSTNAME=aws.amazon.com, FLAGGEDACTIVITY={ISNEW=true}}  |
+----------------------------------------------------------+
```

次に、この要素の `BOOLEAN` 値のフィルタ処理およびアクセスには、引き続きドット `.` 表記を使用します。

```
WITH dataset AS (
  SELECT
    CAST(
      ROW('aws.amazon.com', ROW(true)) AS ROW(hostname VARCHAR, flaggedActivity ROW(isNew BOOLEAN))
    ) AS sites
)
SELECT sites.hostname, sites.flaggedactivity.isnew
FROM dataset
```

このクエリは、ネストされたフィールドを選択し、次の結果を返します。

```
+------------------------+
| hostname       | isnew |
+------------------------+
| aws.amazon.com | true  |
+------------------------+
```

# `UNNEST` を使用して配列をフィルタリングする
<a name="filtering-with-unnest"></a>

ネスト構造を含む配列を、そのいずれかの子要素でフィルタ処理するには、`UNNEST` 演算子を使用してクエリを発行します。`UNNEST` の詳細については、「[ネスト配列のフラット化](flattening-arrays.md)」を参照してください。

例えば、このクエリは、データセット内のサイトのホスト名を見つけます。

```
WITH dataset AS (
  SELECT ARRAY[
    CAST(
      ROW('aws.amazon.com', ROW(true)) AS ROW(hostname VARCHAR, flaggedActivity ROW(isNew BOOLEAN))
    ),
    CAST(
      ROW('news.cnn.com', ROW(false)) AS ROW(hostname VARCHAR, flaggedActivity ROW(isNew BOOLEAN))
    ),
    CAST(
      ROW('netflix.com', ROW(false)) AS ROW(hostname VARCHAR, flaggedActivity ROW(isNew BOOLEAN))
    )
  ] as items
)
SELECT sites.hostname, sites.flaggedActivity.isNew
FROM dataset, UNNEST(items) t(sites)
WHERE sites.flaggedActivity.isNew = true
```

返される結果は次のとおりです。

```
+------------------------+
| hostname       | isnew |
+------------------------+
| aws.amazon.com | true  |
+------------------------+
```

# `regexp_like` を使用して配列内でのキーワードを検索する
<a name="filtering-with-regexp"></a>

次の例では、[regexp\$1like](https://prestodb.io/docs/current/functions/regexp.html) 関数を使用して、配列内の要素内でキーワードのデータセットを検索する方法を示します。入力として評価対象の正規表現パターン、またはパイプ (\$1) で区切られた要素のリストを使用し、パターンを評価して、指定された文字列にそれが含まれるかどうかを判別します。

正規表現パターンは文字列内に含まれている必要がありますが、文字列と一致している必要はありません。文字列全体と一致させるには、冒頭に ^、末尾に \$1 を付けてパターンを囲みます (例: `'^pattern$'`)。

ホスト名と `flaggedActivity` 要素が含まれているサイトの配列について考えてみましょう。この要素内の `ARRAY` には、複数の `MAP` 要素が含まれており、要素ごとに異なる一般的なキーワードと人気度カウントを示しています。この配列の `MAP` 内で特定のキーワードを検索するとします。

このデータセットを検索して特定のキーワードを持つサイトを見つけるには、類似した SQL `regexp_like` 演算子の代わりに `LIKE` を使用します。多数のキーワードの検索には `regexp_like` の方が効率的です。

**Example 例 1: `regexp_like` の使用**  
この例のクエリでは、`regexp_like` 関数を使用して用語 `'politics|bigdata'` を検索します。これは配列内の値で見つかります。  

```
WITH dataset AS (
  SELECT ARRAY[
    CAST(
      ROW('aws.amazon.com', ROW(ARRAY[
          MAP(ARRAY['term', 'count'], ARRAY['bigdata', '10']),
          MAP(ARRAY['term', 'count'], ARRAY['serverless', '50']),
          MAP(ARRAY['term', 'count'], ARRAY['analytics', '82']),
          MAP(ARRAY['term', 'count'], ARRAY['iot', '74'])
      ])
      ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
   ),
   CAST(
     ROW('news.cnn.com', ROW(ARRAY[
       MAP(ARRAY['term', 'count'], ARRAY['politics', '241']),
       MAP(ARRAY['term', 'count'], ARRAY['technology', '211']),
       MAP(ARRAY['term', 'count'], ARRAY['serverless', '25']),
       MAP(ARRAY['term', 'count'], ARRAY['iot', '170'])
     ])
     ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
   ),
   CAST(
     ROW('netflix.com', ROW(ARRAY[
       MAP(ARRAY['term', 'count'], ARRAY['cartoons', '1020']),
       MAP(ARRAY['term', 'count'], ARRAY['house of cards', '112042']),
       MAP(ARRAY['term', 'count'], ARRAY['orange is the new black', '342']),
       MAP(ARRAY['term', 'count'], ARRAY['iot', '4'])
     ])
     ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
   )
 ] AS items
),
sites AS (
  SELECT sites.hostname, sites.flaggedactivity
  FROM dataset, UNNEST(items) t(sites)
)
SELECT hostname
FROM sites, UNNEST(sites.flaggedActivity.flags) t(flags)
WHERE regexp_like(flags['term'], 'politics|bigdata')
GROUP BY (hostname)
```
このクエリは 2 つのサイトを返します。  

```
+----------------+
| hostname       |
+----------------+
| aws.amazon.com |
+----------------+
| news.cnn.com   |
+----------------+
```

**Example 例 2: `regexp_like` の使用**  
次の例のクエリでは、`regexp_like` 関数を使用して検索語句に一致するサイトの人気度スコアを合計し、最高から最低の順に並べます。  

```
WITH dataset AS (
  SELECT ARRAY[
    CAST(
      ROW('aws.amazon.com', ROW(ARRAY[
          MAP(ARRAY['term', 'count'], ARRAY['bigdata', '10']),
          MAP(ARRAY['term', 'count'], ARRAY['serverless', '50']),
          MAP(ARRAY['term', 'count'], ARRAY['analytics', '82']),
          MAP(ARRAY['term', 'count'], ARRAY['iot', '74'])
      ])
      ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
    ),
    CAST(
      ROW('news.cnn.com', ROW(ARRAY[
        MAP(ARRAY['term', 'count'], ARRAY['politics', '241']),
        MAP(ARRAY['term', 'count'], ARRAY['technology', '211']),
        MAP(ARRAY['term', 'count'], ARRAY['serverless', '25']),
        MAP(ARRAY['term', 'count'], ARRAY['iot', '170'])
      ])
      ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
    ),
    CAST(
      ROW('netflix.com', ROW(ARRAY[
        MAP(ARRAY['term', 'count'], ARRAY['cartoons', '1020']),
        MAP(ARRAY['term', 'count'], ARRAY['house of cards', '112042']),
        MAP(ARRAY['term', 'count'], ARRAY['orange is the new black', '342']),
        MAP(ARRAY['term', 'count'], ARRAY['iot', '4'])
      ])
      ) AS ROW(hostname VARCHAR, flaggedActivity ROW(flags ARRAY(MAP(VARCHAR, VARCHAR)) ))
    )
  ] AS items
),
sites AS (
  SELECT sites.hostname, sites.flaggedactivity
  FROM dataset, UNNEST(items) t(sites)
)
SELECT hostname, array_agg(flags['term']) AS terms, SUM(CAST(flags['count'] AS INTEGER)) AS total
FROM sites, UNNEST(sites.flaggedActivity.flags) t(flags)
WHERE regexp_like(flags['term'], 'politics|bigdata')
GROUP BY (hostname)
ORDER BY total DESC
```
このクエリは 2 つのサイトを返します。  

```
+------------------------------------+
| hostname       | terms    | total  |
+----------------+-------------------+
| news.cnn.com   | politics |  241   |
+----------------+-------------------+
| aws.amazon.com | bigdata |  10    |
+----------------+-------------------+
```

# 地理空間データをクエリする
<a name="querying-geospatial-data"></a>

地理空間データには、オブジェクトの地理的位置を指定する識別子が含まれています。このタイプのデータの例としては、天気予報、地図の案内、位置情報を含むツイート、店舗の場所、航空路線などがあります。地理空間データは、ビジネス分析、レポート、および予測で重要な役割を果たします。

緯度や経度などの地理空間識別子を使用すると、郵送先住所を地理座標系に変換できます。

## 地理空間クエリとは
<a name="geospatial-query-what-is"></a>

地理空間クエリとは、Athena でサポートされている特殊な SQL クエリタイプです。非空間 SQL クエリとは以下の点が異なります。
+ 特殊なジオメトリデータ型として `point`、`line`、`multiline`、`polygon`、および `multipolygon` を使用する。
+ ジオメトリデータ型間の関係として `distance`、`equals`、`crosses`、`touches`、`overlaps`、`disjoint` などを表現する。

Athena で地理空間クエリを使用すると、以下のオペレーションと、その他の類似したオペレーションを実行できます。
+ 2 点間の距離を確認する。
+ あるエリア (ポリゴン) 内に別のエリアが含まれているかどうかを確認する。
+ 1 つの行が別の行や多角形と交差または接触しているかどうかを確認する。

例えば、Athena でレーニア山の地理座標について `double` 型の値から `point` ジオメトリデータ型を得るには、以下の例にあるように `ST_Point (longitude, latitude)` 地理空間関数を使用します。

```
ST_Point(-121.7602, 46.8527)
```

## 入力データ形式とジオメトリデータ型
<a name="geospatial-input-data-formats-supported-geometry-types"></a>

Athena で地理空間関数を使用するには、データを WKT 形式で入力するか、Hive JSON SerDe を使用します。Athena でサポートされているジオメトリデータ型を使用することもできます。

### 入力データ形式
<a name="input-data-formats"></a>

地理空間クエリを処理するため、Athena では以下のデータ形式での入力データがサポートされています。
+  **WKT (Well-known Text)**。Athena では、WKT が `varchar(x)` または `string` のデータ型として表されます。
+  **JSON エンコード形式の地理空間データ**。地理空間データが含まれている JSON ファイルを解析してテーブルを作成するために、Athena では [Hive JSON SerDe](https://github.com/Esri/spatial-framework-for-hadoop/wiki/Hive-JSON-SerDe) が使用されます。Athena でこの SerDe を使用する方法の詳細については、「[JSON SerDe ライブラリ](json-serde.md)」を参照してください。

### ジオメトリデータ型
<a name="geometry-data-types"></a>

地理空間クエリを処理するため、Athena では以下の特化されたジオメトリデータ型がサポートされています。
+  `point` 
+  `line` 
+  `polygon` 
+  `multiline` 
+  `multipolygon` 

## サポートされる地理空間関数
<a name="geospatial-functions-list"></a>

Athena エンジンバージョン 3 の地理空間関数については、「Trino documentation」の「[Geospatial functions](https://trino.io/docs/current/functions/geospatial.html)」を参照してください。

# 例: 地理空間クエリ
<a name="geospatial-example-queries"></a>

このトピックの例では、GitHub で利用可能なサンプルデータから 2 つのテーブルを作成し、そのデータに基づいてテーブルをクエリします。サンプルデータは、あくまで例に過ぎず、正確であることは保証されていません。以下のファイルにあります。
+ **[https://github.com/Esri/gis-tools-for-hadoop/blob/master/samples/data/earthquake-data/earthquakes.csv](https://github.com/Esri/gis-tools-for-hadoop/blob/master/samples/data/earthquake-data/earthquakes.csv)** – カリフォルニアで発生した地震をリスト化します。この `earthquakes` テーブルの例では、このデータのフィールドを使用しています。
+ **[https://github.com/Esri/gis-tools-for-hadoop/blob/master/samples/data/counties-data/california-counties.json](https://github.com/Esri/gis-tools-for-hadoop/blob/master/samples/data/counties-data/california-counties.json)** – [ESRI 準拠の GeoJSON 形式](https://doc.arcgis.com/en/arcgis-online/reference/geojson.htm)でカリフォルニア州の郡データをリスト化します。データには `AREA`、`PERIMETER`、`STATE`、`COUNTY`、および `NAME` など多くのフィールドが含まれていますが 、サンプルの `counties` テーブルでは `Name` (文字列) と `BoundaryShape` (バイナリ) の 2 つしか使用していません。
**注記**  
Athena は、`com.esri.json.hadoop.EnclosedEsriJsonInputFormat` を使用して JSON データを地理空間バイナリ形式に変換します。

以下のコード例は、`earthquakes` という名前のテーブルを作成します。

```
CREATE external TABLE earthquakes
(
 earthquake_date string,
 latitude double,
 longitude double,
 depth double,
 magnitude double,
 magtype string,
 mbstations string,
 gap string,
 distance string,
 rms string,
 source string,
 eventid string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE LOCATION 's3://amzn-s3-demo-bucket/my-query-log/csv/';
```

以下のコード例は、`counties` という名前のテーブルを作成します。

```
CREATE external TABLE IF NOT EXISTS counties
 (
 Name string,
 BoundaryShape binary
 )
ROW FORMAT SERDE 'com.esri.hadoop.hive.serde.EsriJsonSerDe'
STORED AS INPUTFORMAT 'com.esri.json.hadoop.EnclosedEsriJsonInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/my-query-log/json/';
```

以下のサンプルクエリは、`CROSS JOIN` 関数を `counties` および `earthquake` テーブルで使用します。この例では、境界に `ST_POINT` で指定される地震位置が含まれる郡のクエリに `ST_CONTAINS` を使用します。クエリはこれらの郡を名前でグループ化し、発生数順に並べて、それらを降順で返します。

```
SELECT counties.name,
        COUNT(*) cnt
FROM counties
CROSS JOIN earthquakes
WHERE ST_CONTAINS (ST_GeomFromLegacyBinary(counties.boundaryshape), ST_POINT(earthquakes.longitude, earthquakes.latitude))
GROUP BY  counties.name
ORDER BY  cnt DESC
```

このクエリは以下を返します。

```
+------------------------+
| name             | cnt |
+------------------------+
| Kern             | 36  |
+------------------------+
| San Bernardino   | 35  |
+------------------------+
| Imperial         | 28  |
+------------------------+
| Inyo             | 20  |
+------------------------+
| Los Angeles      | 18  |
+------------------------+
| Riverside        | 14  |
+------------------------+
| Monterey         | 14  |
+------------------------+
| Santa Clara      | 12  |
+------------------------+
| San Benito       | 11  |
+------------------------+
| Fresno           | 11  |
+------------------------+
| San Diego        | 7   |
+------------------------+
| Santa Cruz       | 5   |
+------------------------+
| Ventura          | 3   |
+------------------------+
| San Luis Obispo  | 3   |
+------------------------+
| Orange           | 2   |
+------------------------+
| San Mateo        | 1   |
+------------------------+
```

## その他のリソース
<a name="geospatial-example-queries-additional-resources"></a>

地理空間クエリのその他の例については、次のブログ記事を参照してください。
+ [Extend geospatial queries in Amazon Athena with UDFs and AWS Lambda](https://aws.amazon.com/blogs/big-data/extend-geospatial-queries-in-amazon-athena-with-udfs-and-aws-lambda/) 
+ [Visualize over 200 years of global climate data using Amazon Athena and Amazon Quick](https://aws.amazon.com/blogs/big-data/visualize-over-200-years-of-global-climate-data-using-amazon-athena-and-amazon-quicksight/).
+ [Querying OpenStreetMap with Amazon Athena](https://aws.amazon.com/blogs/big-data/querying-openstreetmap-with-amazon-athena/)

# JSON データをクエリする
<a name="querying-JSON"></a>

Amazon Athena では、JSON でエンコードされたデータのクエリ、ネストされた JSON からのデータの抽出、値の検索、および JSON 配列の長さとサイズの確認を行うことができます。Athena で JSON データをクエリする際の基本については、次のサンプル planet データを検討してください。

```
{name:"Mercury",distanceFromSun:0.39,orbitalPeriod:0.24,dayLength:58.65}
{name:"Venus",distanceFromSun:0.72,orbitalPeriod:0.62,dayLength:243.02}
{name:"Earth",distanceFromSun:1.00,orbitalPeriod:1.00,dayLength:1.00}
{name:"Mars",distanceFromSun:1.52,orbitalPeriod:1.88,dayLength:1.03}
```

各レコード (基本的に、テーブル内の各行) がそれぞれの行にどのように配置されているかに注目してください。この JSON データをクエリするには、次のような `CREATE TABLE` ステートメントを使用します。

```
CREATE EXTERNAL TABLE `planets_json`(
  `name` string,
  `distancefromsun` double,
  `orbitalperiod` double,
  `daylength` double)
ROW FORMAT SERDE
  'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/json/'
```

データをクエリするには、次のようなシンプルな `SELECT` ステートメントを使用します。

```
SELECT * FROM planets_json
```

クエリの結果は以下のようになります。


****  

| \$1 | name | distancefromsun | orbitalperiod | daylength | 
| --- | --- | --- | --- | --- | 
| 1 | Mercury | 0.39 | 0.24 | 58.65 | 
| 2 | Venus | 0.72 | 0.62 | 243.02 | 
| 3 | Earth | 1.0 | 1.0 | 1.0 | 
| 4 | Mars | 1.52 | 1.88 | 1.03 | 

`CREATE TABLE` ステートメントが [OpenX JSON SerDe](openx-json-serde.md) をどのように使用しているかに注目してください。これにより、各 JSON レコードを別の行に配置する必要があります。JSON がプリティプリント形式の場合、またはすべてのレコードが 1 行にある場合、データは正しく読み取られません。

プリティプリント形式の JSON データをクエリするには、OpenX JSON SerDe の代わりに [Amazon Ion Hive SerDe](ion-serde.md) を使用できます。プリティプリント形式で保存された以前のデータについて考えてみましょう。

```
{
  name:"Mercury",
  distanceFromSun:0.39,
  orbitalPeriod:0.24,
  dayLength:58.65
}
{
  name:"Venus",
  distanceFromSun:0.72,
  orbitalPeriod:0.62,
  dayLength:243.02
}
{
  name:"Earth",
  distanceFromSun:1.00,
  orbitalPeriod:1.00,
  dayLength:1.00
}
{
  name:"Mars",
  distanceFromSun:1.52,
  orbitalPeriod:1.88,
  dayLength:1.03
}
```

このデータをクエリするには、次のような `CREATE TABLE` ステートメントを使用します。OpenX JSON SerDe を指定する代わりに、このステートメントが `STORED AS ION` を指定していることに注意してください。

```
CREATE EXTERNAL TABLE `planets_ion`(
  `name` string,
  `distancefromsun` DECIMAL(10, 2),
  `orbitalperiod` DECIMAL(10, 2),
  `daylength` DECIMAL(10, 2))
STORED AS ION
LOCATION
  's3://amzn-s3-demo-bucket/json-ion/'
```

クエリ `SELECT * FROM planets_ion` は以前と同じ結果を生成します。Amazon Ion Hive SerDe を使用してこの方法でテーブルを作成する方法の詳細については、「[Amazon Ion テーブルを作成する](ion-serde-using-create-table.md)」を参照してください。

前述の JSON データの例には、ネストされた配列や構造体などの複雑なデータ型は含まれていません。ネストされた JSON データのクエリについては、「[例: ネスト JSON の逆シリアル化](openx-json-serde.md#nested-json-serde-example)」を参照してください。

**Topics**
+ [JSON データ読み取りのベストプラクティス](parsing-json-data.md)
+ [文字列から JSON データを抽出する](extracting-data-from-JSON.md)
+ [JSON 配列内の値を検索する](searching-for-values.md)
+ [JSON 配列の長さとサイズを取得する](length-and-size.md)
+ [JSON クエリをトラブルシューティングする](json-troubleshooting.md)

# JSON データ読み取りのベストプラクティス
<a name="parsing-json-data"></a>

JavaScript Object Notation (JSON) は、データ構造をテキストとしてエンコードするための一般的な方法です。多くのアプリケーションやツールは、JSON エンコード形式のデータを出力します。

Amazon Athena では、外部データからテーブルを作成し、それらに JSON でエンコードされたデータを含めることができます。このようなタイプのソースデータには、Athena を [JSON SerDe ライブラリ](json-serde.md) と共に使用します。

JSON でエンコードされたデータを読み取るために以下のヒントを使用してください。
+ 適切な SerDe、ネイティブ JSON SerDe、`org.apache.hive.hcatalog.data.JsonSerDe`、または OpenX SerDe、`org.openx.data.jsonserde.JsonSerDe` を選択します。詳細については、「[JSON SerDe ライブラリ](json-serde.md)」を参照してください。
+ 各 JSON エンコード方式のレコードが、プリティプリントではなく、個別の行に入力されていることを確認します。
**注記**  
SerDe では、各 JSON ドキュメントが、レコード内のフィールドを区切る行終端文字なしの、1 行のテキストに収まっていることを想定しています。JSON テキストがプリティプリント形式の場合、テーブルを作成した後にクエリを実行しようとすると、以下のようなエラーメッセージが表示される場合があります。「HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object」、または「HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT」。詳細については、GitHub の OpenX SerDe のドキュメントで「[JSON Data Files](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)」(JSON データファイル) を参照してください。
+ JSON でエンコードされたデータを、大文字と小文字が区別されない列内に生成します。
+ 例に示すように、誤った形式のレコードを無視するオプションを指定します。

  ```
  CREATE EXTERNAL TABLE json_table (
    column_a string,
    column_b int
   )
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
   WITH SERDEPROPERTIES ('ignore.malformed.json' = 'true')
   LOCATION 's3://amzn-s3-demo-bucket/path/';
  ```
+ Athena で、未確定のスキーマを持つソースデータのフィールドを JSON でエンコードされた文字列に変換します。

Athena が JSON データに基づくテーブルを作成するとき、Athena は既存の事前定義されたスキーマに基づいてデータを解析します。しかし、データには事前定義されたスキーマがないものもあります。このような場合におけるスキーマ管理を簡素化するには、多くの場合、不確定のスキーマがあるソースデータのフィールドを Athena で JSON 文字列に変換してから、[JSON SerDe ライブラリ](json-serde.md) を使用することが有用です。

たとえば、さまざまなセンサーからのイベントを一般的なフィールドで発行する IoT アプリケーションについて考えます。これらのフィールドの 1 つに、イベントを送信するセンサー独自のカスタムペイロードを保存する必要があるとします。この場合、スキーマがわからないため、情報を JSON エンコード形式の文字列として保存することをお勧めします。これを実行するには、以下の例にあるように、Athena テーブル内のデータを JSON に変換します。JSON でエンコードされたデータを Athena データ型に変換することも可能です。

**Topics**
+ [Athena データ型を JSON データに変換する](converting-native-data-types-to-json.md)
+ [JSON を Athena データ型に変換する](converting-json-to-native-data-types.md)

# Athena データ型を JSON データに変換する
<a name="converting-native-data-types-to-json"></a>

Athena データ型を JSON データに変換するには、`CAST` を使用します。

```
WITH dataset AS (
  SELECT
    CAST('HELLO ATHENA' AS JSON) AS hello_msg,
    CAST(12345 AS JSON) AS some_int,
    CAST(MAP(ARRAY['a', 'b'], ARRAY[1,2]) AS JSON) AS some_map
)
SELECT * FROM dataset
```

このクエリは以下を返します。

```
+-------------------------------------------+
| hello_msg      | some_int | some_map      |
+-------------------------------------------+
| "HELLO ATHENA" | 12345    | {"a":1,"b":2} |
+-------------------------------------------+
```

# JSON を Athena データ型に変換する
<a name="converting-json-to-native-data-types"></a>

JSON データを Athena データ型に変換するには、`CAST` を使用します。

**注記**  
以下の例では、文字列を JSON エンコード形式にするために、`JSON` キーワードで開始し、文字列を単一引用符で囲んでいます (例: `JSON '12345'`)。

```
WITH dataset AS (
  SELECT
    CAST(JSON '"HELLO ATHENA"' AS VARCHAR) AS hello_msg,
    CAST(JSON '12345' AS INTEGER) AS some_int,
    CAST(JSON '{"a":1,"b":2}' AS MAP(VARCHAR, INTEGER)) AS some_map
)
SELECT * FROM dataset
```

このクエリは以下を返します。

```
+-------------------------------------+
| hello_msg    | some_int | some_map  |
+-------------------------------------+
| HELLO ATHENA | 12345    | {a:1,b:2} |
+-------------------------------------+
```

# 文字列から JSON データを抽出する
<a name="extracting-data-from-JSON"></a>

Athena のテーブルにデシリアライズしたくない、JSON でエンコードされた文字列が含まれるデータソースがある場合があります。このような場合でも、Presto の JSON 関数を使用し、このデータに対して SQL オペレーションを実行できます。

次の JSON 文字列をデータセット例として考えます。

```
{"name": "Susan Smith",
"org": "engineering",
"projects":
    [
     {"name":"project1", "completed":false},
     {"name":"project2", "completed":true}
    ]
}
```

## 例: プロパティを抽出する
<a name="examples-extracting-properties"></a>

この JSON 文字列から `name` プロパティと `projects` プロパティを抽出するには、次の例に示すように、`json_extract` 関数を使用します。`json_extract` 関数は、JSON 文字列を含む列を対象にして、`JSONPath` (ドット `.` 表記を含む式など) を使用して JSON 文字列を検索します。

**注記**  
 `JSONPath` は、単純なツリー トラバーサルを行います。JSON ドキュメントのルートを示す `$` 記号に続けて、ルートの直下にネストされたピリオドと要素を使用します (例: `$.name`)。

```
WITH dataset AS (
  SELECT '{"name": "Susan Smith",
           "org": "engineering",
           "projects": [{"name":"project1", "completed":false},
           {"name":"project2", "completed":true}]}'
    AS myblob
)
SELECT
  json_extract(myblob, '$.name') AS name,
  json_extract(myblob, '$.projects') AS projects
FROM dataset
```

返される値は JSON でエンコードされた文字列で、ネイティブ Athena データ型ではありません。

```
+-----------------------------------------------------------------------------------------------+
| name           | projects                                                                     |
+-----------------------------------------------------------------------------------------------+
| "Susan Smith"  | [{"name":"project1","completed":false},{"name":"project2","completed":true}] |
+-----------------------------------------------------------------------------------------------+
```

JSON 文字列からスカラー値を抽出するには、`json_extract_scalar(json, json_path)` 関数を使用します。これは `json_extract` に似ていますが、JSON でエンコードされた文字列の代わりに `varchar` 文字列値を返します。*json\$1path* パラメータの値は、スカラー (ブール値、数値、または文字列) である必要があります。

**注記**  
配列、マップ、または構造体に対して `json_extract_scalar` 関数は使用しないでください。

```
WITH dataset AS (
  SELECT '{"name": "Susan Smith",
           "org": "engineering",
           "projects": [{"name":"project1", "completed":false},{"name":"project2", "completed":true}]}'
    AS myblob
)
SELECT
  json_extract_scalar(myblob, '$.name') AS name,
  json_extract_scalar(myblob, '$.projects') AS projects
FROM dataset
```

このクエリは以下を返します。

```
+---------------------------+
| name           | projects |
+---------------------------+
| Susan Smith    |          |
+---------------------------+
```

配列の例で `projects` プロパティの最初の要素を取得するには、`json_array_get` 関数を使用してインデックス位置を指定します。

```
WITH dataset AS (
  SELECT '{"name": "Bob Smith",
           "org": "engineering",
           "projects": [{"name":"project1", "completed":false},{"name":"project2", "completed":true}]}'
    AS myblob
)
SELECT json_array_get(json_extract(myblob, '$.projects'), 0) AS item
FROM dataset
```

JSON エンコード形式の配列で、指定したインデックス位置にある値が返されます。

```
+---------------------------------------+
| item                                  |
+---------------------------------------+
| {"name":"project1","completed":false} |
+---------------------------------------+
```

Athena 文字列型を返すには、`JSONPath` 式内で `[]` 演算子を使用し、次に `json_extract_scalar` 関数を使用します。`[]` の詳細については、「[配列要素にアクセスする](accessing-array-elements.md)」を参照してください。

```
WITH dataset AS (
   SELECT '{"name": "Bob Smith",
             "org": "engineering",
             "projects": [{"name":"project1", "completed":false},{"name":"project2", "completed":true}]}'
     AS myblob
)
SELECT json_extract_scalar(myblob, '$.projects[0].name') AS project_name
FROM dataset
```

次の結果が返されます。

```
+--------------+
| project_name |
+--------------+
| project1     |
+--------------+
```

# JSON 配列内の値を検索する
<a name="searching-for-values"></a>

JSON エンコード形式の配列内に特定の値が存在するかどうかを確認するには、`json_array_contains` 関数を使用します。

次のクエリでは「project2」に参加しているユーザーの名前を一覧表示します。

```
WITH dataset AS (
  SELECT * FROM (VALUES
    (JSON '{"name": "Bob Smith", "org": "legal", "projects": ["project1"]}'),
    (JSON '{"name": "Susan Smith", "org": "engineering", "projects": ["project1", "project2", "project3"]}'),
    (JSON '{"name": "Jane Smith", "org": "finance", "projects": ["project1", "project2"]}')
  ) AS t (users)
)
SELECT json_extract_scalar(users, '$.name') AS user
FROM dataset
WHERE json_array_contains(json_extract(users, '$.projects'), 'project2')
```

このクエリはユーザーのリストを返します。

```
+-------------+
| user        |
+-------------+
| Susan Smith |
+-------------+
| Jane Smith  |
+-------------+
```

次のクエリ例では、プロジェクトを完了したユーザーの名前とユーザー別の完了したプロジェクト数を一覧表示します。実行するアクションは以下のとおりです。
+ `SELECT` ステートメントをネストして見やすくします。
+ プロジェクトの配列を抽出します。
+ `CAST` で配列をキー/値ペアのネイティブ配列に変換します。
+ `UNNEST` 演算子を使用して配列の各要素を抽出します。
+ 取得した値をフィルタ処理して完了済みプロジェクトに絞り込み、カウントします。

**注記**  
`CAST` を使用して `MAP` する場合、キー要素を `VARCHAR` (Presto のネイティブ文字列) として指定できますが、値は JSON のままにします。`MAP` の値は、最初のキー/値ペアが文字列型で、2 番目のペアがブール型であるなど、さまざまな型になるためです。

```
WITH dataset AS (
  SELECT * FROM (VALUES
    (JSON '{"name": "Bob Smith",
             "org": "legal",
             "projects": [{"name":"project1", "completed":false}]}'),
    (JSON '{"name": "Susan Smith",
             "org": "engineering",
             "projects": [{"name":"project2", "completed":true},
                          {"name":"project3", "completed":true}]}'),
    (JSON '{"name": "Jane Smith",
             "org": "finance",
             "projects": [{"name":"project2", "completed":true}]}')
  ) AS t (users)
),
employees AS (
  SELECT users, CAST(json_extract(users, '$.projects') AS
    ARRAY(MAP(VARCHAR, JSON))) AS projects_array
  FROM dataset
),
names AS (
  SELECT json_extract_scalar(users, '$.name') AS name, projects
  FROM employees, UNNEST (projects_array) AS t(projects)
)
SELECT name, count(projects) AS completed_projects FROM names
WHERE cast(element_at(projects, 'completed') AS BOOLEAN) = true
GROUP BY name
```

このクエリは次の結果を返します。

```
+----------------------------------+
| name        | completed_projects |
+----------------------------------+
| Susan Smith | 2                  |
+----------------------------------+
| Jane Smith  | 1                  |
+----------------------------------+
```

# JSON 配列の長さとサイズを取得する
<a name="length-and-size"></a>

JSON 配列の長さとサイズを取得するために、`json_array_length` および `json_size` 関数を使用できます。

## 例: `json_array_length`
<a name="example-json-array-length"></a>

JSON エンコード形式の配列の長さを取得するには、`json_array_length` 関数を使用します。

```
WITH dataset AS (
  SELECT * FROM (VALUES
    (JSON '{"name":
            "Bob Smith",
            "org":
            "legal",
            "projects": [{"name":"project1", "completed":false}]}'),
    (JSON '{"name": "Susan Smith",
            "org": "engineering",
            "projects": [{"name":"project2", "completed":true},
                         {"name":"project3", "completed":true}]}'),
    (JSON '{"name": "Jane Smith",
             "org": "finance",
             "projects": [{"name":"project2", "completed":true}]}')
  ) AS t (users)
)
SELECT
  json_extract_scalar(users, '$.name') as name,
  json_array_length(json_extract(users, '$.projects')) as count
FROM dataset
ORDER BY count DESC
```

このクエリは次の結果を返します。

```
+---------------------+
| name        | count |
+---------------------+
| Susan Smith | 2     |
+---------------------+
| Bob Smith   | 1     |
+---------------------+
| Jane Smith  | 1     |
+---------------------+
```

## 例: `json_size`
<a name="example-json-size"></a>

JSON エンコード形式の配列やオブジェクトのサイズを取得するには、`json_size` 関数を使用し、JSON 文字列を含む列とその配列やオブジェクトへの `JSONPath` 式を指定します。

```
WITH dataset AS (
  SELECT * FROM (VALUES
    (JSON '{"name": "Bob Smith", "org": "legal", "projects": [{"name":"project1", "completed":false}]}'),
    (JSON '{"name": "Susan Smith", "org": "engineering", "projects": [{"name":"project2", "completed":true},{"name":"project3", "completed":true}]}'),
    (JSON '{"name": "Jane Smith", "org": "finance", "projects": [{"name":"project2", "completed":true}]}')
  ) AS t (users)
)
SELECT
  json_extract_scalar(users, '$.name') as name,
  json_size(users, '$.projects') as count
FROM dataset
ORDER BY count DESC
```

このクエリは次の結果を返します。

```
+---------------------+
| name        | count |
+---------------------+
| Susan Smith | 2     |
+---------------------+
| Bob Smith   | 1     |
+---------------------+
| Jane Smith  | 1     |
+---------------------+
```

# JSON クエリをトラブルシューティングする
<a name="json-troubleshooting"></a>

JSON 関連のクエリに関する問題のトラブルシューティングについては、「[JSON 関連のエラー](troubleshooting-athena.md#troubleshooting-athena-json-related-errors)」、または以下のリソースを参照してください。
+ [Amazon Athena で JSON データを読み込もうとすると、エラーが発生します。](https://aws.amazon.com/premiumsupport/knowledge-center/error-json-athena/)
+ [Athena で AWS Config からファイルを読み取る際に発生する、「HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object – JSONException: Duplicate key (HIVE\$1CURSOR\$1ERROR: 行は有効な JSON オブジェクトではありません – JSONException: キーの重複)」を解決する方法を教えてください。](https://aws.amazon.com/premiumsupport/knowledge-center/json-duplicate-key-error-athena-config/)
+ [JSON ファイルに複数のレコードがあるにも関わらず、Amazon Athena の SELECT COUNT クエリがレコードを 1 件しか返しません。](https://aws.amazon.com/premiumsupport/knowledge-center/select-count-query-athena-json-records/)
+ [Athena テーブルの行の Amazon S3 ソースファイルを表示するにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/find-s3-source-file-athena-table-row/)

「[Amazon Athena での SQL クエリに関する考慮事項と制約事項](other-notable-limitations.md)」も参照してください。

# Amazon Athena で機械学習 (ML) を使用する
<a name="querying-mlmodel"></a>

Machine Learning (ML) with Amazon Athena では、Amazon SageMaker AI を使用して Machine Learning (ML) 推論を実行する SQL ステートメントの記述に Athena を使用できます。この機能により、データ分析用の ML モデルへのアクセスが簡単になり、複合型のプログラミング方法を使用して推論を実行する必要がなくなります。

ML with Athena を使用するには、`USING EXTERNAL FUNCTION` 句で ML with Athena 関数を定義します。この関数は、使用する SageMaker AI モデルのエンドポイントをポイントし、モデルに渡す変数名とデータ型を指定します。クエリの後続の句は、関数を参照してモデルに値を渡します。モデルは、クエリが渡す値に基づいて推論を実行し、推論結果を返します。SageMaker AI に関する詳細と SageMaker AI エンドポイントの仕組みに関する詳細については、「[Amazon SageMaker AI デベロッパーガイド](https://docs.aws.amazon.com/sagemaker/latest/dg/)」を参照してください。

ML with Athena と SageMaker AI 推論を使用して結果セット内の異常な値を検出する例については、AWS ビッグデータブログの記事「[Amazon Athena 機械学習推論機能を起動して異常値を検出する](https://aws.amazon.com/blogs/big-data/detecting-anomalous-values-by-invoking-the-amazon-athena-machine-learning-inference-function/)」を参照してください。

## 考慮事項と制限事項
<a name="considerations-and-limitations"></a>
+ **利用可能なリージョン** – Athena ML 機能は、Athena エンジンバージョン 2 以降がサポートされている AWS リージョンで使用できます。
+ **SageMaker AI モデルのエンドポイントは `text/csv` を受け入れて返す必要があります** – データ形式の詳細については、「*Amazon SageMaker AI デベロッパーガイド*」の「[推論の共通データ形式](https://docs.aws.amazon.com/sagemaker/latest/dg/cdf-inference.html)」を参照してください。
+ **Athena が CSV ヘッダーを送信しない** – SageMaker AI エンドポイントが `text/csv` である場合、入力ハンドラーは入力の最初の行が CSV ヘッダーであると想定しません。Athena は CSV ヘッダーを送信しないため、Athena に返される出力に含まれる結果は Athena が想定する行よりも 1 行少なくなり、エラーが発生します。
+ **SageMaker AI エンドポイントのスケーリング** – 参照された SageMaker AI モデルのエンドポイントが、エンドポイントへの Athena コールのために十分にスケールアップされていることを確認してください。詳細については、「*Amazon SageMaker AI デベロッパーガイド*」の「[SageMaker AI モデルの自動スケーリング](https://docs.aws.amazon.com/sagemaker/latest/dg/endpoint-auto-scaling.html)」と、「*Amazon SageMaker AI API リファレンス*」の「[CreateEndpointConfig](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateEndpointConfig.html)」を参照してください。
+ **IAM アクセス許可** – ML with Athena 関数を指定するクエリを実行するには、クエリを実行する IAM プリンシパルに、参照される SageMaker AI モデルのエンドポイントへの `sagemaker:InvokeEndpoint` アクションの実行が許可されている必要があります。詳細については、「[Athena で ML へのアクセスを許可する](machine-learning-iam-access.md)」を参照してください。
+ **`GROUP BY` 句で ML with Athena 関数を直接使用することはできません**

**Topics**
+ [考慮事項と制限事項](#considerations-and-limitations)
+ [ML with Athena 構文を使用する](ml-syntax.md)
+ [お客様のユースケースを見る](ml-videos.md)

# ML with Athena 構文を使用する
<a name="ml-syntax"></a>

`USING EXTERNAL FUNCTION` 句は、クエリ内の後続の `SELECT` ステートメントで参照できる 1 つの ML with Athena 関数または複数の関数を指定します。関数名、変数名、および変数と戻り値のデータ型を定義します。

## 概要
<a name="ml-synopsis"></a>

以下の構文は、ML with Athena 関数を指定する `USING EXTERNAL FUNCTION` 句を示しています。

```
USING EXTERNAL FUNCTION ml_function_name (variable1 data_type[, variable2 data_type][,...])
RETURNS data_type 
SAGEMAKER 'sagemaker_endpoint'
SELECT ml_function_name()
```

## パラメータ
<a name="udf-parameters"></a>

**USING EXTERNAL FUNCTION *ml\$1function\$1name* (*variable1**data\$1type*[, *variable2**data\$1type*][,...])**  
*ml\$1function\$1name* は、後続のクエリ句で使用できる関数名を定義します。各 *variable data\$1type* は、SageMaker AI モデルが入力として受け入れる名前付き変数とそれに対応するデータ型を指定します。指定されるデータ型は、サポートされている Athena データ型である必要があります。

**RETURNS *data\$1type***  
*data\$1type* は、SageMaker AI モデルからの出力として *ml\$1function\$1name* がクエリに返す SQL データ型を指定します。

**SAGEMAKER '*sagemaker\$1endpoint*'**  
*sagemaker\$1endpoint* は、SageMaker AI モデルのエンドポイントを指定します。

**SELECT [...]*ml\$1function\$1name*(*expression*) [...]**  
結果を返すために関数変数と SageMaker AI モデルに値を渡す SELECT クエリです。*ml\$1function\$1name* は以前にクエリで定義された関数を指定し、値を渡すために評価される *expression* がその後に続きます。渡される値および返される値は、`USING EXTERNAL FUNCTION` 句内の関数に指定された対応するデータ型と一致する必要があります。

## 例
<a name="ml-examples"></a>

以下の例は、ML with Athena を使用したクエリを示しています。

**Example**  

```
USING EXTERNAL FUNCTION predict_customer_registration(age INTEGER) 
    RETURNS DOUBLE
    SAGEMAKER 'xgboost-2019-09-20-04-49-29-303' 
SELECT predict_customer_registration(age) AS probability_of_enrolling, customer_id 
     FROM "sampledb"."ml_test_dataset" 
     WHERE predict_customer_registration(age) < 0.5;
```

# お客様のユースケースを見る
<a name="ml-videos"></a>

Machine Learning (ML) with Amazon Athena のプレビュー版を使用する以下の動画では、Athena と SageMaker AI を併用できる方法が紹介されています。

## カスタマーチャーンの予測
<a name="ml-videos-predict-churn"></a>

以下の動画は、Athena と Amazon SageMaker AI の機械学習機能を組み合わせてカスタマーチャーンを予測する方法を紹介しています。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/CUHbSpekRVg/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/CUHbSpekRVg)


## ボットネットの検出
<a name="ml-videos-detect-botnets"></a>

以下の動画は、ある企業が Amazon Athena と Amazon SageMaker AI を使用してボットネットを検出する方法を紹介しています。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/0dUv-jCt2aw/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/0dUv-jCt2aw)


# ユーザー定義関数を使用してクエリする
<a name="querying-udf"></a>

Amazon Athena のユーザー定義関数 (UDF) を使用すると、レコードまたはレコードのグループを処理するためのカスタム関数を作成できます。UDF は、パラメータを受け入れ、作業を実行し、結果を返します。

Athena で UDF を使用するには、SQL クエリの `USING EXTERNAL FUNCTION` ステートメントの前に `SELECT` 句を記述します。この `SELECT` ステートメントは UDF を参照し、クエリの実行時に、UDF に渡される変数を定義します。SQL クエリは UDF を呼び出すときに、Java ランタイムを使用して Lambda 関数を呼び出します。UDF は、Java デプロイパッケージのメソッドとして Lambda 関数内で定義されます。Lambda 関数の同じ Java デプロイパッケージで複数の UDF を定義できます。また、`USING EXTERNAL FUNCTION` 句で Lambda 関数の名前も指定します。

Athena UDF 用の Lambda 関数のデプロイには 2 つのオプションがあり、Lambda を使用して直接関数をデプロイすることも、AWS Serverless Application Repository を使用することもできます。UDF の既存の Lambda 関数を検索するには、パブリック AWS Serverless Application Repository またはプライベートリポジトリを検索し、Lambda にデプロイします。また、Java ソースコードを作成または変更して、JAR ファイルにパッケージ化し、Lambda または AWS Serverless Application Repository を使用してデプロイすることもできます。これを開始するための Java ソースコードとパッケージの例については、「[Lambda を利用して UDF を作成およびデプロイする](udf-creating-and-deploying.md)」を参照してください。Lambda の詳細については、[AWS Lambda デベロッパーガイド](https://docs.aws.amazon.com/lambda/latest/dg/)を参照してください。AWS Serverless Application Repository の詳細については、[AWS Serverless Application Repository 開発者ガイド](https://docs.aws.amazon.com/serverlessrepo/latest/devguide/)を参照してください。

Athena で UDF を使用してテキストを翻訳および分析する例については、AWS Machine Learning ブログ記事「[Amazon Athena、Amazon Translate、および Amazon Comprehend で SQL 関数を使用してテキストを翻訳および分析する](https://aws.amazon.com/blogs/machine-learning/translate-and-analyze-text-using-sql-functions-with-amazon-athena-amazon-translate-and-amazon-comprehend/)」を参照、または [video](udf-videos.md#udf-videos-xlate) をご覧ください。

UDF を使用して Amazon Athena で地理空間クエリを拡張する例については、*AWS Big Data Blog* の「[Extend geospatial queries in Amazon Athena with UDFs and AWS Lambda](https://aws.amazon.com/blogs/big-data/extend-geospatial-queries-in-amazon-athena-with-udfs-and-aws-lambda/)」を参照してください。

**Topics**
+ [Athena の UDF の動画](udf-videos.md)
+ [考慮事項と制限事項](udf-considerations-limitations.md)
+ [UDF クエリ構文を使用してクエリする](udf-query-syntax.md)
+ [Lambda を利用して UDF を作成およびデプロイする](udf-creating-and-deploying.md)

# Athena の UDF の動画
<a name="udf-videos"></a>

Athena での UDF の使用に関する詳細については、以下の動画をご覧ください。

**動画: Amazon Athena のユーザー定義関数 (UDF) の概要**  
以下の動画は、Amazon Athena で UDF を使用して、機密情報のリダクションを行う方法を紹介しています。

**注記**  
この動画で示されている構文はリリース前のものですが、概念は同じです。`AmazonAthenaPreviewFunctionality` ワークグループなしで Athena を使用してください。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/AxJ6jP4Pfmo/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/AxJ6jP4Pfmo)


**動画:Amazon Athena で SQL クエリを使用したテキストフィールドの翻訳、分析、およびリダクション**  
以下の動画は、その他の AWS のサービス と共に Amazon Athena の UDF を使用して、テキストを翻訳し、分析する方法を紹介しています。

**注記**  
この動画で示されている構文はリリース前のものですが、概念は同じです。正しい構文については、*AWS Machine Learning ブログ*の関連するブログ記事「[Amazon Athena、Amazon Translate、および Amazon Comprehend による SQL 関数を使用したテキストの翻訳、修正、分析](https://aws.amazon.com/blogs/machine-learning/translate-and-analyze-text-using-sql-functions-with-amazon-athena-amazon-translate-and-amazon-comprehend/)」を参照してください。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/Od7rXG-WMO4/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/Od7rXG-WMO4)


# 考慮事項と制限事項
<a name="udf-considerations-limitations"></a>

Athena でユーザー定義関数 (UDF) を使用する際には、次の点を考慮してください。
+ **組み込み Athena 関数** – Athena の組み込み関数は、高い性能を発揮するように設計されています。可能な場合は、UDF よりも組み込み関数を使用することをお勧めします。組み込み関数の詳細については、「[Amazon Athena の関数](functions.md)」を参照してください。
+ **スカラー UDF 限定** – Athena は、一度に 1 行を処理し、単一の列値を返すスカラー UDF のみをサポートします。Athena は、Lambda を呼び出すたびに行のバッチを UDF に渡しましますが、これは並行的に行われる可能性があります。UDF とクエリを設計するときは、この処理がネットワークトラフィックに及ぼす可能性がある影響に注意する必要があります。
+ **UDF ハンドラ関数は省略形式を使用** – UDF 関数には、省略形式 (フルフォーマットではない) を使用します (例:`package.Class::method` の代わりに `package.Class`)。
+ **UDF メソッドは小文字を使用する必要がある** – UDF メソッドは小文字にする必要があります。キャメルケースは使用できません。
+ **パラメータを必要とする UDF メソッド** — UDF メソッドには少なくとも 1 つの入力パラメータが必要です。入力パラメータなしで定義された UDF を呼び出そうとすると、ランタイム例外が発生する原因となります。UDF はデータレコードに対して関数を実行するためのものですが、引数のない UDF はデータを取り込まないため、例外が発生します。
+ **Java ランタイムサポート** – 現在、Athena UDF は Lambda について Java 8、Java 11、Java 17 のランタイムをサポートしています。詳細については、*AWS Lambda デベロッパーガイド*の「[Java による Lambda 関数のビルド](https://docs.aws.amazon.com/lambda/latest/dg/lambda-java.html)」を参照してください。
**注記**  
 Java 17 の場合、`JAVA_TOOL_OPTIONS` 環境変数の値を Lambda の `--add-opens=java.base/java.nio=ALL-UNNAMED` に設定する必要があります。
+ **IAM 許可** – Athena で UDF クエリステートメントを作成して実行するには、クエリを実行する IAM プリンシパルに、Athena 関数以外のアクションを実行することが許可されている必要があります。詳細については、「[Athena UDF へのアクセスを許可する: ポリシーの例](udf-iam-access.md)」を参照してください。
+ **Lambda のクォータ** – UDF には Lambda のクォータが適用されます。詳細については、*AWS Lambda デベロッパーガイド*の「[Lambda のクォータ](https://docs.aws.amazon.com/lambda/latest/dg/limits.html)」を参照してください。
+ **行レベルのフィルタリング** – UDF では、Lake Formation の行レベルのフィルタリングはサポートされていません。
+ **ビュー** – UDF でビューを使用することはできません。
+ **既知の問題** – 既知の問題に関する最新のリストについては、GitHub の awslabs/aws-athena-query-federation セクションにある「[Limitations and Issues](https://github.com/awslabs/aws-athena-query-federation/wiki/Limitations_And_Issues)」(制限と問題) を参照してください。

# UDF クエリ構文を使用してクエリする
<a name="udf-query-syntax"></a>

`USING EXTERNAL FUNCTION` 句は、クエリで後続の `SELECT` ステートメントで参照できる UDF または複数の UDF を指定します。UDF のメソッド名と UDF をホストする Lambda 関数の名前が必要です。Lambda 関数名の代わりに、Lambda ARN を使用できます。クロスアカウントのシナリオでは、Lambda ARN が必要です。

## 概要
<a name="udf-synopsis"></a>

```
USING EXTERNAL FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...])
RETURNS data_type
LAMBDA 'lambda_function_name_or_ARN'
[, EXTERNAL FUNCTION UDF_name2(variable1 data_type[, variable2 data_type][,...]) 
RETURNS data_type 
LAMBDA 'lambda_function_name_or_ARN'[,...]]
SELECT  [...] UDF_name(expression) [, UDF_name2(expression)] [...]
```

## パラメータ
<a name="udf-parameters"></a>

**USING EXTERNAL FUNCTION *UDF\$1name*(*variable1* *data\$1type*[, *variable2* *data\$1type*][,...])**  
*UDF\$1name* は UDF の名前を指定します。この名前は、参照される Lambda 関数内の Java メソッドに対応している必要があります。各 *variable data\$1type* は、UDF が入力として受け入れる名前付きの変数とそれに対応するデータ型を指定します。*data\$1type* は、以下の表に記載されているサポート対象の Athena データ型の 1 つであり、対応する Java データ型にマップする必要があります。      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/udf-query-syntax.html)

**RETURNS *data\$1type***  
`data_type` は、UDF が出力として返す SQL データ型を指定します。上記の表にリストされている Athena データ型がサポートされます。`DECIMAL` データ型の場合、この構文 `RETURNS DECIMAL(precision, scale)` を使います。*精度*と*スケール*は整数です。

**LAMBDA '*lambda\$1function*'**  
*lambda\$1function* は、UDF の実行時に呼び出される Lambda 関数の名前を指定します。

**SELECT [...] *UDF\$1name*(*expression*) [...]**  
UDF に値を渡し、結果を返す `SELECT` クエリです。*UDF\$1Name* は使用する UDF を指定し、値を渡すために評価される *expression* がその後に続きます。渡される値と返される値は、`USING EXTERNAL FUNCTION` 句で UDF に指定された対応するデータ型と一致する必要があります。

### 例
<a name="udf-examples"></a>

GitHub にある [AthenaUDFHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/src/main/java/com/amazonaws/athena/connectors/udfs/AthenaUDFHandler.java) コードに基づいたクエリの例については、GitHub の「[Amazon Athena UDF connector](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-udfs)」(Amazon Athena UDF コネクタ) ページを参照してください。

# Lambda を利用して UDF を作成およびデプロイする
<a name="udf-creating-and-deploying"></a>

カスタム UDF を作成するには、`UserDefinedFunctionHandler` クラスを拡張して新しい Java クラスを作成します。SDK の [UserDefinedFunctionHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-federation-sdk/src/main/java/com/amazonaws/athena/connector/lambda/handlers/UserDefinedFunctionHandler.java) のソースコードは、GitHub の awslabs/aws-athena-query-federation/athena-federation-sdk [リポジトリ](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-federation-sdk)で入手できます。このコードには、検証および変更して UDF を作成するために使用できる [UDF 実装例](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-udfs)が付属しています。

このセクションの手順では、コマンドラインとデプロイから [Apache Maven](https://maven.apache.org/index.html) を使用してカスタム UDF Jar ファイルを記述し、構築する方法を示します。

Maven を使用して Athena のカスタム UDF を作成するには、次のステップを実行します。

1. [SDK のクローン作成と開発環境の準備](#udf-create-install-sdk-prep-environment)

1. [Maven プロジェクトの作成](#create-maven-project)

1. [Maven プロジェクトへの依存関係とプラグインの追加](#udf-add-maven-dependencies)

1. [UDF に Java コードを記述](#udf-write-java)

1. [JAR ファイルのビルド](#udf-create-package-jar)

1. [JAR を AWS Lambda にデプロイする](#udf-create-deploy)

## SDK のクローン作成と開発環境の準備
<a name="udf-create-install-sdk-prep-environment"></a>

始める前に、`sudo yum install git -y` を使用して git がシステムにインストールされていることを確認してください。

**AWS クエリフェデレーション SDK をインストールするには**
+ コマンドラインで次のコマンドを入力して、SDK リポジトリのクローンを作成します。このリポジトリには、SDK、例、データソースコネクタのスイートが含まれています。データソースコネクタの詳細については、「[Amazon Athena フェデレーティッドクエリを使用する](federated-queries.md)」を参照してください。

  ```
  git clone https://github.com/awslabs/aws-athena-query-federation.git
  ```

**この手順の前提条件をインストールする**

Apache Maven、AWS CLI、および AWS Serverless Application Model ビルドツールが既にインストールされている開発マシンで作業している場合は、このステップをスキップできます。

1. クローン作成時に作成した `aws-athena-query-federation` ディレクトリのルートから、開発環境を準備する [prepare\$1dev\$1env.sh](https://github.com/awslabs/aws-athena-query-federation/blob/master/tools/prepare_dev_env.sh) スクリプトを実行します。

1. インストールプロセスによって作成された新しい変数を調達するようにシェルを更新するか、ターミナルセッションを再起動します。

   ```
   source ~/.profile
   ```
**重要**  
このステップをスキップすると、後で AWS CLI または AWS SAM ビルドツールが Lambda 関数を公開できないというエラーが表示されます。

## Maven プロジェクトの作成
<a name="create-maven-project"></a>

次のコマンドを実行して、Maven プロジェクトを作成します。*groupId* を組織の一意の ID に置き換え、*my-athena-udf* をアプリケーション名に置き換えます。詳細については、Apache Maven ドキュメントの「[How do I make my first Maven project?](https://maven.apache.org/guides/getting-started/index.html#How_do_I_make_my_first_Maven_project)」を参照してください。

```
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=groupId \
-DartifactId=my-athena-udfs
```

## Maven プロジェクトへの依存関係とプラグインの追加
<a name="udf-add-maven-dependencies"></a>

Maven プロジェクト `pom.xml` ファイルに次の設定を追加します。例については、GitHub の [pom.xml](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/pom.xml) ファイルを参照してください。

```
<properties>
    <aws-athena-federation-sdk.version>2022.47.1</aws-athena-federation-sdk.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-athena-federation-sdk</artifactId>
        <version>${aws-athena-federation-sdk.version}</version>
    </dependency>
</dependencies>
    
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.1</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```

## UDF に Java コードを記述
<a name="udf-write-java"></a>

[UserDefinedFunctionHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-federation-sdk/src/main/java/com/amazonaws/athena/connector/lambda/handlers/UserDefinedFunctionHandler.java) を拡張して、新しいクラスを作成します。クラス内に UDF を記述します。

次の例では、UDF の 2 つの Java メソッド、`compress()` および `decompress()` がクラス `MyUserDefinedFunctions` 内に作成されます。

```
*package *com.mycompany.athena.udfs;

public class MyUserDefinedFunctions
        extends UserDefinedFunctionHandler
{
    private static final String SOURCE_TYPE = "MyCompany";

    public MyUserDefinedFunctions()
    {
        super(SOURCE_TYPE);
    }

    /**
     * Compresses a valid UTF-8 String using the zlib compression library.
     * Encodes bytes with Base64 encoding scheme.
     *
     * @param input the String to be compressed
     * @return the compressed String
     */
    public String compress(String input)
    {
        byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);

        // create compressor
        Deflater compressor = new Deflater();
        compressor.setInput(inputBytes);
        compressor.finish();

        // compress bytes to output stream
        byte[] buffer = new byte[4096];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length);
        while (!compressor.finished()) {
            int bytes = compressor.deflate(buffer);
            byteArrayOutputStream.write(buffer, 0, bytes);
        }

        try {
            byteArrayOutputStream.close();
        }
        catch (IOException e) {
            throw new RuntimeException("Failed to close ByteArrayOutputStream", e);
        }

        // return encoded string
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        return Base64.getEncoder().encodeToString(compressedBytes);
    }

    /**
     * Decompresses a valid String that has been compressed using the zlib compression library.
     * Decodes bytes with Base64 decoding scheme.
     *
     * @param input the String to be decompressed
     * @return the decompressed String
     */
    public String decompress(String input)
    {
        byte[] inputBytes = Base64.getDecoder().decode((input));

        // create decompressor
        Inflater decompressor = new Inflater();
        decompressor.setInput(inputBytes, 0, inputBytes.length);

        // decompress bytes to output stream
        byte[] buffer = new byte[4096];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length);
        try {
            while (!decompressor.finished()) {
                int bytes = decompressor.inflate(buffer);
                if (bytes == 0 && decompressor.needsInput()) {
                    throw new DataFormatException("Input is truncated");
                }
                byteArrayOutputStream.write(buffer, 0, bytes);
            }
        }
        catch (DataFormatException e) {
            throw new RuntimeException("Failed to decompress string", e);
        }

        try {
            byteArrayOutputStream.close();
        }
        catch (IOException e) {
            throw new RuntimeException("Failed to close ByteArrayOutputStream", e);
        }

        // return decoded string
        byte[] decompressedBytes = byteArrayOutputStream.toByteArray();
        return new String(decompressedBytes, StandardCharsets.UTF_8);
    }
}
```

## JAR ファイルのビルド
<a name="udf-create-package-jar"></a>

`mvn clean install` を実行して、プロジェクトをビルドします。正常にビルドされると、JAR ファイルが `target` という名前のプロジェクトの `artifactId-version.jar` フォルダに作成されます。ここで、*artifactId* は Maven プロジェクトで指定した名前（例: `my-athena-udfs`）です。

## JAR を AWS Lambda にデプロイする
<a name="udf-create-deploy"></a>

コードを Lambda にデプロイする、次の 2 つの方法があります。
+ AWS Serverless Application Repository を使用してデプロイする（推奨）
+ JAR ファイルから Lambda 関数を作成する

### オプション 1: AWS Serverless Application Repository にデプロイする
<a name="udf-create-deploy-sar"></a>

JAR ファイルを AWS Serverless Application Repository にデプロイするときは、アプリケーションのアーキテクチャを表す AWS SAM テンプレート YAML ファイルを作成します。次に、この YAML ファイルと、アプリケーションのアーティファクトがアップロードされて AWS Serverless Application Repository に対して利用可能になる Simple Storage Service (Amazon S3) バケットを指定します。以下の手順では、先ほどクローンした Athena Query Federation SDK の `athena-query-federation/tools` ディレクトリにある [publish.sh](https://github.com/awslabs/aws-athena-query-federation/blob/master/tools/publish.sh) スクリプトを使用します。

詳細と要件については、「AWS Serverless Application Repository デベロッパーガイド」の「[アプリケーションの公開](https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-publishing-applications.html)」、「AWS Serverless Application Model デベロッパーガイド」の「[AWS SAM テンプレートの概念](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html)」、および「[AWS SAM CLI を使用してサーバーレスアプリケーションを公開する](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-publishing-applications.html)」を参照してください。

次の例は、YAML ファイルのパラメータを示しています。同様のパラメータを YAML ファイルに追加し、プロジェクトディレクトリに保存します。完全な例については、GitHub の [athena-udf.yaml](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/athena-udfs.yaml) を参照してください。

```
Transform: 'AWS::Serverless-2016-10-31'
Metadata:
  'AWS::ServerlessRepo::Application':
    Name: MyApplicationName
    Description: 'The description I write for my application'
    Author: 'Author Name'
    Labels:
      - athena-federation
    SemanticVersion: 1.0.0
Parameters:
  LambdaFunctionName:
    Description: 'The name of the Lambda function that will contain your UDFs.'
    Type: String
  LambdaTimeout:
    Description: 'Maximum Lambda invocation runtime in seconds. (min 1 - 900 max)'
    Default: 900
    Type: Number
  LambdaMemory:
    Description: 'Lambda memory in MB (min 128 - 3008 max).'
    Default: 3008
    Type: Number
Resources:
  ConnectorConfig:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Handler: "full.path.to.your.handler. For example, com.amazonaws.athena.connectors.udfs.MyUDFHandler"
      CodeUri: "Relative path to your JAR file. For example, ./target/athena-udfs-1.0.jar"
      Description: "My description of the UDFs that this Lambda function enables."
      Runtime: java8
      Timeout: !Ref LambdaTimeout
      MemorySize: !Ref LambdaMemory
```

YAML ファイルを保存したプロジェクトディレクトリに `publish.sh` スクリプトをコピーし、次のコマンドを実行します。

```
./publish.sh MyS3Location MyYamlFile
```

たとえば、バケットの場所が `s3://amzn-s3-demo-bucket/mysarapps/athenaudf` で、YAML ファイルが `my-athena-udfs.yaml` として保存された場合:

```
./publish.sh amzn-s3-demo-bucket/mysarapps/athenaudf my-athena-udfs
```

**Lambda 関数を作成するには**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) で Lambda コンソールを開いて [**Create function**] (関数の作成) をクリックし、[**Browse serverless app repository**] (Serverless Application Repository の参照) を選択します。

1. [**プライベートアプリケーション**] を選択し、リストでアプリケーションを見つけるか、キーワードを使用してアプリケーションを検索して選択します。

1. アプリケーションの詳細を確認して指定し、[**デプロイ**] を選択します。

   これで、Lambda 関数の JAR ファイルで定義されたメソッド名を Athena で UDF として使用できるようになりました。

### オプション 2: Lambda 関数を直接作成する
<a name="udf-create-deploy-lambda"></a>

コンソールまたは AWS CLI を使用して、Lambda 関数を直接作成することもできます。以下の例は、Lambda `create-function` CLI コマンドを使用する方法を示しています。

```
aws lambda create-function \
 --function-name MyLambdaFunctionName \
 --runtime java8 \
 --role arn:aws:iam::1234567890123:role/my_lambda_role \
 --handler com.mycompany.athena.udfs.MyUserDefinedFunctions \
 --timeout 900 \
 --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar
```

# リージョン全体でクエリする
<a name="querying-across-regions"></a>

Athena は、Athena を使用しているリージョンとは異なる AWS リージョン で Simple Storage Service (Amazon S3) データをクエリする機能をサポートしています。データを移動するのが実用的でない場合や許可されない場合、あるいは複数のリージョンにわたってデータをクエリする場合には、必要に応じてリージョン間のクエリを実行できます。特定のリージョンで Athena を使用できない場合でも、Athena を使用できる別のリージョンからそのリージョンのデータをクエリできます。

Simple Storage Service (Amazon S3) データが自分のアカウントに属していない場合でも、リージョン内のデータをクエリするためには、そのリージョンで自分のアカウントを有効にする必要があります。米国東部 (オハイオ) など一部のリージョンでは、アカウントの作成時にリージョンへのアクセスが自動的に有効になります。そうでないリージョンでは、リージョンを使用する前に、アカウントをリージョンに「オプトイン」する必要があります。オプトインを必要とするリージョンのリストについては、「Amazon EC2 ユーザーガイド」の「[利用できるリージョン](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions)」を参照してください。リージョンへのオプトインに関する具体的な手順については、「Amazon Web Services 全般のリファレンス」の「[AWS リージョンの管理](https://docs.aws.amazon.com/general/latest/gr/rande-manage.html)」を参照してください。

## 考慮事項と制限事項
<a name="querying-across-regions-considerations-and-limitations"></a>
+ **データアクセス許可** – リージョン間で Athena から Simple Storage Service (Amazon S3) データを正常にクエリするには、アカウントにデータを読み取る許可が必要です。クエリするデータが別のアカウントに属している場合は、目的のデータが含まれている Simple Storage Service (Amazon S3) ロケーションへのアクセス権をそのアカウントから付与してもらう必要があります。
+ **データ転送料金** – リージョン間のクエリには、Amazon S3 データ転送料金が適用されます。クエリを実行すると、データセットのサイズよりも多くのデータが転送される可能性があります。データのサブセットに対してクエリをテストし、[AWS Cost Explorer](https://aws.amazon.com/aws-cost-management/aws-cost-explorer/) でコストを確認することから始めることをお勧めします。
+ **AWS Glue** – リージョン間で AWS Glue を使用できます。リージョン間の AWS Glue トラフィックには、追加料金が適用される場合があります。詳細については、「AWS ビッグデータブログ」の[「クロスアカウントおよびリージョン間の AWS Glue 接続の作成」](https://aws.amazon.com/blogs/big-data/create-cross-account-and-cross-region-aws-glue-connections/)を参照してください。
+ **Simple Storage Service (Amazon S3) 暗号化オプション** – リージョン間のクエリでは、SSE-S3 と SSE-KMS の暗号化オプションはサポートされていますが、CSE-KMS はサポートされていません。詳細については、「[サポートされる Amazon S3 の暗号化オプション](encryption.md#encryption-options-S3-and-Athena)」を参照してください。
+ **[フェデレーティッドクエリ]** — 複数 AWS リージョン にわたる統合クエリの使用はサポートされていません。

上記の条件が満たされていれば、指定した `LOCATION` 値を指す Athena テーブルを作成し、データを透過的にクエリできます。特別な構文は不要です。Athena テーブル作成の詳細については、「[Athena でテーブルを作成する](creating-tables.md)」を参照してください。

# AWS Glue Data Catalog をクエリする
<a name="querying-glue-catalog"></a>

AWS Glue Data Catalog は多くの AWS のサービス で中央メタデータリポジトリとして使用されるため、データカタログメタデータのクエリが必要になる場合があります。これを実行するには、Athena で SQL クエリを使用できます。Athena を使用して、データベース、テーブル、パーティション、および列などの AWS Glue カタログメタデータをクエリできます。

AWS Glue カタログのメタデータを取得するには、Athena バックエンドで `information_schema` データベースをクエリします。このトピックのクエリ例は、一般的なユースケースのために Athena を使用して AWS Glue カタログメタデータをクエリする方法を示しています。

## 考慮事項と制限事項
<a name="querying-glue-catalog-considerations-limitations"></a>
+ `information_schema` データベースをクエリする代わりに、個別の Apache Hive [DDL コマンド](ddl-reference.md)を使用して、Athena から特定のデータベース、テーブル、ビュー、パーティション、および列のメタデータ情報を抽出することができます。ただし、出力は表形式になりません。
+ `information_schema` のクエリのパフォーマンスは、AWS Glue メタデータの量が少ない、または中程度である場合に最も高くなります。大量のメタデータがある場合は、エラーが発生する可能性があります。
+ `CREATE VIEW` を使用して `information_schema` データベース上にビューを作成することはできません。

**Topics**
+ [考慮事項と制限事項](#querying-glue-catalog-considerations-limitations)
+ [データベースを一覧表示し、指定したデータベースを検索する](querying-glue-catalog-querying-available-databases-including-rdbms.md)
+ [指定したデータベース内のテーブルを一覧表示し、名前でテーブルを検索する](querying-glue-catalog-listing-tables.md)
+ [特定のテーブルのパーティションを一覧表示する](querying-glue-catalog-listing-partitions.md)
+ [指定したテーブルまたはビューの列を一覧表示または検索する](querying-glue-catalog-listing-columns.md)
+ [特定のテーブルに共通する列を一覧表示する](querying-glue-catalog-listing-columns-in-common.md)
+ [全テーブルのすべての列を一覧表示する](querying-glue-catalog-listing-all-columns-for-all-tables.md)

# データベースを一覧表示し、指定したデータベースを検索する
<a name="querying-glue-catalog-querying-available-databases-including-rdbms"></a>

このセクションの例では、メタデータ内のデータベースをスキーマ名別にリストする方法を示します。

**Example – データベースのリスト化**  
次のクエリ例は、`information_schema.schemata` テーブルのデータベースを一覧表示します。  

```
SELECT schema_name
FROM   information_schema.schemata
LIMIT  10;
```
次の表に項目の例を示します。  


****  

|  |  | 
| --- |--- |
| 6 | alb-databas1 | 
| 7 | alb\$1original\$1cust | 
| 8 | alblogsdatabase | 
| 9 | athena\$1db\$1test | 
| 10 | athena\$1ddl\$1db | 

**Example – 指定したデータベースの検索**  
次のクエリの例では、`rdspostgresql` はサンプルデータベースです。  

```
SELECT schema_name
FROM   information_schema.schemata
WHERE  schema_name = 'rdspostgresql'
```
次の表に項目の例を示します。  


****  

|  | schema\$1name | 
| --- | --- | 
| 1 | rdspostgresql | 

# 指定したデータベース内のテーブルを一覧表示し、名前でテーブルを検索する
<a name="querying-glue-catalog-listing-tables"></a>

テーブルのメタデータを一覧表示するには、テーブルスキーマまたはテーブル名でクエリを実行します。

**Example – テーブルのスキーマ別のリスト化**  
次のクエリは、`rdspostgresql` テーブルスキーマを使用するテーブルを一覧表示します。  

```
SELECT table_schema,
       table_name,
       table_type
FROM   information_schema.tables
WHERE  table_schema = 'rdspostgresql'
```
次の表は、サンプル結果を示しています。  


****  

|  | table\$1schema | table\$1name | table\$1type | 
| --- | --- | --- | --- | 
| 1 | rdspostgresql | rdspostgresqldb1\$1public\$1account | BASE TABLE | 

**Example – 名前によるテーブルの検索**  
次のクエリは、テーブル `athena1` のメタデータ情報を取得します。  

```
SELECT table_schema,
       table_name,
       table_type
FROM   information_schema.tables
WHERE  table_name = 'athena1'
```
次の表は、サンプル結果を示しています。  


****  

|  | table\$1schema | table\$1name | table\$1type | 
| --- | --- | --- | --- | 
| 1 | default | athena1 | BASE TABLE | 

# 特定のテーブルのパーティションを一覧表示する
<a name="querying-glue-catalog-listing-partitions"></a>

次の例のように、`SHOW PARTITIONS table_name` を使用して、指定したテーブルのパーティションをリスト化できます。

```
SHOW PARTITIONS cloudtrail_logs_test2
```

`$partitions` メタデータクエリを使用して、特定のテーブルのパーティション番号とパーティション値を一覧表示することもできます。

**Example — \$1partitions 構文を使用したテーブルのパーティションのクエリ**  
以下のクエリの例では、`$partitions` 構文を使用して、テーブル `cloudtrail_logs_test2` のパーティションを一覧表示します。  

```
SELECT * FROM default."cloudtrail_logs_test2$partitions" ORDER BY partition_number
```
次の表に項目の例を示します。  


****  

|  | table\$1catalog | table\$1schema | table\$1name | 年 | 月 | 日 | 
| --- | --- | --- | --- | --- | --- | --- | 
| 1 | awsdatacatalog | デフォルト | cloudtrail\$1logs\$1test2 | 2020 | 08 | 10 | 
| 2 | awsdatacatalog | デフォルト | cloudtrail\$1logs\$1test2 | 2020 | 08 | 11 | 
| 3 | awsdatacatalog | デフォルト | cloudtrail\$1logs\$1test2 | 2020 | 08 | 12 | 

# 指定したテーブルまたはビューの列を一覧表示または検索する
<a name="querying-glue-catalog-listing-columns"></a>

指定したデータベースとテーブルで、テーブルのすべての列、ビューのすべての列を一覧表示したり、名前で列を検索したりできます。

列を一覧表示するには、`SELECT *` クエリを使用します。`FROM` 句で、`information_schema.columns` を指定します。`WHERE` 句で、`table_schema='database_name'` を使用してデータベースを指定し、`table_name = 'table_name'` を使用して一覧表示する列を含むテーブルまたはビューを指定します。

**Example – 指定したテーブルのすべての列のリスト化**  
次のクエリ例は、テーブル `rdspostgresqldb1_public_account` のすべての列を一覧表示します。  

```
SELECT *
FROM   information_schema.columns
WHERE  table_schema = 'rdspostgresql'
       AND table_name = 'rdspostgresqldb1_public_account'
```
次の表に項目の例を示します。  


****  

|  | table\$1catalog | table\$1schema | table\$1name | column\$1name | ordinal\$1position | column\$1default | is\$1nullable | data\$1type | コメント | extra\$1info | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 1 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | password | 1 |  | はい | varchar |  |  | 
| 2 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | user\$1id | 2 |  | はい | integer |  |  | 
| 3 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | created\$1on | 3 |  | はい | timestamp |  |  | 
| 4 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | last\$1login | 4 |  | はい | timestamp |  |  | 
| 5 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | email | 5 |  | はい | varchar |  |  | 
| 6 | awsdatacatalog | rdspostgresql | rdspostgresqldb1\$1public\$1account | username | 6 |  | はい | varchar |  |  | 

**Example – 指定したビューの列のリスト化**  
次のクエリ例は、ビュー `default` の `arrayview` データベース内のすべての列を一覧表示します。  

```
SELECT *
FROM   information_schema.columns
WHERE  table_schema = 'default'
       AND table_name = 'arrayview'
```
次の表に項目の例を示します。  


****  

|  | table\$1catalog | table\$1schema | table\$1name | column\$1name | ordinal\$1position | column\$1default | is\$1nullable | data\$1type | コメント | extra\$1info | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 1 | awsdatacatalog | デフォルト | arrayview | searchdate | 1 |  | はい | varchar |  |  | 
| 2 | awsdatacatalog | デフォルト | arrayview | sid | 2 |  | はい | varchar |  |  | 
| 3 | awsdatacatalog | デフォルト | arrayview | btid | 3 |  | はい | varchar |  |  | 
| 4 | awsdatacatalog | デフォルト | arrayview | p | 4 |  | はい | varchar |  |  | 
| 5 | awsdatacatalog | デフォルト | arrayview | infantprice | 5 |  | はい | varchar |  |  | 
| 6 | awsdatacatalog | デフォルト | arrayview | sump | 6 |  | はい | varchar |  |  | 
| 7 | awsdatacatalog | デフォルト | arrayview | journeymaparray | 7 |  | はい | array(varchar) |  |  | 

**Example – 指定したデータベースとテーブルでの名前による列の検索**  
次のクエリ例は、`sid` データベースの `arrayview` ビューで `default` 列のメタデータを検索します。  

```
SELECT *
FROM   information_schema.columns
WHERE  table_schema = 'default'
       AND table_name = 'arrayview' 
       AND column_name='sid'
```
次の表は、サンプル結果を示しています。  


****  

|  | table\$1catalog | table\$1schema | table\$1name | column\$1name | ordinal\$1position | column\$1default | is\$1nullable | data\$1type | コメント | extra\$1info | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 1 | awsdatacatalog | デフォルト | arrayview | sid | 2 |  | はい | varchar |  |  | 

# 特定のテーブルに共通する列を一覧表示する
<a name="querying-glue-catalog-listing-columns-in-common"></a>

データベース内の特定のテーブルに共通する列を一覧表示できます。
+ `SELECT column_name FROM information_schema.columns` 構文を使用してください。
+ `WHERE` 句には、以下の構文 `WHERE table_name IN ('table1', 'table2')` を使用します。

**Example — 同じデータベース内の 2 つのテーブルに共通する列を一覧表示する**  
次のクエリ例では、テーブル `table1` と `table2` に共通する列を一覧表示しています。  

```
SELECT column_name
FROM information_schema.columns
WHERE table_name IN ('table1', 'table2')
GROUP BY column_name
HAVING COUNT(*) > 1;
```

# 全テーブルのすべての列を一覧表示する
<a name="querying-glue-catalog-listing-all-columns-for-all-tables"></a>

`AwsDataCatalog` にある全テーブル、あるいは `AwsDataCatalog` にある特定のデータベース内の全テーブルで、すべての列を一覧表示できます。
+ `AwsDataCatalog` にある全データベースのすべての列を一覧表示するには、クエリ `SELECT * FROM information_schema.columns` を使用します。
+ 結果を特定のデータベースに制限するには、`WHERE` 句で `table_schema='database_name'` を使用します。

**Example — 特定のデータベース内の全テーブルですべての列を一覧表示する**  
次のクエリ例では、データベース `webdata` にある全テーブルのすべての列を一覧表示します。  

```
SELECT * FROM information_schema.columns WHERE table_schema = 'webdata'            
```

# AWS のサービス ログをクエリする
<a name="querying-aws-service-logs"></a>

このセクションでは、Amazon Athena を使用して一般的なデータセット (AWS CloudTrail ログ、Amazon CloudFront ログ、Classic Load Balancer ログ、Application Load Balancer ログ、Amazon VPC フローログ、Network Load Balancer ログなど) をクエリするための手順をいくつか紹介します。

このセクションのタスクでは Athena コンソールを使用しますが、[Athena JDBC ドライバー](connect-with-jdbc.md)、[AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/athena/)、または [Amazon Athena API リファレンス](https://docs.aws.amazon.com/athena/latest/APIReference/)などの他のツールを使うこともできます。

Athena での AWS CloudFormation を使用した AWS のサービス のログのテーブル、パーティション、およびクエリ例の自動作成については、AWS Big Dataブログの「[Amazon Athena でのAWS のサービス ログのテーブル作成とクエリの自動化](https://aws.amazon.com/blogs/big-data/automating-aws-service-logs-table-creation-and-querying-them-with-amazon-athena/)」を参照してください。AWS Glue 用の Python ライブラリを使用して、AWS のサービス のログを処理し、Athena でクエリを実行するための共通のフレームワークを作成する方法については、「[Amazon Athena を使用して AWS のサービス のログに対するクエリを簡単に実行する](https://aws.amazon.com/blogs/big-data/easily-query-aws-service-logs-using-amazon-athena/)」を参照してください。

このセクションのトピックでは、Athena と、クエリするデータがが格納される Amazon S3 バケットにアクセスするための適切なアクセス許可が設定済みであることを前提としています。詳細については、[設定、管理、プログラムによるアクセス](setting-up.md)および[はじめに](getting-started.md)を参照してください。

**Topics**
+ [Application Load Balancer](application-load-balancer-logs.md)
+ [エラスティックロードバランシング](elasticloadbalancer-classic-logs.md)
+ [CloudFront](cloudfront-logs.md)
+ [CloudTrail](cloudtrail-logs.md)
+ [Amazon EMR](emr-logs.md)
+ [Global Accelerator](querying-global-accelerator-flow-logs.md)
+ [GuardDuty](querying-guardduty.md)
+ [Network Firewall](querying-network-firewall-logs.md)
+ [Network Load Balancer](networkloadbalancer-classic-logs.md)
+ [Route 53](querying-r53-resolver-logs.md)
+ [Amazon SES](querying-ses-logs.md)
+ [Amazon VPC](vpc-flow-logs.md)
+ [AWS WAF](waf-logs.md)

# Application Load Balancer ログをクエリする
<a name="application-load-balancer-logs"></a>

Application Load Balancer は、Elastic Load Balancing の負荷分散オプションであり、コンテナを使用したマイクロサービスのデプロイメントでのトラフィックの分散を可能にします。Application Load Balancer のログをクエリすることで、トラフィックの送信元、レイテンシー、Elastic Load Balancing インスタンスとバックエンドアプリケーションとの間で転送されるバイト数を確認できます。詳細については、「*Application Load Balancer ユーザーガイド*」の「[Access logs for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html)」と「[Connection logs for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html)」を参照してください。

## 前提条件
<a name="application-load-balancer-logs-prerequisites"></a>
+ [アクセスログ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html)または[接続ログ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html) を有効にして、Application Load Balancer ログを Amazon S3 バケットに保存できるようにします。
+ Athena 用に作成するテーブルを保存するデータベース。データベースを作成するには、Athena または AWS Glue コンソールを使用します。詳細については、本ガイドの「[Athena でデータベースを作成する](creating-databases.md)」または「*AWS Glue デベロッパーガイド*」の「[AWS Glue コンソールでのデータベースの操作](https://docs.aws.amazon.com/glue/latest/dg/console-databases.html)」を参照してください。

**Topics**
+ [前提条件](#application-load-balancer-logs-prerequisites)
+ [ALB アクセスログ用のテーブルを作成する](create-alb-access-logs-table.md)
+ [パーティション射影を使用して Athena で ALB アクセスログ用テーブルを作成する](create-alb-access-logs-table-partition-projection.md)
+ [ALB アクセスログのクエリ例](query-alb-access-logs-examples.md)
+ [ALB 接続ログ用テーブルを作成する](create-alb-connection-logs-table.md)
+ [パーティション射影を使用して Athena で ALB 接続ログ用テーブルを作成する](create-alb-connection-logs-table-partition-projection.md)
+ [ALB 接続ログのクエリ例](query-alb-connection-logs-examples.md)
+ [その他のリソース](application-load-balancer-logs-additional-resources.md)

# ALB アクセスログ用のテーブルを作成する
<a name="create-alb-access-logs-table"></a>

1. 次の `CREATE TABLE` ステートメントをコピーして Athena コンソールのクエリエディタに貼り付け、必要に応じて独自のログエントリ要件に合わせて変更します。Athena コンソールを開始する方法については、「[はじめに](getting-started.md)」を参照してください。`LOCATION` 句内のパスを Amazon S3 アクセスログフォルダの場所に置き換えます。アクセスログファイルの場所に関する詳細については、「*Application Load Balancer ユーザーガイド*」の「[アクセスログファイル](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-file-format)」を参照してください。

   各フィールドについては、「*Application Load Balancer のユーザーガイド*」の「[アクセスログのエントリ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format)」を参照してください。
**注記**  
次の `CREATE TABLE` ステートメントには、最近追加された `classification` 列、`classification_reason` 列、および `conn_trace_id` 列 (「traceability ID」または「TID」) が含まれています。これらのエントリを含まないApplication Load Balancer アクセスログのテーブルを作成するには、`CREATE TABLE` ステートメントから対応する列を削除し、それに応じて正規表現を変更します。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
               type string,
               time string,
               elb string,
               client_ip string,
               client_port int,
               target_ip string,
               target_port int,
               request_processing_time double,
               target_processing_time double,
               response_processing_time double,
               elb_status_code int,
               target_status_code string,
               received_bytes bigint,
               sent_bytes bigint,
               request_verb string,
               request_url string,
               request_proto string,
               user_agent string,
               ssl_cipher string,
               ssl_protocol string,
               target_group_arn string,
               trace_id string,
               domain_name string,
               chosen_cert_arn string,
               matched_rule_priority string,
               request_creation_time string,
               actions_executed string,
               redirect_url string,
               lambda_error_reason string,
               target_port_list string,
               target_status_code_list string,
               classification string,
               classification_reason string,
               conn_trace_id string
               )
               ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
               WITH SERDEPROPERTIES (
               'serialization.format' = '1',
               'input.regex' = 
           '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\\s]+?)\" \"([^\\s]+)\" \"([^ ]*)\" \"([^ ]*)\" ?([^ ]*)? ?( .*)?'
               )
               LOCATION 's3://amzn-s3-demo-bucket/access-log-folder-path/'
   ```
**注記**  
新しい ALB ログフィールドが追加された場合に備えて、将来のログエントリを処理できるように、`input.regex` パラメータの末尾に *`?( .*)?`* パターンを必ず残しておくことをお勧めします。

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `alb_access_logs` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

# パーティション射影を使用して Athena で ALB アクセスログ用テーブルを作成する
<a name="create-alb-access-logs-table-partition-projection"></a>

ALB アクセスログにはパーティションスキームを事前に指定できる既知の構造があるため、Athena のパーティション射影機能を使用することで、クエリの実行時間を短縮し、パーティション管理を自動化することが可能です。新しいデータが追加されると、パーティション射影は新しいパーティションを自動で追加します。このため、`ALTER TABLE ADD PARTITION` を使用してパーティションを手動で追加する必要がなくなります。

以下の `CREATE TABLE` ステートメント例は、単一の AWS リージョンの指定された日付から現在までの ALB アクセスログに、パーティション射影を自動的に使用します。ステートメントは、前のセクションの例に基づいていますが、`PARTITIONED BY` 句および `TBLPROPERTIES` 句を追加して、パーティション射影を有効にしています。`LOCATION` 句および `storage.location.template` 句では、プレースホルダーを ALB アクセスログの Amazon S3 バケットの場所を特定する値に置き換えます。アクセスログファイルの場所に関する詳細については、「*Application Load Balancer ユーザーガイド*」の「[アクセスログファイル](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-file-format)」を参照してください。`projection.day.range` では、*2022*/*01*/*01* を使用を開始する日に置き換えます。クエリが正常に実行されると、テーブルをクエリできます。パーティションをロードするのに、`ALTER TABLE ADD PARTITION` を実行する必要はありません。ログファイルの各フィールドに関する詳細については、「[アクセスログのエントリ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format)」を参照してください。

```
CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
            type string,
            time string,
            elb string,
            client_ip string,
            client_port int,
            target_ip string,
            target_port int,
            request_processing_time double,
            target_processing_time double,
            response_processing_time double,
            elb_status_code int,
            target_status_code string,
            received_bytes bigint,
            sent_bytes bigint,
            request_verb string,
            request_url string,
            request_proto string,
            user_agent string,
            ssl_cipher string,
            ssl_protocol string,
            target_group_arn string,
            trace_id string,
            domain_name string,
            chosen_cert_arn string,
            matched_rule_priority string,
            request_creation_time string,
            actions_executed string,
            redirect_url string,
            lambda_error_reason string,
            target_port_list string,
            target_status_code_list string,
            classification string,
            classification_reason string,
            conn_trace_id string
            )
            PARTITIONED BY
            (
             day STRING
            )
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' = 
        '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\\s]+?)\" \"([^\\s]+)\" \"([^ ]*)\" \"([^ ]*)\" ?([^ ]*)? ?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/'
            TBLPROPERTIES
            (
             "projection.enabled" = "true",
             "projection.day.type" = "date",
             "projection.day.range" = "2022/01/01,NOW",
             "projection.day.format" = "yyyy/MM/dd",
             "projection.day.interval" = "1",
             "projection.day.interval.unit" = "DAYS",
             "storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/${day}"
            )
```

パーティション射影の詳細については、「[Amazon Athena でパーティション射影を使用する](partition-projection.md)」を参照してください。

**注記**  
新しい ALB ログフィールドが追加された場合に備えて、将来のログエントリを処理できるように、`input.regex` パラメータの末尾に *?( .\$1)?* パターンを必ず残しておくことをお勧めします。

# ALB アクセスログのクエリ例
<a name="query-alb-access-logs-examples"></a>

次のクエリでは、ロードバランサーで受信し、クライアント IP アドレス別にグループ分けした HTTP GET リクエストの数をカウントします。

```
SELECT COUNT(request_verb) AS
 count,
 request_verb,
 client_ip
FROM alb_access_logs
GROUP BY request_verb, client_ip
LIMIT 100;
```

別のクエリでは、Safari ブラウザのユーザーがアクセスした URL を表示します。

```
SELECT request_url
FROM alb_access_logs
WHERE user_agent LIKE '%Safari%'
LIMIT 10;
```

次のクエリでは、ELB ステータスコードの値が 500 以上であるレコードが表示されます。

```
SELECT * FROM alb_access_logs
WHERE elb_status_code >= 500
```

次の例は、`datetime` でログを解析する方法を示しています。

```
SELECT client_ip, sum(received_bytes) 
FROM alb_access_logs
WHERE parse_datetime(time,'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z') 
     BETWEEN parse_datetime('2018-05-30-12:00:00','yyyy-MM-dd-HH:mm:ss') 
     AND parse_datetime('2018-05-31-00:00:00','yyyy-MM-dd-HH:mm:ss') 
GROUP BY client_ip;
```

次のクエリは、指定された日からのすべての ALB アクセスログに対してパーティション射影を使用するテーブルをクエリします。

```
SELECT * 
FROM alb_access_logs 
WHERE day = '2022/02/12'
```

# ALB 接続ログ用テーブルを作成する
<a name="create-alb-connection-logs-table"></a>

1. 次の `CREATE TABLE` サンプルステートメントをコピーして Athena コンソールのクエリエディタに貼り付け、必要に応じて独自のログエントリ要件に合わせて変更します。Athena コンソールを開始する方法については、「[はじめに](getting-started.md)」を参照してください。`LOCATION` 句内のパスを Amazon S3 接続ログフォルダの場所に置き換えます。接続ログファイルの場所に関する詳細については、「*Application Load Balancer ユーザーガイド*」の「[接続ログファイル](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-file-format)」を参照してください。ログファイルの各フィールドに関する詳細については、「[接続ログエントリ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-entry-format)」を参照してください。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS alb_connection_logs (
            time string,
            client_ip string,
            client_port int,
            listener_port int,
            tls_protocol string,
            tls_cipher string,
            tls_handshake_latency double,
            leaf_client_cert_subject string,
            leaf_client_cert_validity string,
            leaf_client_cert_serial_number string,
            tls_verify_status string,
            conn_trace_id string
            ) 
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' =
             '([^ ]*) ([^ ]*) ([0-9]*) ([0-9]*) ([A-Za-z0-9.-]*) ([^ ]*) ([-.0-9]*) \"([^\"]*)\" ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/connection-log-folder-path/'
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `alb_connection_logs` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

# パーティション射影を使用して Athena で ALB 接続ログ用テーブルを作成する
<a name="create-alb-connection-logs-table-partition-projection"></a>

ALB 接続ログにはパーティションスキームを事前に指定できる既知の構造があるため、Athena のパーティション射影機能を使用することで、クエリの実行時間を短縮し、パーティション管理を自動化することが可能です。新しいデータが追加されると、パーティション射影は新しいパーティションを自動で追加します。このため、`ALTER TABLE ADD PARTITION` を使用してパーティションを手動で追加する必要がなくなります。

以下の `CREATE TABLE` ステートメント例は、単一の AWS リージョンの指定された日付から現在までの ALB 接続ログに、パーティション射影を自動的に使用します。ステートメントは、前のセクションの例に基づいていますが、`PARTITIONED BY` 句および `TBLPROPERTIES` 句を追加して、パーティション射影を有効にしています。`LOCATION` 句および `storage.location.template` 句では、プレースホルダーを ALB 接続ログの Amazon S3 バケットの場所を特定する値に置き換えます。接続ログファイルの場所に関する詳細については、「Application Load Balancer ユーザーガイド」の「[接続ログファイル](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-file-format)」を参照してください。`projection.day.range` では、*2023*/*01*/*01* を使用したい開始日に置き換えます。クエリが正常に実行されると、テーブルをクエリできます。パーティションをロードするのに、`ALTER TABLE ADD PARTITION` を実行する必要はありません。ログファイルの各フィールドに関する詳細については、「[接続ログエントリ](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-entry-format)」を参照してください。

```
CREATE EXTERNAL TABLE IF NOT EXISTS alb_connection_logs (
         time string,
         client_ip string,
         client_port int,
         listener_port int,
         tls_protocol string,
         tls_cipher string,
         tls_handshake_latency double,
         leaf_client_cert_subject string,
         leaf_client_cert_validity string,
         leaf_client_cert_serial_number string,
         tls_verify_status string,
         conn_trace_id string
         )
            PARTITIONED BY
            (
             day STRING
            )
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' =
             '([^ ]*) ([^ ]*) ([0-9]*) ([0-9]*) ([A-Za-z0-9.-]*) ([^ ]*) ([-.0-9]*) \"([^\"]*)\" ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/'
            TBLPROPERTIES
            (
             "projection.enabled" = "true",
             "projection.day.type" = "date",
             "projection.day.range" = "2023/01/01,NOW",
             "projection.day.format" = "yyyy/MM/dd",
             "projection.day.interval" = "1",
             "projection.day.interval.unit" = "DAYS",
             "storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/${day}"
            )
```

パーティション射影の詳細については、「[Amazon Athena でパーティション射影を使用する](partition-projection.md)」を参照してください。

# ALB 接続ログのクエリ例
<a name="query-alb-connection-logs-examples"></a>

以下のクエリは、`tls_verify_status` の値が `'Success'` ではなかったオカレンスの数をカウントし、クライアント IP アドレスごとにグループ化します。

```
SELECT DISTINCT client_ip, count() AS count FROM alb_connection_logs
WHERE tls_verify_status != 'Success'
GROUP BY client_ip
ORDER BY count() DESC;
```

以下のクエリは、指定された時間範囲内で `tls_handshake_latency` の値が 2 秒を超えたオカレンスを検索します。

```
SELECT * FROM alb_connection_logs
WHERE 
  (
    parse_datetime(time, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z') 
    BETWEEN 
    parse_datetime('2024-01-01-00:00:00', 'yyyy-MM-dd-HH:mm:ss') 
    AND 
    parse_datetime('2024-03-20-00:00:00', 'yyyy-MM-dd-HH:mm:ss') 
  ) 
  AND 
    (tls_handshake_latency >= 2.0);
```

# その他のリソース
<a name="application-load-balancer-logs-additional-resources"></a>

ALB ログの使用に関する詳細については、次のリソースを参照してください。
+ 「*AWS ナレッジセンター*」の「[Amazon Athena で Application Load Balancer のアクセスログを分析する方法を教えてください](https://repost.aws/knowledge-center/athena-analyze-access-logs)」。
+ Elastic Load Balancing における HTTP ステータスコードについては、「*Application Load Balancer ユーザーガイド*」の「[Application Load Balancer のトラブルシューティング](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html)」を参照してください。
+ 「*AWS Big Data Blog*」の「[Catalog and analyze Application Load Balancer logs more efficiently with AWS Glue custom classifiers and Amazon Athena](https://aws.amazon.com/blogs/big-data/catalog-and-analyze-application-load-balancer-logs-more-efficiently-with-aws-glue-custom-classifiers-and-amazon-athena/)」。

# Classic Load Balancer ログをクエリする
<a name="elasticloadbalancer-classic-logs"></a>

Classic Load Balancer ログを使用して、Elastic Load Balancing インスタンスおよびバックエンドアプリケーションとの間で送受信されるトラフィックパターンを分析して理解します。トラフィックの送信元、レイテンシー、および転送されたバイト数を確認できます。

Elastic Load Balancing ログを分析する前に、宛先の Amazon S3 バケットでの保存用にそれらを設定します。詳細については、「[Classic Load Balancer のアクセスログの有効化](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html)」を参照してください。

**Elastic Load Balancing ログのテーブルを作成する**

1. 以下の DDL ステートメントをコピーして Athena コンソール内に貼り付けます。Elastic Load Balancing ログレコードの[構文](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html#access-log-entry-format)をチェックします。以下のクエリを更新して、最新バージョンのレコードのための列と Regex 構文を含めることが必要になる場合があります。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS elb_logs (
    
    timestamp string,
    elb_name string,
    request_ip string,
    request_port int,
    backend_ip string,
    backend_port int,
    request_processing_time double,
    backend_processing_time double,
    client_response_time double,
    elb_response_code string,
    backend_response_code string,
    received_bytes bigint,
    sent_bytes bigint,
    request_verb string,
    url string,
    protocol string,
    user_agent string,
    ssl_cipher string,
    ssl_protocol string
   )
   ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
   WITH SERDEPROPERTIES (
    'serialization.format' = '1',
    'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (\"[^\"]*\") ([A-Z0-9-]+) ([A-Za-z0-9.-]*)$'
   )
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/AWS_account_ID/elasticloadbalancing/';
   ```

1. `LOCATION` Amazon S3 バケットを変更して、Elastic Load Balancing ログの宛先を指定します。

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `elb_logs` テーブルを登録して、その中のデータをクエリ向けに準備します。詳細については、「[クエリの例](#query-elb-classic-example)」を参照してください。

## クエリの例
<a name="query-elb-classic-example"></a>

以下の例のようなクエリを使用します。この例では、`4XX` または `5XX` エラーレスポンスコードを返したバックエンドアプリケーションサーバーを示しています。`LIMIT` 演算子を使用すると、一度にクエリするログの数を制限できます。

```
SELECT
 timestamp,
 elb_name,
 backend_ip,
 backend_response_code
FROM elb_logs
WHERE backend_response_code LIKE '4%' OR
      backend_response_code LIKE '5%'
LIMIT 100;
```

後続のクエリを使用して、バックエンド IP アドレスと Elastic Load Balancing インスタンス名でグループ分けされたすべてのトランザクションの応答時間を合算します。

```
SELECT sum(backend_processing_time) AS
 total_ms,
 elb_name,
 backend_ip
FROM elb_logs WHERE backend_ip <> ''
GROUP BY backend_ip, elb_name
LIMIT 100;
```

詳細については、「[Athena を使用した S3 のデータの分析](https://aws.amazon.com/blogs/big-data/analyzing-data-in-s3-using-amazon-athena/)」を参照してください。

# Amazon CloudFront ログをクエリする
<a name="cloudfront-logs"></a>

Amazon CloudFront CDN を設定して、ウェブディストリビューションのアクセスログを Amazon Simple Storage Service にエクスポートできます。これらのログを使用して、CloudFront によって提供されるウェブプロパティ全体でのユーザーのサーフィンパターンを調べます。

ログのクエリを開始する前に、使用する CloudFront ディストリビューションでウェブディストリビューションのアクセスログを有効にします。詳細については、「Amazon CloudFront デベロッパーガイド」の「[アクセスログ](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html)」を参照してください。ログを保存する Amazon S3 バケットをメモしておきます。

**Topics**
+ [CloudFront 標準ログ用テーブルを作成する (レガシー)](create-cloudfront-table-standard-logs.md)
+ [Athena で JSON での手動パーティショニングを使用して CloudFront ログ用のテーブルを作成する](create-cloudfront-table-manual-json.md)
+ [Athena で Parquet での手動パーティショニングを使用して CloudFront ログ用のテーブルを作成する](create-cloudfront-table-manual-parquet.md)
+ [Athena で JSON でのパーティショニング射影を使用して CloudFront ログ用のテーブルを作成する](create-cloudfront-table-partition-json.md)
+ [Athena で Parquet でのパーティション射影を使用して CloudFront ログ用のテーブルを作成する](create-cloudfront-table-partition-parquet.md)
+ [CloudFront リアルタイムログ用テーブルを作成する](create-cloudfront-table-real-time-logs.md)
+ [その他のリソース](cloudfront-logs-additional-resources.md)

# CloudFront 標準ログ用テーブルを作成する (レガシー)
<a name="create-cloudfront-table-standard-logs"></a>

**注記**  
次の手順は、CloudFront にあるウェブディストリビューションのアクセスログで機能します。RTMP ディストリビューションのストリーミングログには該当しません。

**CloudFront 標準ログファイルフィールド用のテーブルを作成する**

1. 次の DDL ステートメントの例をコピーして Athena コンソールのクエリエディタに貼り付けます。例のステートメントでは、「Amazon CloudFront デベロッパーガイド」の「[標準ログファイルフィールド](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat)」セクションに記載されているログファイルフィールドを使用しています。`LOCATION` をログを保存する Simple Storage Service (Amazon S3) バケットに変更します。クエリエディタの使用については、「[はじめに](getting-started.md)」を参照してください。

   このクエリは、フィールドがタブ文字で区切られることを示すために `ROW FORMAT DELIMITED` と `FIELDS TERMINATED BY '\t'` を指定します。`ROW FORMAT DELIMITED` には、Athena がデフォルトで [LazySimpleSerDe](lazy-simple-serde.md) を使用します。列 `date` は Athena の予約語であるため、バックティック (`) を使用してエスケープされています。詳細については、「[クエリで予約キーワードをエスケープする](reserved-words.md)」を参照してください。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS cloudfront_standard_logs (
     `date` DATE,
     time STRING,
     x_edge_location STRING,
     sc_bytes BIGINT,
     c_ip STRING,
     cs_method STRING,
     cs_host STRING,
     cs_uri_stem STRING,
     sc_status INT,
     cs_referrer STRING,
     cs_user_agent STRING,
     cs_uri_query STRING,
     cs_cookie STRING,
     x_edge_result_type STRING,
     x_edge_request_id STRING,
     x_host_header STRING,
     cs_protocol STRING,
     cs_bytes BIGINT,
     time_taken FLOAT,
     x_forwarded_for STRING,
     ssl_protocol STRING,
     ssl_cipher STRING,
     x_edge_response_result_type STRING,
     cs_protocol_version STRING,
     fle_status STRING,
     fle_encrypted_fields INT,
     c_port INT,
     time_to_first_byte FLOAT,
     x_edge_detailed_result_type STRING,
     sc_content_type STRING,
     sc_content_len BIGINT,
     sc_range_start BIGINT,
     sc_range_end BIGINT
   )
   ROW FORMAT DELIMITED 
   FIELDS TERMINATED BY '\t'
   LOCATION 's3://amzn-s3-demo-bucket/'
   TBLPROPERTIES ( 'skip.header.line.count'='2' )
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `cloudfront_standard_logs` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

## クエリの例
<a name="query-examples-cloudfront-logs"></a>

以下のクエリは、2018 年 6 月 9 日から 6 月 11 日の間に CloudFront によって提供されたバイト数をCに で処理されたバイト数を集計します。date 列名は予約語であるため、二重引用符で囲みます。

```
SELECT SUM(bytes) AS total_bytes
FROM cloudfront_standard_logs
WHERE "date" BETWEEN DATE '2018-06-09' AND DATE '2018-06-11'
LIMIT 100;
```

クエリ結果から重複する行 (重複する空の行など) を削除するには、次の例のように `SELECT DISTINCT` ステートメントを使用します。

```
SELECT DISTINCT * 
FROM cloudfront_standard_logs 
LIMIT 10;
```

# Athena で JSON での手動パーティショニングを使用して CloudFront ログ用のテーブルを作成する
<a name="create-cloudfront-table-manual-json"></a>

**JSON 形式を使用して CloudFront 標準ログファイルフィールド用のテーブルを作成するには**

1. 次の DDL ステートメントの例をコピーして Athena コンソールのクエリエディタに貼り付けます。例のステートメントでは、「Amazon CloudFront デベロッパーガイド」の「[標準ログファイルフィールド](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat)」セクションに記載されているログファイルフィールドを使用しています。`LOCATION` をログを保存する Simple Storage Service (Amazon S3) バケットに変更します。

   このクエリでは、Athena で JSON フィールドを正しく読み取るために OpenX JSON SerDe を次の SerDe プロパティとともに使用します。

   ```
   CREATE EXTERNAL TABLE `cf_logs_manual_partition_json`(
     `date` string , 
     `time` string , 
     `x-edge-location` string , 
     `sc-bytes` string , 
     `c-ip` string , 
     `cs-method` string , 
     `cs(host)` string , 
     `cs-uri-stem` string , 
     `sc-status` string , 
     `cs(referer)` string , 
     `cs(user-agent)` string , 
     `cs-uri-query` string , 
     `cs(cookie)` string , 
     `x-edge-result-type` string , 
     `x-edge-request-id` string , 
     `x-host-header` string , 
     `cs-protocol` string , 
     `cs-bytes` string , 
     `time-taken` string , 
     `x-forwarded-for` string , 
     `ssl-protocol` string , 
     `ssl-cipher` string , 
     `x-edge-response-result-type` string , 
     `cs-protocol-version` string , 
     `fle-status` string , 
     `fle-encrypted-fields` string , 
     `c-port` string , 
     `time-to-first-byte` string , 
     `x-edge-detailed-result-type` string , 
     `sc-content-type` string , 
     `sc-content-len` string , 
     `sc-range-start` string , 
     `sc-range-end` string )
   ROW FORMAT SERDE 
     'org.openx.data.jsonserde.JsonSerDe' 
   WITH SERDEPROPERTIES ( 
     'paths'='c-ip,c-port,cs(Cookie),cs(Host),cs(Referer),cs(User-Agent),cs-bytes,cs-method,cs-protocol,cs-protocol-version,cs-uri-query,cs-uri-stem,date,fle-encrypted-fields,fle-status,sc-bytes,sc-content-len,sc-content-type,sc-range-end,sc-range-start,sc-status,ssl-cipher,ssl-protocol,time,time-taken,time-to-first-byte,x-edge-detailed-result-type,x-edge-location,x-edge-request-id,x-edge-response-result-type,x-edge-result-type,x-forwarded-for,x-host-header') 
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.mapred.TextInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/'
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `cf_logs_manual_partition_json` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

## クエリの例
<a name="query-examples-cloudfront-logs-manual-json"></a>

以下のクエリは、2025 年 1 月 15 日に CloudFront によって提供されたバイト数を集計します。

```
SELECT sum(cast("sc-bytes" as BIGINT)) as sc
FROM cf_logs_manual_partition_json
WHERE "date"='2025-01-15'
```

クエリ結果から重複する行 (重複する空の行など) を削除するには、次の例のように `SELECT DISTINCT` ステートメントを使用します。

```
SELECT DISTINCT * FROM cf_logs_manual_partition_json
```

# Athena で Parquet での手動パーティショニングを使用して CloudFront ログ用のテーブルを作成する
<a name="create-cloudfront-table-manual-parquet"></a>

**Parquet 形式を使用して CloudFront 標準ログファイルフィールド用のテーブルを作成するには**

1. 次の DDL ステートメントの例をコピーして Athena コンソールのクエリエディタに貼り付けます。例のステートメントでは、「Amazon CloudFront デベロッパーガイド」の「[標準ログファイルフィールド](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat)」セクションに記載されているログファイルフィールドを使用しています。

   このクエリでは、Athena で Parquet フィールドを正しく読み取るために ParquetHiveSerDe を次の SerDe プロパティとともに使用します。

   ```
   CREATE EXTERNAL TABLE `cf_logs_manual_partition_parquet`(
     `date` string, 
     `time` string, 
     `x_edge_location` string, 
     `sc_bytes` string, 
     `c_ip` string, 
     `cs_method` string, 
     `cs_host` string, 
     `cs_uri_stem` string, 
     `sc_status` string, 
     `cs_referer` string, 
     `cs_user_agent` string, 
     `cs_uri_query` string, 
     `cs_cookie` string, 
     `x_edge_result_type` string, 
     `x_edge_request_id` string, 
     `x_host_header` string, 
     `cs_protocol` string, 
     `cs_bytes` string, 
     `time_taken` string, 
     `x_forwarded_for` string, 
     `ssl_protocol` string, 
     `ssl_cipher` string, 
     `x_edge_response_result_type` string, 
     `cs_protocol_version` string, 
     `fle_status` string, 
     `fle_encrypted_fields` string, 
     `c_port` string, 
     `time_to_first_byte` string, 
     `x_edge_detailed_result_type` string, 
     `sc_content_type` string, 
     `sc_content_len` string, 
     `sc_range_start` string, 
     `sc_range_end` string)
   ROW FORMAT SERDE 
     'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/'
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `cf_logs_manual_partition_parquet` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

## クエリの例
<a name="query-examples-cloudfront-logs-manual-parquet"></a>

以下のクエリは、2025 年 1 月 19 日に CloudFront によって提供されたバイト数を集計します。

```
SELECT sum(cast("sc_bytes" as BIGINT)) as sc
FROM cf_logs_manual_partition_parquet
WHERE "date"='2025-01-19'
```

クエリ結果から重複する行 (重複する空の行など) を削除するには、次の例のように `SELECT DISTINCT` ステートメントを使用します。

```
SELECT DISTINCT * FROM cf_logs_manual_partition_parquet
```

# Athena で JSON でのパーティショニング射影を使用して CloudFront ログ用のテーブルを作成する
<a name="create-cloudfront-table-partition-json"></a>

Athena のパーティション射影機能を使用すると、クエリランタイムを短縮し、パーティション管理を自動化できます。新しいデータが追加されると、パーティション射影は新しいパーティションを自動で追加します。このため、`ALTER TABLE ADD PARTITION` を使用してパーティションを手動で追加する必要がなくなります。

次の CREATE TABLE ステートメント例は、指定した CloudFront 配信から現在までの単一の AWS リージョンの CloudTrail ログでパーティション射影を自動的に使用します。クエリが正常に実行されると、テーブルをクエリできます。

```
CREATE EXTERNAL TABLE `cloudfront_logs_pp`(
  `date` string, 
  `time` string, 
  `x-edge-location` string, 
  `sc-bytes` string, 
  `c-ip` string, 
  `cs-method` string, 
  `cs(host)` string, 
  `cs-uri-stem` string, 
  `sc-status` string, 
  `cs(referer)` string, 
  `cs(user-agent)` string, 
  `cs-uri-query` string, 
  `cs(cookie)` string, 
  `x-edge-result-type` string, 
  `x-edge-request-id` string, 
  `x-host-header` string, 
  `cs-protocol` string, 
  `cs-bytes` string, 
  `time-taken` string, 
  `x-forwarded-for` string, 
  `ssl-protocol` string, 
  `ssl-cipher` string, 
  `x-edge-response-result-type` string, 
  `cs-protocol-version` string, 
  `fle-status` string, 
  `fle-encrypted-fields` string, 
  `c-port` string, 
  `time-to-first-byte` string, 
  `x-edge-detailed-result-type` string, 
  `sc-content-type` string, 
  `sc-content-len` string, 
  `sc-range-start` string, 
  `sc-range-end` string)
  PARTITIONED BY(
         distributionid string,
         year int,
         month int,
         day int,
         hour int )
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ( 
  'paths'='c-ip,c-port,cs(Cookie),cs(Host),cs(Referer),cs(User-Agent),cs-bytes,cs-method,cs-protocol,cs-protocol-version,cs-uri-query,cs-uri-stem,date,fle-encrypted-fields,fle-status,sc-bytes,sc-content-len,sc-content-type,sc-range-end,sc-range-start,sc-status,ssl-cipher,ssl-protocol,time,time-taken,time-to-first-byte,x-edge-detailed-result-type,x-edge-location,x-edge-request-id,x-edge-response-result-type,x-edge-result-type,x-forwarded-for,x-host-header') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/'
TBLPROPERTIES (
  'projection.distributionid.type'='enum',
  'projection.distributionid.values'='E2Oxxxxxxxxxxx',
  'projection.day.range'='01,31', 
  'projection.day.type'='integer', 
  'projection.day.digits'='2', 
  'projection.enabled'='true', 
  'projection.month.range'='01,12', 
  'projection.month.type'='integer', 
  'projection.month.digits'='2', 
  'projection.year.range'='2025,2026', 
  'projection.year.type'='integer', 
  'projection.hour.range'='00,23',
  'projection.hour.type'='integer',
  'projection.hour.digits'='2',
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/${distributionid}/${year}/${month}/${day}/${hour}/')
```

前の例で使用したプロパティに関する考慮事項を次に示します。
+ **テーブル名** – テーブル名 *`cloudfront_logs_pp`* は置き換えることができます。任意の名前に変更できます。
+ **場所** – Amazon S3 バケットを指すように `s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/` を変更します。
+ **配信 ID** – `projection.distributionid.values` では、カンマで区切って複数の配信 ID を指定できます。例えば、*<distributionID1>*, *<distributionID2>* のように指定します。
+ **年の範囲** – `projection.year.range` でデータに基づいて年の範囲を定義できます。例えば、**2025 や **2026 などの任意の期間に調整できます。
**注記**  
将来の日付 (例: 2025-2040) など、空のパーティションを含めると、クエリのパフォーマンスに影響が生じる可能性があります。ただし、パーティション射影は将来の日付を効果的に処理するように設計されています。最適なパフォーマンスを維持するには、パーティションを慎重に管理し、可能な場合は空のパーティションの過度な使用を避けてください。
+ **保存場所テンプレート** – 次の CloudFront パーティション構造と S3 パスに基づいて `storage.location.template` を正しく更新する必要があります。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/create-cloudfront-table-partition-json.html)

  CloudFront パーティション構造と S3 構造が必要なパターンに一致することを確認したら、`storage.location.template` を次のように更新します。

  ```
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account_id/CloudFront/${distributionid}/folder2/${year}/${month}/${day}/${hour}/folder3/'
  ```
**注記**  
データの正しい保存と取得を保証するには、`storage.location.template` を適切に設定することが重要です。

# Athena で Parquet でのパーティション射影を使用して CloudFront ログ用のテーブルを作成する
<a name="create-cloudfront-table-partition-parquet"></a>

次の CREATE TABLE ステートメント例は、指定した CloudFront 配信から現在までの単一の AWS リージョンの Parquet の CloudTrail ログでパーティション射影を自動的に使用します。クエリが正常に実行されると、テーブルをクエリできます。

```
CREATE EXTERNAL TABLE `cloudfront_logs_parquet_pp`(
`date` string, 
`time` string, 
`x_edge_location` string, 
`sc_bytes` string, 
`c_ip` string, 
`cs_method` string, 
`cs_host` string, 
`cs_uri_stem` string, 
`sc_status` string, 
`cs_referer` string, 
`cs_user_agent` string, 
`cs_uri_query` string, 
`cs_cookie` string, 
`x_edge_result_type` string, 
`x_edge_request_id` string, 
`x_host_header` string, 
`cs_protocol` string, 
`cs_bytes` string, 
`time_taken` string, 
`x_forwarded_for` string, 
`ssl_protocol` string, 
`ssl_cipher` string, 
`x_edge_response_result_type` string, 
`cs_protocol_version` string, 
`fle_status` string, 
`fle_encrypted_fields` string, 
`c_port` string, 
`time_to_first_byte` string, 
`x_edge_detailed_result_type` string, 
`sc_content_type` string, 
`sc_content_len` string, 
`sc_range_start` string, 
`sc_range_end` string)
PARTITIONED BY(
 distributionid string,
 year int,
 month int,
 day int,
 hour int )
ROW FORMAT SERDE 
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/'
TBLPROPERTIES (
'projection.distributionid.type'='enum',
'projection.distributionid.values'='E3OK0LPUNWWO3',
'projection.day.range'='01,31',
'projection.day.type'='integer',
'projection.day.digits'='2',
'projection.enabled'='true',
'projection.month.range'='01,12',
'projection.month.type'='integer',
'projection.month.digits'='2',
'projection.year.range'='2019,2025',
'projection.year.type'='integer',
'projection.hour.range'='01,12',
'projection.hour.type'='integer',
'projection.hour.digits'='2',
'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/${distributionid}/${year}/${month}/${day}/${hour}/')
```

前の例で使用したプロパティに関する考慮事項を次に示します。
+ **テーブル名** – テーブル名 *`cloudfront_logs_pp`* は置き換えることができます。任意の名前に変更できます。
+ **場所** – Amazon S3 バケットを指すように `s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/` を変更します。
+ **配信 ID** – `projection.distributionid.values` では、カンマで区切って複数の配信 ID を指定できます。例えば、*<distributionID1>*, *<distributionID2>* のように指定します。
+ **年の範囲** – `projection.year.range` でデータに基づいて年の範囲を定義できます。例えば、**2025 や **2026 などの任意の期間に調整できます。
**注記**  
将来の日付 (例: 2025-2040) など、空のパーティションを含めると、クエリのパフォーマンスに影響が生じる可能性があります。ただし、パーティション射影は将来の日付を効果的に処理するように設計されています。最適なパフォーマンスを維持するには、パーティションを慎重に管理し、可能な場合は空のパーティションの過度な使用を避けてください。
+ **保存場所テンプレート** – 次の CloudFront パーティション構造と S3 パスに基づいて `storage.location.template` を正しく更新する必要があります。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/create-cloudfront-table-partition-parquet.html)

  CloudFront パーティション構造と S3 構造が必要なパターンに一致することを確認したら、`storage.location.template` を次のように更新します。

  ```
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account_id/CloudFront/${distributionid}/folder2/${year}/${month}/${day}/${hour}/folder3/'
  ```
**注記**  
データの正しい保存と取得を保証するには、`storage.location.template` を適切に設定することが重要です。

# CloudFront リアルタイムログ用テーブルを作成する
<a name="create-cloudfront-table-real-time-logs"></a>

**CloudFront リアルタイムログファイルフィールド用のテーブルを作成する**

1. 次の DDL ステートメントの例をコピーして Athena コンソールのクエリエディタに貼り付けます。ステートメント例では、「Amazon CloudFront 開発者ガイド」の「[Real-time logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html)」セクションに記載されているログファイルフィールドを使用しています。`LOCATION` をログを保存する Simple Storage Service (Amazon S3) バケットに変更します。クエリエディタの使用については、「[はじめに](getting-started.md)」を参照してください。

   このクエリは、フィールドがタブ文字で区切られることを示すために `ROW FORMAT DELIMITED` と `FIELDS TERMINATED BY '\t'` を指定します。`ROW FORMAT DELIMITED` には、Athena がデフォルトで [LazySimpleSerDe](lazy-simple-serde.md) を使用します。列 `timestamp` は Athena の予約語であるため、バックティック (`) を使用してエスケープされています。詳細については、「[クエリで予約キーワードをエスケープする](reserved-words.md)」を参照してください。

   以下の例には、利用可能なフィールドのすべてが含まれています。不要なフィールドは、コメントアウトまたは削除することができます。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS cloudfront_real_time_logs ( 
   `timestamp` STRING,
   c_ip STRING,
   time_to_first_byte BIGINT,
   sc_status BIGINT,
   sc_bytes BIGINT,
   cs_method STRING,
   cs_protocol STRING,
   cs_host STRING,
   cs_uri_stem STRING,
   cs_bytes BIGINT,
   x_edge_location STRING,
   x_edge_request_id STRING,
   x_host_header STRING,
   time_taken BIGINT,
   cs_protocol_version STRING,
   c_ip_version STRING,
   cs_user_agent STRING,
   cs_referer STRING,
   cs_cookie STRING,
   cs_uri_query STRING,
   x_edge_response_result_type STRING,
   x_forwarded_for STRING,
   ssl_protocol STRING,
   ssl_cipher STRING,
   x_edge_result_type STRING,
   fle_encrypted_fields STRING,
   fle_status STRING,
   sc_content_type STRING,
   sc_content_len BIGINT,
   sc_range_start STRING,
   sc_range_end STRING,
   c_port BIGINT,
   x_edge_detailed_result_type STRING,
   c_country STRING,
   cs_accept_encoding STRING,
   cs_accept STRING,
   cache_behavior_path_pattern STRING,
   cs_headers STRING,
   cs_header_names STRING,
   cs_headers_count BIGINT,
   primary_distribution_id STRING,
   primary_distribution_dns_name STRING,
   origin_fbl STRING,
   origin_lbl STRING,
   asn STRING
   )
   ROW FORMAT DELIMITED 
   FIELDS TERMINATED BY '\t'
   LOCATION 's3://amzn-s3-demo-bucket/'
   TBLPROPERTIES ( 'skip.header.line.count'='2' )
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `cloudfront_real_time_logs` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

# その他のリソース
<a name="cloudfront-logs-additional-resources"></a>

Athena を使用した CloudFront ログのクエリについての詳細は、「[AWS ビッグデータブログ](https://aws.amazon.com/blogs/big-data/)」の以下の記事を参照してください。

[Amazon Athena を使用して AWS のサービス ログを簡単にクエリする](https://aws.amazon.com/blogs/big-data/easily-query-aws-service-logs-using-amazon-athena/) (2019 年 5 月 29 日)。

[Amazon CloudFront のアクセスログを大規模に分析する](https://aws.amazon.com/blogs/big-data/analyze-your-amazon-cloudfront-access-logs-at-scale/) (December 21, 2018 年 12 月 21 日)。

[AWS Lambda、Amazon Athena、Amazon Managed Service for Apache Flink を使用して Amazon CloudFront アクセスログを分析するためのサーバーレスアーキテクチャを構築する](https://aws.amazon.com/blogs/big-data/build-a-serverless-architecture-to-analyze-amazon-cloudfront-access-logs-using-aws-lambda-amazon-athena-and-amazon-kinesis-analytics/) (2017 年 5 月 26 日)。

# AWS CloudTrail ログをクエリする
<a name="cloudtrail-logs"></a>

AWS CloudTrail は、Amazon Web Services アカウントの AWS API コールとイベントを記録するサービスです。

CloudTrail ログには、コンソールを含めた AWS のサービス に対して発行された、あらゆる API コールの詳細が記載されます。CloudTrail は暗号化されたログファイルを生成して、それらを Amazon S3 に保存します。詳細については、[AWS CloudTrail ユーザーガイド](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html)を参照してください。

**注記**  
アカウント、リージョン、および日付にわたって CloudTrail イベント情報に対して SQL クエリを実行する場合は、CloudTrail Lake の使用を検討してください。CloudTrail Lakeは、企業からの情報を単一の検索可能なイベントデータストアに集約するトレイルを作成する AWS の代替です。Amazon S3 バケットストレージを使用する代わりに、イベントはデータレイクに保存されるため、より豊富で高速なクエリが可能になります。これを使用して、組織、リージョン間、およびカスタム時間範囲内でイベントを検索する SQL クエリを作成できます。CloudTrail Lake クエリは CloudTrail コンソール自体で実行するため、CloudTrail Lake を使用すると Athena は必要ありません。詳細については、[CloudTrail Lake](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-lake.html) のドキュメントを参照してください。

Athena での CloudTrail ログ の使用は、AWS のサービス のアクティビティに関する分析を強化する手段として優れています。たとえば、クエリを使用して傾向を識別したり、アクティビティを属性 (ソース IP アドレスやユーザーなど) でさらに分離したりできます。

一般的な用途は、セキュリティとコンプライアンスのための運用上のアクティビティの分析に CloudTrail ログを使用することです。詳細な例については、「AWS ビッグデータブログ」の記事「[AWS CloudTrail と Amazon Athena を使用してセキュリティ、コンプライアンス、運用上のアクティビティを分析する方法](https://aws.amazon.com/blogs/big-data/aws-cloudtrail-and-amazon-athena-dive-deep-to-analyze-security-compliance-and-operational-activity/)」を参照してください。

Athena は、ログファイルの `LOCATION` を指定して、Amazon S3 からこれらのログファイルを直接クエリするために使用できます。以下の 2 つの方法のいずれかを実行できます。
+ CloudTrail コンソールから直接 CloudTrailログファイルのテーブルを作成する。
+ Athena コンソールで CloudTrail ログファイルのテーブルを手動で作成する。

**Topics**
+ [CloudTrail ログと Athena テーブルを理解する](create-cloudtrail-table-understanding.md)
+ [CloudTrail ログ用の Athena テーブルを作成するために CloudTrail コンソールを使用する](create-cloudtrail-table-ct.md)
+ [Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する](create-cloudtrail-table.md)
+ [手動パーティショニングを使用して組織全体の証跡用のテーブルを作成する](create-cloudtrail-table-org-wide-trail.md)
+ [パーティション射影を使用して Athena で CloudTrail ログ用テーブルを作成する](create-cloudtrail-table-partition-projection.md)
+ [CloudTrail ログクエリの例](query-examples-cloudtrail-logs.md)

# CloudTrail ログと Athena テーブルを理解する
<a name="create-cloudtrail-table-understanding"></a>

テーブルの作成を開始する前に、CloudTrail、そしてそれがどのようにデータを保存するかについての理解を深めておく必要があります。これは、テーブルを CloudTrail コンソールから作成するか Athena から作成するかにかかわらず、必要なテーブルを作成するために役立ちます。

CloudTrail は、ログを JSON テキストファイルとして、圧縮された gzip 形式 (`*.json.gz`) で保存します。ログファイルの保存先は、証跡のセットアップ方法、AWS リージョン あるいはログを記録する対象のリージョン、その他の要因によって異なります。

ログの保存先、JSON 構造、およびレコードファイルの内容の詳細については、[AWS CloudTrail ユーザーガイド](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html)の以下のトピックを参照してください。
+  [CloudTrail ログファイルの検索](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-find-log-files.html) 
+  [CloudTrail ログファイルの例](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-examples.html) 
+  [CloudTrail レコードの内容](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)
+  [CloudTrail イベントリファレンス](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html) 

ログを収集して Amazon S3 に保存し、AWS マネジメントコンソール で CloudTrail を有効にします。詳細については、「AWS CloudTrail ユーザーガイド」の「[証跡の作成](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-create-a-trail-using-the-console-first-time.html)」を参照してください。

# CloudTrail ログ用の Athena テーブルを作成するために CloudTrail コンソールを使用する
<a name="create-cloudtrail-table-ct"></a>

CloudTrail コンソールから直接 CloudTrail ログをクエリするために、パーティションされていない Athena テーブルを作成できます。CloudTrail コンソールからの Athena テーブルの作成には、Athena でテーブルを作成するために十分なアクセス許可を持つロールでログインする必要があります。

**注記**  
CloudTrail コンソールを使用して、組織の証跡ログ用の Athena テーブルを作成することはできません。代わりに、Athena コンソールを使用してテーブルを手動で作成し、正しいストレージ場所を指定できるようにします。組織の証跡については、*AWS CloudTrail ユーザーガイド*の「[組織の証跡の作成](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/creating-trail-organization.html)」を参照してください。
+ Athena のためのアクセス許可のセットアップについては、「[設定、管理、プログラムによるアクセス](setting-up.md)」を参照してください。
+ パーティションを含むテーブルの作成については、「[Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する](create-cloudtrail-table.md)」を参照してください。

**CloudTrail コンソールを使用して CloudTrail 証跡用の Athena テーブルを作成する**

1. CloudTrail コンソールの [https://console.aws.amazon.com/cloudtrail/](https://console.aws.amazon.com/cloudtrail/) を開いてください。

1. ナビゲーションペインで [**Event history (イベント履歴)**] を選択してください。

1. [**Athena テーブルを作成**] をクリックします。  
![\[[Create Athena table] (Athena テーブルを作成) をクリックします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/cloudtrail-logs-create-athena-table.png)

1. **[Storage location]** (ストレージの場所) の下矢印を使用して、クエリする証跡のためにログファイルが保存される Amazon S3 バケットを選択します。
**注記**  
証跡に関連付けられているバケットの名前を探すには、CloudTrail のナビゲーションペインで **[Trails]** (証跡) を選択して、証跡の **[S3 bucket]** (S3 バケット) 列を表示します。バケットの Amazon S3 の場所を確認するには、**[S3 bucket]** (S3 バケット) 列でバケットのリンクを選択します。これにより、Amazon S3 コンソールで CloudTrail バケットの場所が開きます。

1. **[テーブルの作成]** を選択します。Amazon S3 バケットの名前が含まれたデフォルトの名前でテーブルが作成されます。

# Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する
<a name="create-cloudtrail-table"></a>

Athena コンソールで、CloudTrail ログファイル用のテーブルを手動で作成してから、Athena でクエリを実行することができます。

**Athena コンソールを使用して CloudTrail 証跡のための Athena テーブルを作成する**

1. 次の DDL ステートメントをコピーして Athena コンソールのクエリエディタに貼り付け、必要に応じて変更します。CloudTrail ログファイルは、公開 API コールの順序付けられたスタックトレースではないため、ログファイルのフィールドは特定の順序では表示されません。

   ```
   CREATE EXTERNAL TABLE cloudtrail_logs (
   eventversion STRING,
   useridentity STRUCT<
                  type:STRING,
                  principalid:STRING,
                  arn:STRING,
                  accountid:STRING,
                  invokedby:STRING,
                  accesskeyid:STRING,
                  username:STRING,
                  onbehalfof: STRUCT<
                       userid: STRING,
                       identitystorearn: STRING>,
     sessioncontext:STRUCT<
       attributes:STRUCT<
                  mfaauthenticated:STRING,
                  creationdate:STRING>,
       sessionissuer:STRUCT<  
                  type:STRING,
                  principalid:STRING,
                  arn:STRING, 
                  accountid:STRING,
                  username:STRING>,
       ec2roledelivery:string,
       webidfederationdata: STRUCT<
                  federatedprovider: STRING,
                  attributes: map<string,string>>
     >
   >,
   eventtime STRING,
   eventsource STRING,
   eventname STRING,
   awsregion STRING,
   sourceipaddress STRING,
   useragent STRING,
   errorcode STRING,
   errormessage STRING,
   requestparameters STRING,
   responseelements STRING,
   additionaleventdata STRING,
   requestid STRING,
   eventid STRING,
   resources ARRAY<STRUCT<
                  arn:STRING,
                  accountid:STRING,
                  type:STRING>>,
   eventtype STRING,
   apiversion STRING,
   readonly STRING,
   recipientaccountid STRING,
   serviceeventdetails STRING,
   sharedeventid STRING,
   vpcendpointid STRING,
   vpcendpointaccountid STRING,
   eventcategory STRING,
   addendum STRUCT<
     reason:STRING,
     updatedfields:STRING,
     originalrequestid:STRING,
     originaleventid:STRING>,
   sessioncredentialfromconsole STRING,
   edgedevicedetails STRING,
   tlsdetails STRUCT<
     tlsversion:STRING,
     ciphersuite:STRING,
     clientprovidedhostheader:STRING>
   )
   PARTITIONED BY (region string, year string, month string, day string)
   ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
   STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/Account_ID/';
   ```
**注記**  
例に示されている `org.apache.hive.hcatalog.data.JsonSerDe` の使用をお勧めします。`com.amazon.emr.hive.serde.CloudTrailSerde` は存在するものの、現在新しい CloudTrail フィールドの一部を処理しません。

1. (オプション) テーブルに必要のないフィールドをすべて削除します。特定の列のセットのみを読み込む必要がある場合は、テーブル定義で他の列を除外できます。

1. クエリするログデータが含まれる Amazon S3 バケットをポイントするように `s3://amzn-s3-demo-bucket/AWSLogs/Account_ID/` を変更します。例では、特定のアカウントに関するログの `LOCATION` 値を使用していますが、目的に応じた保存先を指定できます。以下に例を示します。
   + 複数のアカウントのデータを分析するには、`LOCATION` を元の設定に戻し、`AWSLogs` を使用してすべての `LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/'` を分析対称にします。
   + 特定の日付、アカウント、リージョンのデータを分析するには、`LOCATION 's3://amzn-s3-demo-bucket/123456789012/CloudTrail/us-east-1/2016/03/14/'.` を使用します。
   + 管理イベントの代わりにネットワークアクティビティデータを分析するには、`LOCATION` 句の `/CloudTrail/` を `/CloudTrail-NetworkActivity/` に置き換えます。

   オブジェクト階層の最上位レベルを使用することで、Athena を使用したクエリの実行時に最大の柔軟性が提供されます。

1. フィールドが正しく表示されていることを確認します。CloudTrail レコード内のフィールドの完全なリストに関する詳細については、「[CloudTrail レコードの内容](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)」を参照してください。

   ステップ 1 の `CREATE TABLE` ステートメント例では、[Hive JSON SerDe](hive-json-serde.md) を使用します。この例では、フィールド `requestparameters`、`responseelements`、および `additionaleventdata` は、クエリでタイプ `STRING` としてリストされていますが、JSON で使用される `STRUCT` データ型です。そのため、これらのフィールドからデータを取得するには、`JSON_EXTRACT` 関数を使用します。詳細については、「[文字列から JSON データを抽出する](extracting-data-from-JSON.md)」を参照してください。パフォーマンスを向上させるために、この例では、AWS リージョン、年、月、日に基づいてデータをパーティションしています。

1. Athena コンソールで `CREATE TABLE` ステートメントを実行します。

1. 以下の例のように、[ALTER TABLE ADD PARTITION](alter-table-add-partition.md) コマンドを使用してパーティションをロードすることで、データをクエリできるようにします。

   ```
   ALTER TABLE table_name ADD 
      PARTITION (region='us-east-1',
                 year='2019',
                 month='02',
                 day='01')
      LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/Account_ID/CloudTrail/us-east-1/2019/02/01/'
   ```

# 手動パーティショニングを使用して組織全体の証跡用のテーブルを作成する
<a name="create-cloudtrail-table-org-wide-trail"></a>

Athena で組織全体の CloudTrail ログファイル用のテーブルを作成するには、「[Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する](create-cloudtrail-table.md)」(Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する) の手順に従います。ただし、次の手順に記載されている変更を加えてください。

**組織全体の CloudTrail ログ用の Athena テーブルを作成するには**

1. 次の例のように、`CREATE TABLE` ステートメントで、組織 ID が含まれるように `LOCATION` 句を変更します。

   ```
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/'
   ```

1. 次の例のように、`PARTITIONED BY` 句で、アカウント ID のエントリを文字列として追加します。

   ```
   PARTITIONED BY (account string, region string, year string, month string, day string)
   ```

   次の例は、結合された結果を示しています。

   ```
   ...
   
   PARTITIONED BY (account string, region string, year string, month string, day string) 
   ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
   STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/Account_ID/CloudTrail/'
   ```

1. 次の例のように、`ALTER TABLE` ステートメントの `ADD PARTITION` 句には、アカウント ID を含めます。

   ```
   ALTER TABLE table_name ADD
   PARTITION (account='111122223333',
   region='us-east-1',
   year='2022',
   month='08',
   day='08')
   ```

1. 次の例のように、`ALTER TABLE` ステートメントの `LOCATION` 句には、追加する組織 ID、アカウント ID、パーティションを含めます。

   ```
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/Account_ID/CloudTrail/us-east-1/2022/08/08/'
   ```

   次の例では、`ALTER TABLE` ステートメントは結合された結果を示します。

   ```
   ALTER TABLE table_name ADD
   PARTITION (account='111122223333',
   region='us-east-1',
   year='2022',
   month='08',
   day='08')
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/111122223333/CloudTrail/us-east-1/2022/08/08/'
   ```

大規模な組織では、この方法を使用して各組織アカウント ID のパーティションを手動で追加および維持するのは面倒である可能性があることに留意してください。このようなシナリオでは、Athena ではなく CloudTrail Lake の利用を検討してください。このようなシナリオにおいて CloudTrail Lake を利用することには、次の利点があります:
+ 組織全体のログを自動的に集約する
+ パーティションまたは Athena テーブルの設定やメンテナンスが不要
+ クエリが CloudTrail コンソールで直接実行される
+ SQL 互換のクエリ言語を使用する

詳細については、「AWS CloudTrail ユーザーガイド」の「[AWS CloudTrail Lake の使用](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-lake.html)」を参照してください。

# パーティション射影を使用して Athena で CloudTrail ログ用テーブルを作成する
<a name="create-cloudtrail-table-partition-projection"></a>

CloudTrail ログには事前に指定できるパーティションスキームを持つ既知の構造があるため、Athena のパーティション射影機能を使用することで、クエリランタイムを短縮し、パーティション管理を自動化できます。新しいデータが追加されると、パーティション射影は新しいパーティションを自動で追加します。このため、`ALTER TABLE ADD PARTITION` を使用してパーティションを手動で追加する必要がなくなります。

次の `CREATE TABLE` ステートメント例では、指定した日付から現在までの単一の AWS リージョン リージョンの CloudTrail ログで、パーティション射影を自動的に使用しています。`LOCATION` 句と `storage.location.template` 句では、*bucket*、*account-id*、および *aws-region* の各プレースホルダーを、対応する同等の値に置き換えます。`projection.timestamp.range` では、*2020*/*01*/*01* を使用を開始する日に置き換えます。クエリが正常に実行されると、テーブルをクエリできます。パーティションをロードするのに、`ALTER TABLE ADD PARTITION` を実行する必要はありません。

```
CREATE EXTERNAL TABLE cloudtrail_logs_pp(
    eventversion STRING,
    useridentity STRUCT<
        type: STRING,
        principalid: STRING,
        arn: STRING,
        accountid: STRING,
        invokedby: STRING,
        accesskeyid: STRING,
        username: STRING,
        onbehalfof: STRUCT<
             userid: STRING,
             identitystorearn: STRING>,
        sessioncontext: STRUCT<
            attributes: STRUCT<
                mfaauthenticated: STRING,
                creationdate: STRING>,
            sessionissuer: STRUCT<
                type: STRING,
                principalid: STRING,
                arn: STRING,
                accountid: STRING,
                username: STRING>,
            ec2roledelivery:string,
            webidfederationdata: STRUCT<
                federatedprovider: STRING,
                attributes: map<string,string>>
        >
    >,
    eventtime STRING,
    eventsource STRING,
    eventname STRING,
    awsregion STRING,
    sourceipaddress STRING,
    useragent STRING,
    errorcode STRING,
    errormessage STRING,
    requestparameters STRING,
    responseelements STRING,
    additionaleventdata STRING,
    requestid STRING,
    eventid STRING,
    readonly STRING,
    resources ARRAY<STRUCT<
        arn: STRING,
        accountid: STRING,
        type: STRING>>,
    eventtype STRING,
    apiversion STRING,
    recipientaccountid STRING,
    serviceeventdetails STRING,
    sharedeventid STRING,
    vpcendpointid STRING,
    vpcendpointaccountid STRING,
    eventcategory STRING,
    addendum STRUCT<
      reason:STRING,
      updatedfields:STRING,
      originalrequestid:STRING,
      originaleventid:STRING>,
    sessioncredentialfromconsole STRING,
    edgedevicedetails STRING,
    tlsdetails STRUCT<
      tlsversion:STRING,
      ciphersuite:STRING,
      clientprovidedhostheader:STRING>
  )
PARTITIONED BY (
   `timestamp` string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region'
TBLPROPERTIES (
  'projection.enabled'='true', 
  'projection.timestamp.format'='yyyy/MM/dd', 
  'projection.timestamp.interval'='1', 
  'projection.timestamp.interval.unit'='DAYS', 
  'projection.timestamp.range'='2020/01/01,NOW', 
  'projection.timestamp.type'='date', 
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region/${timestamp}')
```

パーティション射影の詳細については、「[Amazon Athena でパーティション射影を使用する](partition-projection.md)」を参照してください。

# CloudTrail ログクエリの例
<a name="query-examples-cloudtrail-logs"></a>

以下の例は、CloudTrail イベントログ向けに作成されたテーブルから、匿名化された (署名されていない) すべてのリクエストを返すクエリの一部を示しています。このクエリは、`useridentity.accountid` が匿名で `useridentity.arn` が指定されていないリクエストを選択します。

```
SELECT *
FROM cloudtrail_logs
WHERE 
    eventsource = 's3.amazonaws.com' AND 
    eventname in ('GetObject') AND 
    useridentity.accountid = 'anonymous' AND 
    useridentity.arn IS NULL AND
    requestparameters LIKE '%[your bucket name ]%';
```

詳細については、「AWS Big·Data·Blog」(ビッグデータブログ) の記事「[AWS CloudTrail と Amazon Athena を使用して、セキュリティ、コンプライアンス、運用上のアクティビティを分析する](https://aws.amazon.com/blogs/big-data/aws-cloudtrail-and-amazon-athena-dive-deep-to-analyze-security-compliance-and-operational-activity/)」を参照してください。

## CloudTrail ログのネストされたフィールドをクエリする
<a name="cloudtrail-logs-nested-fields"></a>

`userIdentity` および `resources` フィールドはネストされたデータ型であるため、それらのクエリには特別な処理が必要です。

`userIdentity` オブジェクトは、ネストされた `STRUCT` 型で構成されています。以下の例にあるように、これらは、フィールドを区切るためにドットを使用してクエリすることができます。

```
SELECT 
    eventsource, 
    eventname,
    useridentity.sessioncontext.attributes.creationdate,
    useridentity.sessioncontext.sessionissuer.arn
FROM cloudtrail_logs
WHERE useridentity.sessioncontext.sessionissuer.arn IS NOT NULL
ORDER BY eventsource, eventname
LIMIT 10
```

`resources` フィールドは `STRUCT` オブジェクトの配列です。これらの配列では、`CROSS JOIN UNNEST` を使用して配列のネストを解除し、そのオブジェクトをクエリできるようにします。

以下の例は、リソース ARN が `example/datafile.txt` で終わるすべての行を返します。読みやすさのために、[replace](https://prestodb.io/docs/current/functions/string.html#replace) 関数が ARN から初期の `arn:aws:s3:::` サブストリングを削除します。

```
SELECT 
    awsregion,
    replace(unnested.resources_entry.ARN,'arn:aws:s3:::') as s3_resource,
    eventname,
    eventtime,
    useragent
FROM cloudtrail_logs t
CROSS JOIN UNNEST(t.resources) unnested (resources_entry)
WHERE unnested.resources_entry.ARN LIKE '%example/datafile.txt'
ORDER BY eventtime
```

以下の例は、`DeleteBucket` のイベントをクエリします。このクエリは、バケットの名前とバケットが属するアカウント ID を `resources` オブジェクトから抽出します。

```
SELECT 
    awsregion,
    replace(unnested.resources_entry.ARN,'arn:aws:s3:::') as deleted_bucket,
    eventtime AS time_deleted,
    useridentity.username, 
    unnested.resources_entry.accountid as bucket_acct_id 
FROM cloudtrail_logs t
CROSS JOIN UNNEST(t.resources) unnested (resources_entry)
WHERE eventname = 'DeleteBucket'
ORDER BY eventtime
```

ネスト解除の詳細については、「[配列をフィルタリングする](filtering-arrays.md)」を参照してください。

## CloudTrail ログのクエリに関するヒント
<a name="tips-for-querying-cloudtrail-logs"></a>

CloudTrail ログデータを調査する際には、次を考慮してください。
+ ログをクエリする前に、ログテーブルが「[Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する](create-cloudtrail-table.md)」に示している内容と同じになっていることを確認します。これが最初のテーブルではない場合は、コマンド `DROP TABLE cloudtrail_logs` を使用して既存のテーブルを削除します。
+ 既存のテーブルを削除した後、再作成します。詳細については、「[Athena で手動パーティショニングを使用して CloudTrail ログ用のテーブルを作成する](create-cloudtrail-table.md)」を参照してください。

  Athena クエリのフィールドが正しく表示されていることを確認します。CloudTrail レコード内のフィールドの完全なリストについては、「[CloudTrail レコードの内容](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)」を参照してください。

  クエリ内のフィールドが JSON 形式 (`STRUCT` など) である場合は、JSON からデータを抽出します。詳細については、「[文字列から JSON データを抽出する](extracting-data-from-JSON.md)」を参照してください。

  CloudTrail テーブルに対してクエリを発行するためのいくつかの提案事項:
+ 最初に、どの ユーザーが、どの送信元 IP アドレスから API オペレーションを呼び出したかを確認します。
+ 次の基本的な SQL クエリをテンプレートとして使用します。このクエリを Athena コンソールに貼り付けて実行します。

  ```
  SELECT
   useridentity.arn,
   eventname,
   sourceipaddress,
   eventtime
  FROM cloudtrail_logs
  LIMIT 100;
  ```
+ クエリを修正して、データをさらに詳しく調べます。
+ パフォーマンスを強化するには、`LIMIT` 句を追加して、指定したサブセットの行のみが返るようにします。

# Amazon EMR ログをクエリする
<a name="emr-logs"></a>

Amazon EMR と、Amazon EMR で実行されるビッグデータアプリケーションは、ログファイルを生成します。ログファイルは[プライマリノード](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-master-core-task-nodes.html)に書き込まれます。ログファイルを自動的に Amazon S3 にアーカイブするように Amazon EMR を設定することもできます。Amazon Athena を使用してこれらのログをクエリし、アプリケーションとクラスターのイベントと傾向を特定することができます。Amazon EMR のログファイルのタイプと、それらの Amazon S3 への保存に関する詳細については、「Amazon EMR マネジメントガイド」の「[ログファイルを表示する](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-manage-view-web-log-files.html)」を参照してください。

**Topics**
+ [Amazon EMR ログファイルに基づいて、基本的なテーブルを作成およびクエリする](emr-create-table.md)
+ [Amazon EMR ログに基づいて、パーティショニングされたテーブルを作成およびクエリする](emr-create-table-partitioned.md)

# Amazon EMR ログファイルに基づいて、基本的なテーブルを作成およびクエリする
<a name="emr-create-table"></a>

以下の例は、`s3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/elasticmapreduce/` に保存されたログファイルに基づいて、基本的なテーブル `myemrlogs` を作成します。以下の例で使用されている Amazon S3 の場所は、リージョン *us-west-2* で Amazon Web Services アカウント *123456789012* によって作成された EMR クラスターのデフォルトでのログの場所のパターンを反映しています。カスタムの場所を使用する場合、パターンは s3://amzn-s3-demo-bucket/*ClusterID* です。

パーティション化されたテーブルを作成してクエリのパフォーマンスを向上させ、データ転送を削減できる可能性のある方法については、「[Amazon EMR ログに基づいて、パーティショニングされたテーブルを作成およびクエリする](emr-create-table-partitioned.md)」を参照してください。

```
CREATE EXTERNAL TABLE `myemrlogs`(
  `data` string COMMENT 'from deserializer')
ROW FORMAT DELIMITED  
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6'
```

## クエリの例
<a name="emr-example-queries-basic"></a>

次の例のクエリは、前の例で作成した `myemrlogs` テーブルに対して実行できます。

**Example – ERROR、WARN、INFO、EXCEPTION、FATAL、または DEBUG の発生に関するステップログのクエリ**  

```
SELECT data,
        "$PATH"
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'s-86URH188Z6B1')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example – ERROR、WARN、INFO、EXCEPTION、FATAL、または DEBUG に関する特定のインスタンスログ i-00b3c0a839ece0a9c のクエリ**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'i-00b3c0a839ece0a9c')
        AND regexp_like("$PATH",'state')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example – ERROR、WARN、INFO、EXCEPTION、FATAL、または DEBUG に関する Presto アプリケーションログのクエリ**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'presto')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example – ERROR、WARN、INFO、EXCEPTION、FATAL、または DEBUG に関する Namenode アプリケーションログのクエリ**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'namenode')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example – ERROR、WARN、INFO、EXCEPTION、FATAL、または DEBUG に関する日付と時間でのすべてのログのクエリ**  

```
SELECT distinct("$PATH") AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'2019-07-23-10')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

# Amazon EMR ログに基づいて、パーティショニングされたテーブルを作成およびクエリする
<a name="emr-create-table-partitioned"></a>

これらの例は、Athena テーブルを作成するためのものと同じログの場所を使用しますが、テーブルがパーティション分割された後、パーティションがログの場所ごとに作成されます。詳細については、「[データのパーティション化](partitions.md)」を参照してください。

次のクエリは、`mypartitionedemrlogs` という名前のパーティション化されたテーブルを作成します。

```
CREATE EXTERNAL TABLE `mypartitionedemrlogs`(
  `data` string COMMENT 'from deserializer')
 partitioned by (logtype string)
ROW FORMAT DELIMITED  
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6'
```

以下のクエリステートメントは、次に Amazon S3 で Amazon EMR が作成する異なるログタイプのサブディレクトリに基づいて、テーブルパーティションを作成します。

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='containers')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/containers/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='hadoop-mapreduce')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/hadoop-mapreduce/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='hadoop-state-pusher')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/hadoop-state-pusher/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='node')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/node/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='steps')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/steps/'
```

パーティションを作成したら、テーブルで `SHOW PARTITIONS` クエリを実行して、以下を確認します。

```
SHOW PARTITIONS mypartitionedemrlogs;
```

## クエリの例
<a name="emr-example-queries-partitioned"></a>

以下の例は、上記の例で作成されたテーブルとパーティションを使用する特定のログエントリに対するクエリを示しています。

**Example – ERROR または WARN に関するコンテナパーティション内のアプリケーション application\$11561661818238\$10002 ログのクエリ**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='containers'
        AND regexp_like("$PATH",'application_1561661818238_0002')
        AND regexp_like(data, 'ERROR|WARN') limit 100;
```

**Example – ジョブ job\$11561661818238\$10004 と Failed Reduces に関する Hadoop-Mapreduce パーティションのクエリ**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='hadoop-mapreduce'
        AND regexp_like(data,'job_1561661818238_0004|Failed Reduces') limit 100;
```

**Example – クエリ ID 056e0609-33e1-4611-956c-7a31b42d2663 に関するノードパーティションでの Hive ログのクエリ**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='node'
        AND regexp_like("$PATH",'hive')
        AND regexp_like(data,'056e0609-33e1-4611-956c-7a31b42d2663') limit 100;
```

**Example – アプリケーション 1567660019320\$10001\$101\$1000001 に関するノードパーティションでの Resourcemanager ログのクエリ**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='node'
        AND regexp_like(data,'resourcemanager')
        AND regexp_like(data,'1567660019320_0001_01_000001') limit 100
```

# AWS Global Accelerator フローログをクエリする
<a name="querying-global-accelerator-flow-logs"></a>

AWS Global Accelerator を使用して、ネットワークトラフィックを AWS グローバルネットワーク経由で最適なエンドポイントに転送するアクセラレーターを作成できます。Global Accelerator の詳細については、「[AWS Global Accelerator とは?](https://docs.aws.amazon.com/global-accelerator/latest/dg/what-is-global-accelerator.html)」を参照してください。

Global Accelerator フローログは、アクセラレーター内のネットワークインターフェイス間で送受信される IP アドレストラフィックに関する情報の取得を可能にします。フローログデータは Amazon S3 にパブリッシュされ、そこでデータを取得して表示できます。詳細については、「[AWS Global Accelerator のフローログ](https://docs.aws.amazon.com/global-accelerator/latest/dg/monitoring-global-accelerator.flow-logs.html)」を参照してください。

Athena を使用して、Amazon S3 内の Global Accelerator フローログの場所を指定するテーブルを作成することによって、フローログをクエリすることができます。

**Global Accelerator フローログのテーブルを作成する**

1. 以下の DDL ステートメントをコピーして Athena コンソール内に貼り付けます。このクエリでは、*ROW FORMAT DELIMITED* を指定し、[SerDe](serde-reference.md) の指定は省略します。この場合、クエリでは [`LazySimpleSerDe`](lazy-simple-serde.md) が使用されます。このクエリでは、フィールドはスペースで終了します。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS aga_flow_logs (
     version string,
     account string,
     acceleratorid string,
     clientip string,
     clientport int,
     gip string,
     gipport int,
     endpointip string,
     endpointport int,
     protocol string,
     ipaddresstype string,
     numpackets bigint,
     numbytes int,
     starttime int,
     endtime int,
     action string,
     logstatus string,
     agasourceip string,
     agasourceport int,
     endpointregion string,
     agaregion string,
     direction string,
     vpc_id string,
     reject_reason string
   )
   PARTITIONED BY (dt string)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY ' '
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region/'
   TBLPROPERTIES ("skip.header.line.count"="1");
   ```

1. ログデータが含まれる Amazon S3 バケットをポイントするように `LOCATION` 値を変更します。

   ```
   's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region_code/'
   ```

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `aga_flow_logs` テーブルを登録し、そのデータをクエリに使用できるようにします。

1. 次のサンプルクエリのように、パーティションを作成してデータを読み取ります。このクエリは、指定日の 1 つのパーティションを作成します。日付と場所のプレースホルダーを置き換えます。

   ```
   ALTER TABLE aga_flow_logs
   ADD PARTITION (dt='YYYY-MM-dd')
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region_code/YYYY/MM/dd';
   ```

## AWS Global Accelerator フローログのクエリ例
<a name="querying-global-accelerator-flow-logs-examples"></a>

**Example – 特定のエッジロケーションを通過するリクエストをリストする**  
以下のクエリ例は、LHR エッジロケーションを通過するリクエストをリストします。`LIMIT` 演算子を使用すると、一度にクエリするログの数を制限できます。  

```
SELECT 
  clientip, 
  agaregion, 
  protocol, 
  action 
FROM 
  aga_flow_logs 
WHERE 
  agaregion LIKE 'LHR%' 
LIMIT 
  100;
```

**Example – HTTPS リクエストの大部分の受信するエンドポイント IP アドレスをリストする**  
最大数の HTTPS リクエストを受信しているエンドポイント IP アドレスを確認するには、次のクエリを使用します。このクエリは、HTTPS ポート 443 で受信したパケット数をカウントし、送信先 IP アドレス別にグループ分けして、上位 10 の IP アドレスを返します。  

```
SELECT 
  SUM(numpackets) AS packetcount, 
  endpointip 
FROM 
  aga_flow_logs 
WHERE 
  endpointport = 443 
GROUP BY 
  endpointip 
ORDER BY 
  packetcount DESC 
LIMIT 
  10;
```

# Amazon GuardDuty の検出結果をクエリする
<a name="querying-guardduty"></a>

[Amazon GuardDuty](https://aws.amazon.com/guardduty/) は、AWS 環境内での不正または悪質である可能性がある予期しないアクティビティを識別するために役立つ、セキュリティをモニタリングするサービスです。悪意のある可能性がある予期しないアクティビティが検出されると、GuardDuty がストレージと分析のために Amazon S3 にエクスポートできるセキュリティ[結果](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html)を生成します。結果を Amazon S3 にエクスポートしたら、Athena を使用してそれらをクエリできます。この記事は、GuardDutyの 結果用のテーブルを Athena で作成し、それらをクエリする方法を説明します。

Amazon GuardDuty の詳細については、「[Amazon GuardDuty ユーザーガイド](https://docs.aws.amazon.com/guardduty/latest/ug/)」を参照してください。

## 前提条件
<a name="querying-guardduty-prerequisites"></a>
+ Amazon S3 に結果をエクスポートするための GuardDuty 機能を有効にします。ステップについては、「Amazon GuardDuty ユーザーガイド」の「[結果のエクスポート](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_exportfindings.html)」を参照してください。

## GuardDuty の検出結果のために Athena でテーブルを作成する
<a name="querying-guardduty-creating-a-table-in-athena-for-guardduty-findings"></a>

Athena から GuardDuty の結果をクエリするには、結果用のテーブルを作成する必要があります。

**GuardDuty の結果のために Athena でテーブルをで作成する**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. 以下の DDL ステートメントを Athena コンソール内に貼り付けます。`LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/account-id/GuardDuty/'` の値を、Amazon S3 にある GuardDuty の結果にポイントするように変更します。

   ```
   CREATE EXTERNAL TABLE `gd_logs` (
     `schemaversion` string,
     `accountid` string,
     `region` string,
     `partition` string,
     `id` string,
     `arn` string,
     `type` string,
     `resource` string,
     `service` string,
     `severity` string,
     `createdat` string,
     `updatedat` string,
     `title` string,
     `description` string)
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/account-id/GuardDuty/'
    TBLPROPERTIES ('has_encrypted_data'='true')
   ```
**注記**  
SerDe では、各 JSON ドキュメントが、レコード内のフィールドを区切る行終端文字なしの、1 行のテキストに収まっていることを想定しています。JSON テキストがプリティプリント形式の場合、テーブルを作成した後にクエリを実行しようとすると、以下のようなエラーメッセージが表示される場合があります。「HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object」、または「HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT」。詳細については、GitHub の OpenX SerDe のドキュメントで「[JSON Data Files](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)」(JSON データファイル) を参照してください。

1. Athena コンソールでクエリを実行して、`gd_logs` テーブルを登録します。クエリが完了すると、結果は Athena からクエリを実行できる状態になります。

## クエリの例
<a name="querying-guardduty-examples"></a>

以下の例は、Athena から GuardDuty の 結果をクエリする方法を示しています。

**Example – DNS データの流出**  
以下のクエリは、DNS クエリを介してデータを流出している可能性がある Amazon EC2 インスタンスに関する情報を返します。  

```
SELECT
    title,
    severity,
    type,
    id AS FindingID,
    accountid,
    region,
    createdat,
    updatedat,
    json_extract_scalar(service, '$.count') AS Count,
    json_extract_scalar(resource, '$.instancedetails.instanceid') AS InstanceID,
    json_extract_scalar(service, '$.action.actiontype') AS DNS_ActionType,
    json_extract_scalar(service, '$.action.dnsrequestaction.domain') AS DomainName,
    json_extract_scalar(service, '$.action.dnsrequestaction.protocol') AS protocol,
    json_extract_scalar(service, '$.action.dnsrequestaction.blocked') AS blocked
FROM gd_logs
WHERE type = 'Trojan:EC2/DNSDataExfiltration'
ORDER BY severity DESC
```

**Example – 不正な IAM ユーザーアクセス**  
以下のクエリは、すべてのリージョンからの IAM プリンシパルに関するすべての `UnauthorizedAccess:IAMUser` 結果タイプを返します。  

```
SELECT title,
         severity,
         type,
         id,
         accountid,
         region,
         createdat,
         updatedat,
         json_extract_scalar(service, '$.count') AS Count, 
         json_extract_scalar(resource, '$.accesskeydetails.username') AS IAMPrincipal, 
         json_extract_scalar(service,'$.action.awsapicallaction.api') AS APIActionCalled
FROM gd_logs
WHERE type LIKE '%UnauthorizedAccess:IAMUser%' 
ORDER BY severity desc;
```

## GuardDuty の結果のクエリに関するヒント
<a name="querying-guardduty-tips"></a>

クエリを作成するときは、次の点に注意してください。
+ ネストされた JSON フィールドからデータを抽出するには、Presto `json_extract` 関数、または `json_extract_scalar` 関数を使用します。詳細については、「[文字列から JSON データを抽出する](extracting-data-from-JSON.md)」(JSON からデータを抽出する) を参照してください。
+ JSON フィールドのすべての文字が小文字であることを確認します。
+  クエリ結果のダウンロードについては、「[Athena コンソールを使用してクエリ結果ファイルをダウンロードする](saving-query-results.md)」を参照してください。

# AWS Network Firewall ログをクエリする
<a name="querying-network-firewall-logs"></a>

AWS Network Firewall は、Amazon Virtual Private Cloud インスタンスに不可欠なネットワーク保護をデプロイするために使用できるマネージドサービスです。AWS Network Firewall は AWS Firewall Manager と連携するため、AWS Network Firewall ルールに基づいてポリシーを構築して、VPC とアカウント全体に集中的に適用できます。の詳細については、「AWS Network Firewall」を参照してください。。[AWS Network Firewall](https://aws.amazon.com/network-firewall/)

ファイアウォールのステートフルルールエンジンに転送するトラフィックの AWS Network Firewall ログの記録を設定できます。ログを記録すると、ステートフルエンジンがパケットを受信した時間、パケットに関する詳細情報、パケットに対して実行されたステートフルルールアクションなど、ネットワークトラフィックに関する詳細情報が得られます。ログは、設定したログ送信先に公開され、そこでログを取得して表示できます。詳細については、「AWS Network Firewall デベロッパーガイド」の「[AWS Network Firewallからのネットワークトラフィックのログ記録](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html)」を参照してください。

**Topics**
+ [アラートログのテーブルを作成およびクエリする](querying-network-firewall-logs-sample-alert-logs-table.md)
+ [NetFlow ログ用のテーブルを作成およびクエリする](querying-network-firewall-logs-sample-netflow-logs-table.md)

# アラートログのテーブルを作成およびクエリする
<a name="querying-network-firewall-logs-sample-alert-logs-table"></a>

1. 次のサンプル DDL ステートメントをアラートログの構造に合わせて変更します。ステートメントを更新して、最新バージョンのログの列を含めることが必要になる場合があります。詳細については、「AWS Network Firewall デベロッパーガイド」の「[ファイアウォールログの内容](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html#firewall-logging-contents)」を参照してください。

   ```
   CREATE EXTERNAL TABLE network_firewall_alert_logs (
     firewall_name string,
     availability_zone string,
     event_timestamp string,
     event struct<
       timestamp:string,
       flow_id:bigint,
       event_type:string,
       src_ip:string,
       src_port:int,
       dest_ip:string,
       dest_port:int,
       proto:string,
       app_proto:string,
       sni:string,
       tls_inspected:boolean,
       tls_error:struct<
         error_message:string>,
       revocation_check:struct<
         leaf_cert_fpr:string,
         status:string,
         action:string>,
       alert:struct<
         alert_id:string,
         alert_type:string,
         action:string,
         signature_id:int,
         rev:int,
         signature:string,
         category:string,
         severity:int,
         rule_name:string,
         alert_name:string,
         alert_severity:string,
         alert_description:string,
         file_name:string,
         file_hash:string,
         packet_capture:string,
         reference_links:array<string>
       >, 
       src_country:string, 
       dest_country:string, 
       src_hostname:string, 
       dest_hostname:string, 
       user_agent:string, 
       url:string
      >
   )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    LOCATION 's3://amzn-s3-demo-bucket/path_to_alert_logs_folder/';
   ```

1. `LOCATION` 句を変更して Amazon S3 のログ用のフォルダを指定します。

1. Athena クエリエディタで `CREATE TABLE` クエリを実行します。クエリが完了すると、Athena は `network_firewall_alert_logs` テーブルを登録し、テーブルがポイントするデータをクエリできる状態にします。

## クエリの例
<a name="querying-network-firewall-logs-alert-log-sample-query"></a>

このセクションのサンプルアラートログクエリでは、TLS 検査が実行されたイベントのうち、重大度が 2 以上のアラートを含むものがフィルタリングされます。

このクエリでは、エイリアスを使用して、その列が属する `struct` を示す出力列の見出しを作成します。例えば、`event.alert.category` フィールドの列見出しは、単なる `category` ではなく `event_alert_category` になります。列名をさらにカスタマイズするには、好みに合わせてエイリアスを変更します。例えば、アンダースコアやその他の区切り文字を使用して `struct` 名とフィールド名を区切ることができます。

テーブル定義とクエリ結果に含めるフィールドに基づいて、列名と `struct` 参照を必ず変更してください。

```
SELECT 
  firewall_name,
  availability_zone,
  event_timestamp,
  event.timestamp AS event_timestamp,
  event.flow_id AS event_flow_id,
  event.event_type AS event_type,
  event.src_ip AS event_src_ip,
  event.src_port AS event_src_port,
  event.dest_ip AS event_dest_ip,
  event.dest_port AS event_dest_port,
  event.proto AS event_protol,
  event.app_proto AS event_app_proto,
  event.sni AS event_sni,
  event.tls_inspected AS event_tls_inspected,
  event.tls_error.error_message AS event_tls_error_message,
  event.revocation_check.leaf_cert_fpr AS event_revocation_leaf_cert,
  event.revocation_check.status AS event_revocation_check_status,
  event.revocation_check.action AS event_revocation_check_action,
  event.alert.alert_id AS event_alert_alert_id,
  event.alert.alert_type AS event_alert_alert_type,
  event.alert.action AS event_alert_action,
  event.alert.signature_id AS event_alert_signature_id,
  event.alert.rev AS event_alert_rev,
  event.alert.signature AS event_alert_signature,
  event.alert.category AS event_alert_category,
  event.alert.severity AS event_alert_severity,
  event.alert.rule_name AS event_alert_rule_name,
  event.alert.alert_name AS event_alert_alert_name,
  event.alert.alert_severity AS event_alert_alert_severity,
  event.alert.alert_description AS event_alert_alert_description,
  event.alert.file_name AS event_alert_file_name,
  event.alert.file_hash AS event_alert_file_hash,
  event.alert.packet_capture AS event_alert_packet_capture,
  event.alert.reference_links AS event_alert_reference_links,
  event.src_country AS event_src_country,
  event.dest_country AS event_dest_country,
  event.src_hostname AS event_src_hostname,
  event.dest_hostname AS event_dest_hostname,
  event.user_agent AS event_user_agent,
  event.url AS event_url
FROM 
  network_firewall_alert_logs 
WHERE 
  event.alert.severity >= 2
  AND event.tls_inspected = true 
LIMIT 10;
```

# NetFlow ログ用のテーブルを作成およびクエリする
<a name="querying-network-firewall-logs-sample-netflow-logs-table"></a>

1. 次の DDL ステートメントのサンプルを Netflow ログの構造に合わせて変更します。ステートメントを更新して、最新バージョンのログの列を含めることが必要になる場合があります。詳細については、「AWS Network Firewall デベロッパーガイド」の「[ファイアウォールログの内容](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html#firewall-logging-contents)」を参照してください。

   ```
   CREATE EXTERNAL TABLE network_firewall_netflow_logs (
     firewall_name string,
     availability_zone string,
     event_timestamp string,
     event struct<
       timestamp:string,
       flow_id:bigint,
       event_type:string,
       src_ip:string,
       src_port:int,
       dest_ip:string,
       dest_port:int,
       proto:string,
       app_proto:string,
       tls_inspected:boolean,
       netflow:struct<
         pkts:int,
         bytes:bigint,
         start:string,
         `end`:string,
         age:int,
         min_ttl:int,
         max_ttl:int,
         tcp_flags:struct<
           syn:boolean,
           fin:boolean,
           rst:boolean,
           psh:boolean,
           ack:boolean,
           urg:boolean
           >
         >
       >
   )
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
   LOCATION 's3://amzn-s3-demo-bucket/path_to_netflow_logs_folder/';
   ```

1. `LOCATION` 句を変更して Amazon S3 のログ用のフォルダを指定します。

1. Athena クエリエディタで `CREATE TABLE` クエリを実行します。クエリが完了すると、Athena は `network_firewall_netflow_logs` テーブルを登録し、テーブルがポイントするデータをクエリできる状態にします。

## クエリの例
<a name="querying-network-firewall-logs-netflow-log-sample-query"></a>

このセクションのサンプル Netflow ログクエリでは、TLS 検査が実行されたイベントがフィルタリングされます。

このクエリでは、エイリアスを使用して、その列が属する `struct` を示す出力列の見出しを作成します。例えば、`event.netflow.bytes` フィールドの列見出しは、単なる `bytes` ではなく `event_netflow_bytes` になります。列名をさらにカスタマイズするには、好みに合わせてエイリアスを変更します。例えば、アンダースコアやその他の区切り文字を使用して `struct` 名とフィールド名を区切ることができます。

テーブル定義とクエリ結果に含めるフィールドに基づいて、列名と `struct` 参照を必ず変更してください。

```
SELECT
  event.src_ip AS event_src_ip,
  event.dest_ip AS event_dest_ip,
  event.proto AS event_proto,
  event.app_proto AS event_app_proto,
  event.tls_inspected AS event_tls_inspected,
  event.netflow.pkts AS event_netflow_pkts,
  event.netflow.bytes AS event_netflow_bytes,
  event.netflow.tcp_flags.syn AS event_netflow_tcp_flags_syn 
FROM network_firewall_netflow_logs 
WHERE event.tls_inspected = true
```

# Network Load Balancer のログをクエリする
<a name="networkloadbalancer-classic-logs"></a>

Athena を使用して、Network Load Balancer からのログを分析および処理します。これらのログは、Network Load Balancer に送信された Transport Layer Security (TLS) リクエストに関する詳細情報を受け取ります。これらのアクセスログを使用して、トラフィックパターンを分析し、問題のトラブルシューティングを行うことができます。

Network Load Balancer のアクセスログを分析する前に、ログを宛先の Amazon S3 バケットに保存するためにログを設定します。詳細および各 Network Load Balancer アクセスログエントリの詳細については、「[Network Load Balancer のアクセスログ](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html)」を参照してください。

**Network Load Balancer ログのテーブルを作成する**

1. 以下の DDL ステートメントをコピーして Athena コンソール内に貼り付けます。Network Load Balancer ログレコードの[構文](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html#access-log-file-format)をチェックします。ログレコードに対応する列と正規表現を含めるために、必要に応じてステートメントを更新します。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS nlb_tls_logs (
               type string,
               version string,
               time string,
               elb string,
               listener_id string,
               client_ip string,
               client_port int,
               target_ip string,
               target_port int,
               tcp_connection_time_ms double,
               tls_handshake_time_ms double,
               received_bytes bigint,
               sent_bytes bigint,
               incoming_tls_alert int,
               cert_arn string,
               certificate_serial string,
               tls_cipher_suite string,
               tls_protocol_version string,
               tls_named_group string,
               domain_name string,
               alpn_fe_protocol string,
               alpn_be_protocol string,
               alpn_client_preference_list string,
               tls_connection_creation_time string
               )
               ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
               WITH SERDEPROPERTIES (
               'serialization.format' = '1',
               'input.regex' = 
               '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*):([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
               )
               LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/AWS_account_ID/elasticloadbalancing/region';
   ```

1. `LOCATION` の Simple Storage Service (Amazon S3) バケットを変更して、Network Load Balancer ログの宛先を指定します。

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `nlb_tls_logs` テーブルを登録して、その中のデータをクエリ向けに準備します。

## クエリの例
<a name="query-nlb-example"></a>

証明書の使用回数を確認するには、次の例のようなクエリを使用します。

```
SELECT count(*) AS 
         ct,
         cert_arn
FROM "nlb_tls_logs"
GROUP BY  cert_arn;
```

次のクエリでは、1.3 より前の TLS バージョンを使用しているユーザーの数を表示します。

```
SELECT tls_protocol_version,
         COUNT(tls_protocol_version) AS 
         num_connections,
         client_ip
FROM "nlb_tls_logs"
WHERE tls_protocol_version < 'tlsv13'
GROUP BY tls_protocol_version, client_ip;
```

次のクエリを使用して、TLS ハンドシェイクに長い時間がかかっている接続を特定します。

```
SELECT *
FROM "nlb_tls_logs"
ORDER BY  tls_handshake_time_ms DESC 
LIMIT 10;
```

次のクエリは、過去 30 日間にネゴシエートされた TLS プロトコルのバージョンと暗号化スイートを特定し、その数をカウントするために使用します。

```
SELECT tls_cipher_suite,
         tls_protocol_version,
         COUNT(*) AS ct
FROM "nlb_tls_logs"
WHERE from_iso8601_timestamp(time) > current_timestamp - interval '30' day
        AND NOT tls_protocol_version = '-'
GROUP BY tls_cipher_suite, tls_protocol_version
ORDER BY ct DESC;
```

# Amazon Route 53 Resolver クエリログをクエリする
<a name="querying-r53-resolver-logs"></a>

Amazon Route 53 Resolver クエリログ用の Athena テーブルを作成して、それらを Athena からクエリできます。

Route 53 Resolver のクエリロギングは、VPC 内のリソースによって行われた DNS クエリ、インバウンドリゾルバーエンドポイントを使用するオンプレミスリソース、再帰的な DNS 解決にアウトバウンドリゾルバーエンドポイントを使用するクエリ、およびドメインリストをブロック、許可、またはモニタリングするために Route 53 Resolver DNS ファイアウォールルールを使用するクエリをログ記録するためのものです。Resolver クエリログ記録の詳細については、*Amazon Route 53 デベロッパーガイド*の「[Resolver query logging](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-query-logs.html)」を参照してください。ログにある各フィールドについては、「Amazon Route 53 デベロッパーガイド」の「[Resolver クエリログに表示される値](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-query-logs-format.html)」を参照してください。

**Topics**
+ [Resolver クエリログ用のテーブルを作成する](querying-r53-resolver-logs-creating-the-table.md)
+ [パーティション射影を使用する](querying-r53-resolver-logs-partitioning-example.md)
+ [クエリの例](querying-r53-resolver-logs-example-queries.md)

# Resolver クエリログ用のテーブルを作成する
<a name="querying-r53-resolver-logs-creating-the-table"></a>

Athena コンソールのクエリエディタを使用して、Route 53 Resolver クエリログ用のテーブルを作成してクエリできます。

**Route 53 Resolver クエリログ用の Athena テーブルを作成してクエリする**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. Athena クエリエディタに以下の `CREATE TABLE` ステートメントを入力します。`LOCATION` 句の値を、Simple Storage Service (Amazon S3) の Resolver ログの場所に対応する値に置き換えます。

   ```
   CREATE EXTERNAL TABLE r53_rlogs (
     version string,
     account_id string,
     region string,
     vpc_id string,
     query_timestamp string,
     query_name string,
     query_type string,
     query_class
       string,
     rcode string,
     answers array<
       struct<
         Rdata: string,
         Type: string,
         Class: string>
       >,
     srcaddr string,
     srcport int,
     transport string,
     srcids struct<
       instance: string,
       resolver_endpoint: string
       >,
     firewall_rule_action string,
     firewall_rule_group_id string,
     firewall_domain_list_id string
    )
        
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/aws_account_id/vpcdnsquerylogs/{vpc-id}/'
   ```

   Resolver クエリログデータは JSON 形式であるため、CREATE TABLE ステートメントは [JSON SerDe ライブラリ](json-serde.md)を使用してデータを分析します。
**注記**  
SerDe では、各 JSON ドキュメントが、レコード内のフィールドを区切る行終端文字なしの、1 行のテキストに収まっていることを想定しています。JSON テキストがプリティプリント形式の場合、テーブルを作成した後にクエリを実行しようとすると、以下のようなエラーメッセージが表示される場合があります。「HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object」、または「HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT」。詳細については、GitHub の OpenX SerDe のドキュメントで「[JSON Data Files](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)」(JSON データファイル) を参照してください。

1. **[Run query]** (クエリの実行) を選択します。ステートメントが `r53_rlogs` という名前の Athena テーブルを作成します。このテーブルの列は Resolver ログデータの各フィールドを表します。

1. Athena コンソールのクエリエディタで以下のクエリを実行して、テーブルが作成されたことを検証します。

   ```
   SELECT * FROM "r53_rlogs" LIMIT 10
   ```

# パーティション射影を使用する
<a name="querying-r53-resolver-logs-partitioning-example"></a>

次の例は、パーティション射影を使用し、VPC と日付で分割された Resolver クエリログの `CREATE TABLE` ステートメントを示しています。パーティション射影の詳細については、「[Amazon Athena でパーティション射影を使用する](partition-projection.md)」を参照してください。

```
CREATE EXTERNAL TABLE r53_rlogs (
  version string,
  account_id string,
  region string,
  vpc_id string,
  query_timestamp string,
  query_name string,
  query_type string,
  query_class string,
  rcode string,
  answers array<
    struct<
      Rdata: string,
      Type: string,
      Class: string>
    >,
  srcaddr string,
  srcport int,
  transport string,
  srcids struct<
    instance: string,
    resolver_endpoint: string
    >,
  firewall_rule_action string,
  firewall_rule_group_id string,
  firewall_domain_list_id string
)
PARTITIONED BY (
`date` string,
`vpc` string
)
ROW FORMAT SERDE      'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT          'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION              's3://amzn-s3-demo-bucket/route53-query-logging/AWSLogs/aws_account_id/vpcdnsquerylogs/'
TBLPROPERTIES(
'projection.enabled' = 'true',
'projection.vpc.type' = 'enum',
'projection.vpc.values' = 'vpc-6446ae02',
'projection.date.type' = 'date',
'projection.date.range' = '2023/06/26,NOW',
'projection.date.format' = 'yyyy/MM/dd',
'projection.date.interval' = '1',
'projection.date.interval.unit' = 'DAYS',
'storage.location.template' = 's3://amzn-s3-demo-bucket/route53-query-logging/AWSLogs/aws_account_id/vpcdnsquerylogs/${vpc}/${date}/'
)
```

# クエリの例
<a name="querying-r53-resolver-logs-example-queries"></a>

以下の例は、Resolver クエリログで Athena から実行できるクエリをいくつか説明しています。

## 例 1 – ログを降順の query\$1timestamp 順にクエリする
<a name="querying-r53-resolver-logs-example-1-query-logs-in-descending-query_timestamp-order"></a>

以下のクエリは、`query_timestamp` 順で降順にログ結果を表示します。

```
SELECT * FROM "r53_rlogs"
ORDER BY query_timestamp DESC
```

## 例 2 – 指定された開始時刻と終了時刻の範囲内でログをクエリする
<a name="querying-r53-resolver-logs-example-2-query-logs-within-specified-start-and-end-times"></a>

以下のクエリは、2020 年 9 月 24 日の午前 0 時から午前 8 時の間のログをクエリします。開始時刻と終了時刻は、独自の要件に従って置き換えます。

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode
FROM "r53_rlogs"
WHERE (parse_datetime(query_timestamp,'yyyy-MM-dd''T''HH:mm:ss''Z')
     BETWEEN parse_datetime('2020-09-24-00:00:00','yyyy-MM-dd-HH:mm:ss') 
     AND parse_datetime('2020-09-24-00:08:00','yyyy-MM-dd-HH:mm:ss'))
ORDER BY query_timestamp DESC
```

## 例 3 – 指定された DNS クエリ名パターンに基づいてログをクエリする
<a name="querying-r53-resolver-logs-example-3-query-logs-based-on-a-specified-dns-query-name-pattern"></a>

以下のクエリは、クエリ名に文字列「example.com」が含まれたレコードを選択します。

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answers
FROM "r53_rlogs"
WHERE query_name LIKE '%example.com%'
ORDER BY query_timestamp DESC
```

## 例 4 – 応答のないログリクエストをクエリする
<a name="querying-r53-resolver-logs-example-4-query-log-requests-with-no-answer"></a>

以下のクエリは、リクエストが応答を受け取らなかったログエントリを選択します。

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answers
FROM "r53_rlogs"
WHERE cardinality(answers) = 0
```

## 例 5 – 特定の回答が含まれるログをクエリする
<a name="querying-r53-resolver-logs-example-5-query-logs-with-a-specific-answer"></a>

以下のクエリは、`answer.Rdata` 値に指定された IP アドレスがあるログを表示します。

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answer.Rdata
FROM "r53_rlogs"
CROSS JOIN UNNEST(r53_rlogs.answers) as st(answer)
WHERE answer.Rdata='203.0.113.16';
```

# Amazon SES イベントログをクエリする
<a name="querying-ses-logs"></a>

Amazon Athena を使用して、[Amazon Simple Email Service](https://aws.amazon.com/ses/) (Amazon SES) イベントログをクエリできます。

Amazon SES は、ユーザー独自の E メールアドレスとドメインを使用して E メールを送受信するための、簡単でコスト効率の高い方法を提供する E メールプラットフォームです。イベント、メトリクス、および統計を使用して、Amazon SES 送信アクティビティをきめ細かいレベルでモニタリングできます。

ユーザー定義の特性に基づいて、Amazon SES イベントを [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/)、[Amazon Data Firehose](https://aws.amazon.com/kinesis/data-firehose/)、または [Amazon Simple Notification Service](https://aws.amazon.com/sns/) に発行できます。Amazon S3 で情報を保存した後、Amazon Athena からクエリを実行できます。

Amazon SES イベントログデータでビューを作成し、ネストされた配列をフラット化する手順を含む Amazon SES ログの Athena `CREATE TABLE` ステートメントの例については、AWS ブログ記事「[Analyzing Amazon SES event data with AWS Analytics Services](https://aws.amazon.com/blogs/messaging-and-targeting/analyzing-amazon-ses-event-data-with-aws-analytics-services/)」の「Step 3: Using Amazon Athena to query the SES event logs」を参照してください。

# Amazon VPC フローログをクエリする
<a name="vpc-flow-logs"></a>

Amazon Virtual Private Cloud フローログは、VPC 内のネットワークインターフェイス間で送受信される IP トラフィックに関する情報をキャプチャします。このログを使用してネットワークトラフィックのパターンを調査し、VPC ネットワーク全体の脅威やリスクを特定します。

Amazon VPC フローログのクエリを実行するには、2 つの方法があります。

****
+ **Amazon VPC コンソール** — Amazon VPC コンソールの Athena 統合機能を使用して、パーティションを含む Athena データベース、ワークグループ、およびフローログテーブルを作成する CloudFormation テンプレートを生成します。テンプレートでは、[事前定義されたフローログのクエリ](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-athena.html#predefined-queries)のセットも作成します。これは、VPC を通過するトラフィックに関するインサイトの取得に使用できます。

  このアプローチの詳細については、「*Amazon VPC ユーザーガイド*」の「[Amazon Athena を使用したフローログのクエリ](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-athena.html)」を参照してください。
+ **Amazon Athena コンソール** — Athena コンソールでテーブルやクエリを直接作成します。詳細については、引き続きこのページを参照してください。

Athena でログのクエリを開始する前に、[VPC フローログを有効化](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/flow-logs.html)し、それらが Amazon S3 バケットに保存されるように設定します。ログを作成したら、それを数分間実行していくらかのデータを収集します。ログは、Athena で直接クエリできる GZIP 圧縮形式で作成されます。

VPC フローログの作成時に、フローログで返すフィールドおよびフィールドが表示される順序を指定する際は、カスタム形式を使用できます。フローログレコード詳細については、「*Amazon VPC ユーザーガイド*」の「[フローログレコード](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)」を参照してください。

## 考慮事項と制限事項
<a name="vpc-flow-logs-common-considerations"></a>

Athena で Amazon VPC フローログのテーブルを作成する際は、次の点に注意してください。
+ デフォルトでは、Parquet は名前で列にアクセスします。詳細については、「[スキーマの更新を処理する](handling-schema-updates-chapter.md)」を参照してください。
+ Athena の列名には、フローログレコードの名前を使用します。Athena スキーマの列名は、Amazon VPC フローログのフィールド名と完全に一致する必要があります。ただし、これらには次の違いがあります。
  + Amazon VPC のログフィールド名のハイフンは、Athena の列名ではアンダースコアに置き換えられます。Athena のデータベース名、テーブル名、および列名で使用できる文字については、「[データベース、テーブル、列に名前を付ける](tables-databases-columns-names.md)」を参照してください。
  + バックティックで囲むことで、Athena で[予約されたキーワード](reserved-words.md)であるフローログのレコード名をエスケープします。
+ VPC フローログは AWS アカウント 固有です。ログファイルを Amazon S3 に発行すると、Amazon VPC が Amazon S3 で作成するパスには、フローログの作成に使用された AWS アカウント の ID が含まれます。詳細については、「*Amazon VPC ユーザーガイド*」の「[フローログを Amazon S3 に発行する](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-s3.html)」を参照してください。

**Topics**
+ [考慮事項と制限事項](#vpc-flow-logs-common-considerations)
+ [Amazon VPC フローログのテーブルを作成し、クエリする](vpc-flow-logs-create-table-statement.md)
+ [Apache Parquet 形式でフローログのテーブルを作成する](vpc-flow-logs-parquet.md)
+ [パーティション射影を使用して Amazon VPC フローログのテーブルを作成およびクエリする](vpc-flow-logs-partition-projection.md)
+ [パーティション射影を使用して Apache Parquet 形式でフローログのテーブルを作成する](vpc-flow-logs-partition-projection-parquet-example.md)
+ [その他のリソース](query-examples-vpc-logs-additional-resources.md)

# Amazon VPC フローログのテーブルを作成し、クエリする
<a name="vpc-flow-logs-create-table-statement"></a>

次の手順では、Amazon VPC フローログ用の Amazon VPC テーブルを作成します。カスタム形式でフローログを作成する場合は、フローログの作成時に指定したフィールドと一致するフィールドを、それらに指定したものと同じ順序で使用してテーブルを作成します。

**Amazon VPC フローログ用の Athena テーブルを作成するには**

1. [考慮事項と制限事項](vpc-flow-logs.md#vpc-flow-logs-common-considerations) セクションのガイドラインに従って、次のような DDL ステートメントを Athena コンソールクエリエディタに入力します。サンプルステートメントは、「[フローログレコード](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)」に記載されているように、Amazon VPC フローログのバージョン 2 から 5 の列を持つテーブルを作成します。異なる列のセットまたは列の順序を使用する場合は、必要に応じてステートメントを変更します。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS `vpc_flow_logs` (
     version int,
     account_id string,
     interface_id string,
     srcaddr string,
     dstaddr string,
     srcport int,
     dstport int,
     protocol bigint,
     packets bigint,
     bytes bigint,
     start bigint,
     `end` bigint,
     action string,
     log_status string,
     vpc_id string,
     subnet_id string,
     instance_id string,
     tcp_flags int,
     type string,
     pkt_srcaddr string,
     pkt_dstaddr string,
     region string,
     az_id string,
     sublocation_type string,
     sublocation_id string,
     pkt_src_aws_service string,
     pkt_dst_aws_service string,
     flow_direction string,
     traffic_path int
   )
   PARTITIONED BY (`date` date)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY ' '
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/'
   TBLPROPERTIES ("skip.header.line.count"="1");
   ```

   次の点に注意してください。
   + このクエリは `ROW FORMAT DELIMITED` を指定し、SerDe の指定が省略されます。これは、クエリが [CSV、TSV、カスタム区切りファイル用の Lazy Simple SerDe](lazy-simple-serde.md) を使用しているということです。このクエリでは、フィールドはスペースで終了します。
   + `PARTITIONED BY` 句は、`date` 型を使用します。これにより、クエリで数学演算子を使用して、特定の日付より古いものまたは新しいものを選択できます。
**注記**  
`date` は DDL ステートメントの予約済みキーワードであるため、バックティック文字でエスケープされます。詳細については、「[クエリで予約キーワードをエスケープする](reserved-words.md)」を参照してください。
   + 異なるカスタム形式の VPC フローログの場合、フローログの作成時に指定したフィールドと一致するようにフィールドを変更します。

1. ログデータが含まれる Amazon S3 バケットをポイントするように `LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/'` を変更します。

1. Athena コンソールでクエリを実行します。クエリが完了すると、Athena が `vpc_flow_logs` テーブルを登録し、その中のデータに対してクエリを発行できるように準備します。

1. 次のサンプルクエリのように、パーティションを作成してデータを読み取れるようにします。このクエリは、指定日の 1 つのパーティションを作成します。必要に応じて、日付と場所のプレースホルダーを置き換えます。
**注記**  
このクエリは、指定日に対して単一のパーティションのみを作成します。プロセスを自動化するには、このクエリを実行し、この方法で `year/month/day` にパーティションを作成するスクリプトを使用するか、[パーティション射影](vpc-flow-logs-partition-projection.md)を指定する `CREATE TABLE` ステートメントを使用します。

   ```
   ALTER TABLE vpc_flow_logs
   ADD PARTITION (`date`='YYYY-MM-dd')
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/YYYY/MM/dd';
   ```

## vpc\$1flow\$1logs テーブルのクエリ例
<a name="query-examples-vpc-logs"></a>

Athena コンソールのクエリエディタを使用して、作成したテーブルで SQL ステートメントを実行します。クエリを保存したり、以前のクエリを表示したり、クエリ結果を CSV 形式でダウンロードできます。次の例では、`vpc_flow_logs` をテーブルの名前に置き換えます。また、要件に応じて列の値やその他の変数を変更します。

次のクエリ例では、指定された日付に対して最大 100 のフローログを一覧表示します。

```
SELECT * 
FROM vpc_flow_logs 
WHERE date = DATE('2020-05-04') 
LIMIT 100;
```

次のクエリは、すべての拒否された TCP 接続を一覧表示します。新しく作成した日付パーティション列 `date` を使用して、該当イベントが発生した週の曜日を抽出します。

```
SELECT day_of_week(date) AS
  day,
  date,
  interface_id,
  srcaddr,
  action,
  protocol
FROM vpc_flow_logs
WHERE action = 'REJECT' AND protocol = 6
LIMIT 100;
```

最大数の HTTPS リクエストを受信しているサーバーを確認するには、次のクエリを使用します。HTTPS ポート 443 で受信したパケット数をカウントし、送信先 IP アドレス別にグループ分けして、過去 1 週間の上位 10 のサーバーを返します。

```
SELECT SUM(packets) AS
  packetcount,
  dstaddr
FROM vpc_flow_logs
WHERE dstport = 443 AND date > current_date - interval '7' day
GROUP BY dstaddr
ORDER BY packetcount DESC
LIMIT 10;
```

# Apache Parquet 形式でフローログのテーブルを作成する
<a name="vpc-flow-logs-parquet"></a>

次の手順では、Apache Parquet 形式で Amazon VPC フローログ用の Amazon VPC テーブルを作成します。

**Parquet 形式で Amazon VPC フローログ用の Athena テーブルを作成するには**

1. [考慮事項と制限事項](vpc-flow-logs.md#vpc-flow-logs-common-considerations) セクションのガイドラインに従って、次のような DDL ステートメントを Athena コンソールクエリエディタに入力します。サンプルステートメントは、「[フローログレコード](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)」に記載されているように、1 時間ごとに Hive パーティションされる Parquet 形式で Amazon VPC フローログのバージョン 2 から 5 の列を持つテーブルを作成します。1 時間ごとのパーティションがない場合は、`PARTITIONED BY` 句から `hour` を削除します。

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs_parquet (
     version int,
     account_id string,
     interface_id string,
     srcaddr string,
     dstaddr string,
     srcport int,
     dstport int,
     protocol bigint,
     packets bigint,
     bytes bigint,
     start bigint,
     `end` bigint,
     action string,
     log_status string,
     vpc_id string,
     subnet_id string,
     instance_id string,
     tcp_flags int,
     type string,
     pkt_srcaddr string,
     pkt_dstaddr string,
     region string,
     az_id string,
     sublocation_type string,
     sublocation_id string,
     pkt_src_aws_service string,
     pkt_dst_aws_service string,
     flow_direction string,
     traffic_path int
   )
   PARTITIONED BY (
     `aws-account-id` string,
     `aws-service` string,
     `aws-region` string,
     `year` string, 
     `month` string, 
     `day` string,
     `hour` string
   )
   ROW FORMAT SERDE 
     'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/prefix/AWSLogs/'
   TBLPROPERTIES (
     'EXTERNAL'='true', 
     'skip.header.line.count'='1'
     )
   ```

1. ログデータが含まれる Amazon S3 パスをポイントするようにサンプル `LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/'` を変更します。

1. Athena コンソールでクエリを実行します。

1. Hive 互換形式のデータの場合、Athena コンソールで次のコマンドを実行して、メタストアの Hive パーティションを更新およびロードします。クエリが完了すると、`vpc_flow_logs_parquet` テーブルでデータをクエリできます。

   ```
   MSCK REPAIR TABLE vpc_flow_logs_parquet
   ```

   Hive 互換データを使用していない場合は、[ALTER TABLE ADD PARTITION](alter-table-add-partition.md) を実行してパーティションをロードします。

Athena を使用して、Parquet 形式の Amazon VPC フローログをクエリする方法については、「*AWS ビッグデータブログ*」の「[Apache Parquet 形式の VPC フローログを使用して、ネットワーク分析のパフォーマンスを最適化し、そのコストを削減する](https://aws.amazon.com/blogs/big-data/optimize-performance-and-reduce-costs-for-network-analytics-with-vpc-flow-logs-in-apache-parquet-format/)」を参照してください。

# パーティション射影を使用して Amazon VPC フローログのテーブルを作成およびクエリする
<a name="vpc-flow-logs-partition-projection"></a>

次のような `CREATE TABLE` ステートメントを使用してテーブルを作成およびパーティションし、[パーティション射影](partition-projection.md)を使用してパーティションを自動的に入力します。サンプルのテーブル名 `test_table_vpclogs` をそのテーブルの名前に置き換えます。Amazon VPC ログデータが含まれている Amazon S3 バケットを指定するように `LOCATION` 句を編集します。

次は、非 Hive スタイルのパーティション形式で配信される VPC フローログ用の `CREATE TABLE` ステートメントです。この例では、マルチアカウント集計が可能です。複数のアカウントからの VPC フローログを 1 つの Amazon S3 バケットに集中管理する場合は、アカウント ID を Amazon S3 パスに入力する必要があります。

```
CREATE EXTERNAL TABLE IF NOT EXISTS test_table_vpclogs (
  version int,
  account_id string,
  interface_id string,
  srcaddr string,
  dstaddr string,
  srcport int,
  dstport int,
  protocol bigint,
  packets bigint,
  bytes bigint,
  start bigint,
  `end` bigint,
  action string,
  log_status string,
  vpc_id string,
  subnet_id string,
  instance_id string,
  tcp_flags int,
  type string,
  pkt_srcaddr string,
  pkt_dstaddr string,
  az_id string,
  sublocation_type string,
  sublocation_id string,
  pkt_src_aws_service string,
  pkt_dst_aws_service string,
  flow_direction string,
  traffic_path int
)
PARTITIONED BY (accid string, region string, day string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION '$LOCATION_OF_LOGS'
TBLPROPERTIES
(
"skip.header.line.count"="1",
"projection.enabled" = "true",
"projection.accid.type" = "enum",
"projection.accid.values" = "$ACCID_1,$ACCID_2",
"projection.region.type" = "enum",
"projection.region.values" = "$REGION_1,$REGION_2,$REGION_3",
"projection.day.type" = "date",
"projection.day.range" = "$START_RANGE,NOW",
"projection.day.format" = "yyyy/MM/dd",
"storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/${accid}/vpcflowlogs/${region}/${day}"
)
```

## test\$1table\$1vpclogs のクエリ例
<a name="query-examples-vpc-logs-pp"></a>

次のクエリ例では、前述の `CREATE TABLE` ステートメントで作成された `test_table_vpclogs` のクエリを実行します。クエリの `test_table_vpclogs` を独自のテーブルの名前で置き換えます。また、要件に応じて列の値やその他の変数を変更します。

指定された期間の最初の 100 個のアクセスログエントリを時系列順に返すには、次のようなクエリを実行します。

```
SELECT *
FROM test_table_vpclogs
WHERE day >= '2021/02/01' AND day < '2021/02/28'
ORDER BY day ASC
LIMIT 100
```

指定された期間に上位 10 個の HTTP パケットを受信したサーバーを表示するには、次のようなクエリを実行します。このクエリは、HTTPS ポート 443 で受信したパケット数をカウントし、送信先 IP アドレス別にグループ分けして、過去 1 週間の上位 10 エントリを返します。

```
SELECT SUM(packets) AS packetcount, 
       dstaddr
FROM test_table_vpclogs
WHERE dstport = 443
  AND day >= '2021/03/01'
  AND day < '2021/03/31'
GROUP BY dstaddr
ORDER BY packetcount DESC
LIMIT 10
```

指定された期間内に作成されたログを返すには、次のようなクエリを実行します。

```
SELECT interface_id,
       srcaddr,
       action,
       protocol,
       to_iso8601(from_unixtime(start)) AS start_time,
       to_iso8601(from_unixtime("end")) AS end_time
FROM test_table_vpclogs
WHERE DAY >= '2021/04/01'
  AND DAY < '2021/04/30'
```

指定された期間の送信元 IP アドレスのアクセスログを返すには、次のようなクエリを実行します。

```
SELECT *
FROM test_table_vpclogs
WHERE srcaddr = '10.117.1.22'
  AND day >= '2021/02/01'
  AND day < '2021/02/28'
```

すべての拒否された TCP 接続を一覧表示するには、次のようなクエリを実行します。

```
SELECT day,
       interface_id,
       srcaddr,
       action,
       protocol
FROM test_table_vpclogs
WHERE action = 'REJECT' AND protocol = 6 AND day >= '2021/02/01' AND day < '2021/02/28'
LIMIT 10
```

`10.117` で始まる IP アドレス範囲のアクセスログを返すには、次のようなクエリを実行します。

```
SELECT *
FROM test_table_vpclogs
WHERE split_part(srcaddr,'.', 1)='10'
  AND split_part(srcaddr,'.', 2) ='117'
```

特定の時間範囲内の送信先 IP アドレスのアクセスログを返すには、次のようなクエリを実行します。

```
SELECT *
FROM test_table_vpclogs
WHERE dstaddr = '10.0.1.14'
  AND day >= '2021/01/01'
  AND day < '2021/01/31'
```

# パーティション射影を使用して Apache Parquet 形式でフローログのテーブルを作成する
<a name="vpc-flow-logs-partition-projection-parquet-example"></a>

次の VPC フローログのパーティション射影 `CREATE TABLE` ステートメントは Apache Parquet 形式であり、Hive と互換性がなく、曜日ではなく時間と日付でパーティショニングされています。サンプルのテーブル名 `test_table_vpclogs_parquet` をそのテーブルの名前に置き換えます。Amazon VPC ログデータが含まれている Amazon S3 バケットを指定するように `LOCATION` 句を編集します。

```
CREATE EXTERNAL TABLE IF NOT EXISTS test_table_vpclogs_parquet (
  version int,
  account_id string,
  interface_id string,
  srcaddr string,
  dstaddr string,
  srcport int,
  dstport int,
  protocol bigint,
  packets bigint,
  bytes bigint,
  start bigint,
  `end` bigint,
  action string,
  log_status string,
  vpc_id string,
  subnet_id string,
  instance_id string,
  tcp_flags int,
  type string,
  pkt_srcaddr string,
  pkt_dstaddr string,
  az_id string,
  sublocation_type string,
  sublocation_id string,
  pkt_src_aws_service string,
  pkt_dst_aws_service string,
  flow_direction string,
  traffic_path int
)
PARTITIONED BY (region string, date string, hour string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/'
TBLPROPERTIES (
"EXTERNAL"="true",
"skip.header.line.count" = "1",
"projection.enabled" = "true",
"projection.region.type" = "enum",
"projection.region.values" = "us-east-1,us-west-2,ap-south-1,eu-west-1",
"projection.date.type" = "date",
"projection.date.range" = "2021/01/01,NOW",
"projection.date.format" = "yyyy/MM/dd",
"projection.hour.type" = "integer",
"projection.hour.range" = "00,23",
"projection.hour.digits" = "2",
"storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/AWSLogs/${account_id}/vpcflowlogs/${region}/${date}/${hour}"
)
```

# その他のリソース
<a name="query-examples-vpc-logs-additional-resources"></a>

Athena を使用して VPC フローログを分析する方法の詳細については、次の「AWS Big Data Blog」の記事を参照してください。
+ [ポイントアンドクリック Amazon Athena インテグレーションを使用した VPC フローログの分析](https://aws.amazon.com/blogs/networking-and-content-delivery/analyze-vpc-flow-logs-with-point-and-click-amazon-athena-integration/) 
+ [Amazon Athena および Quick を使用した VPC フローログの分析](https://aws.amazon.com/blogs/big-data/analyzing-vpc-flow-logs-using-amazon-athena-and-amazon-quicksight/)
+ [Apache Parquet 形式の VPC フローログでパフォーマンスを最適化し、ネットワーク分析のコストを削減する](https://aws.amazon.com/blogs/big-data/optimize-performance-and-reduce-costs-for-network-analytics-with-vpc-flow-logs-in-apache-parquet-format/)

# AWS WAF ログをクエリする
<a name="waf-logs"></a>

AWS WAF は、保護されたウェブアプリケーションがクライアントから受信する HTTP および HTTPS リクエストを監視して制御できるようにするウェブアプリケーションファイアウォールです。AWS WAF ウェブアクセスコントロールリスト (ACL) 内のルールを設定することにより、ウェブリクエストの処理方法を定義します。その後、ウェブアプリケーションにウェブ ACL を関連付けて保護します。AWS WAF で保護できるウェブアプリケーションリソースの例には、Amazon CloudFront ディストリビューション、Amazon API Gateway REST API、Application Load Balancers などがあります。AWS WAF の詳細については、「*AWS WAF デベロッパーガイド*」の「[AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html)」を参照してください。

AWS WAF ログには、AWS WAF が AWS リソースからリクエストを受信した時間、このリクエストの詳細、各リクエストが適合したルールに対するアクションなど、ウェブ ACL によって分析されたトラフィックに関する情報が含まれます。

AWS WAF ウェブ ACL を設定して、複数の宛先のいずれかにログを発行し、そこでクエリを実行して表示できます。ウェブ ACL ログの設定および AWS WAF ログの内容の詳細については、「*AWS WAF デベロッパーガイド*」の「[AWS WAF ウェブ ACL トラフィックのログ](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html)」を参照してください。

Athena を利用して脅威検出と潜在的なセキュリティ攻撃に関するインサイトを得るために AWS WAF ログを分析する方法については、AWS ネットワークとコンテンツ配信のブログ記事「[How to use Amazon Athena queries to analyze AWS WAF logs and provide the visibility needed for threat detection](https://aws.amazon.com/blogs/networking-and-content-delivery/how-to-use-amazon-athena-queries-to-analyze-aws-waf-logs-and-provide-the-visibility-needed-for-threat-detection/)」を参照してください。

AWS WAF ログを中央データレイクリポジトリに集約して、それらを Athena でクエリする方法の例については、「AWS ビッグデータブログ」のブログ記事「[Analyzing AWS WAF logs with OpenSearch Service, Amazon Athena, and Quick](https://aws.amazon.com/blogs/big-data/analyzing-aws-waf-logs-with-amazon-es-amazon-athena-and-amazon-quicksight/)」を参照してください。

このトピックでは、パーティション射影、手動パーティショニング、およびパーティショニングを使用しない `CREATE TABLE` ステートメントの例を示します。

**注記**  
このトピックの `CREATE TABLE` ステートメントは、v1 および v2 AWS WAF ログの両方に使用できます。v1 では、`webaclid` フィールドに ID が含まれます。v2 では、`webaclid` フィールドに完全な ARN が含まれます。ここでの `CREATE TABLE` ステートメントは、`string` データ型を使用して、アグノスティックにこのコンテンツを取り扱います。

**Topics**
+ [パーティション射影を使用して Athena で AWS WAF S3 ログ用テーブルを作成する](create-waf-table-partition-projection.md)
+ [手動パーティショニングを使用して Athena で AWS WAF S3 ログ用テーブルを作成する](create-waf-table-manual-partition.md)
+ [パーティショニングなしで AWS WAF ログのテーブルを作成する](create-waf-table.md)
+ [AWS WAF ログのクエリ例](query-examples-waf-logs.md)

# パーティション射影を使用して Athena で AWS WAF S3 ログ用テーブルを作成する
<a name="create-waf-table-partition-projection"></a>

AWS WAF ログには、パーティションスキームを事前に指定できる既知の構造があるため、Athena の[パーティション射影](partition-projection.md)機能を使用することで、クエリランタイムを短縮し、パーティション管理を自動化することが可能です。新しいデータが追加されると、パーティション射影は新しいパーティションを自動で追加します。このため、`ALTER TABLE ADD PARTITION` を使用してパーティションを手動で追加する必要がなくなります。

次の `CREATE TABLE` ステートメント例では、指定された日付から現在までの 4 つの異なる AWS WAF リージョンの AWS ログで、パーティション射影を自動的に使用しています。この例の `PARTITION BY` 句は地域と日付でパーティショニングしますが、要件に応じてこれを変更できます。ログ出力と一致するように、必要に応じてフィールドを変更します。`LOCATION` および `storage.location.template` 句では、*amzn-s3-demo-bucket* と *AWS\$1ACCOUNT\$1NUMBER* の各プレースホルダーを AWS WAF ログの Amazon S3 バケットの場所を特定する値に置き換えます。`projection.day.range` では、*2021*/*01*/*01* を使用を開始する日に置き換えます。クエリが正常に実行されると、テーブルをクエリできます。パーティションをロードするのに、`ALTER TABLE ADD PARTITION` を実行する必要はありません。

```
CREATE EXTERNAL TABLE `waf_logs_partition_projection`(
  `timestamp` bigint, 
  `formatversion` int, 
  `webaclid` string, 
  `terminatingruleid` string, 
  `terminatingruletype` string, 
  `action` string, 
  `terminatingrulematchdetails` array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>, 
  `httpsourcename` string, 
  `httpsourceid` string, 
  `rulegrouplist` array<struct<rulegroupid:string,terminatingrule:struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>>,nonterminatingmatchingrules:array<struct<ruleid:string,action:string,overriddenaction:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>,excludedrules:string>>, 
  `ratebasedrulelist` array<struct<ratebasedruleid:string,limitkey:string,maxrateallowed:int>>, 
  `nonterminatingmatchingrules` array<struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>, 
  `requestheadersinserted` array<struct<name:string,value:string>>, 
  `responsecodesent` string, 
  `httprequest` struct<clientip:string,country:string,headers:array<struct<name:string,value:string>>,uri:string,args:string,httpversion:string,httpmethod:string,requestid:string,fragment:string,scheme:string,host:string>,
  `labels` array<struct<name:string>>, 
  `captcharesponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `challengeresponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `ja3fingerprint` string, 
  `ja4fingerprint` string, 
  `oversizefields` string, 
  `requestbodysize` int, 
  `requestbodysizeinspectedbywaf` int)
  PARTITIONED BY ( 
   `log_time` string)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/testui/'
TBLPROPERTIES (
 'projection.enabled'='true',
  'projection.log_time.format'='yyyy/MM/dd/HH/mm',
  'projection.log_time.interval'='1',
  'projection.log_time.interval.unit'='minutes',
  'projection.log_time.range'='2025/01/01/00/00,NOW',
  'projection.log_time.type'='date',
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/testui/${log_time}')
```

**注記**  
この例にある `LOCATION` 句のパスの形式は標準ですが、実装した AWS WAF 設定によって異なる場合があります。例えば、次の例の AWS WAF ログパスは CloudFront 分散用です。  

```
s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/cloudfronyt/2025/01/01/00/00/
```
AWS WAF ログテーブルの作成またはクエリ中に問題が発生した場合は、ログデータの場所を確定するか、[サポート までお問い合わせください](https://console.aws.amazon.com/support/home/)。

パーティション射影の詳細については、「[Amazon Athena でパーティション射影を使用する](partition-projection.md)」を参照してください。

# 手動パーティショニングを使用して Athena で AWS WAF S3 ログ用テーブルを作成する
<a name="create-waf-table-manual-partition"></a>

このセクションでは、手動パーティショニングを使用して AWS WAF ログのテーブルを作成する方法について説明します。

`LOCATION` および `storage.location.template` 句では、*amzn-s3-demo-bucket* と *AWS\$1ACCOUNT\$1NUMBER* の各プレースホルダーを AWS WAF ログの Amazon S3 バケットの場所を特定する値に置き換えます。

```
CREATE EXTERNAL TABLE `waf_logs_manual_partition`(
  `timestamp` bigint, 
  `formatversion` int, 
  `webaclid` string, 
  `terminatingruleid` string, 
  `terminatingruletype` string, 
  `action` string, 
  `terminatingrulematchdetails` array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>, 
  `httpsourcename` string, 
  `httpsourceid` string, 
  `rulegrouplist` array<struct<rulegroupid:string,terminatingrule:struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>>,nonterminatingmatchingrules:array<struct<ruleid:string,action:string,overriddenaction:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>,excludedrules:string>>, 
  `ratebasedrulelist` array<struct<ratebasedruleid:string,limitkey:string,maxrateallowed:int>>, 
  `nonterminatingmatchingrules` array<struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>, 
  `requestheadersinserted` array<struct<name:string,value:string>>, 
  `responsecodesent` string, 
  `httprequest` struct<clientip:string,country:string,headers:array<struct<name:string,value:string>>,uri:string,args:string,httpversion:string,httpmethod:string,requestid:string,fragment:string,scheme:string,host:string>, 
  `labels` array<struct<name:string>>, 
  `captcharesponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `challengeresponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `ja3fingerprint` string, 
  `ja4fingerprint` string, 
  `oversizefields` string, 
  `requestbodysize` int, 
  `requestbodysizeinspectedbywaf` int)
  PARTITIONED BY ( `year` string, `month` string, `day` string, `hour` string, `min` string)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/webacl/'
```

# パーティショニングなしで AWS WAF ログのテーブルを作成する
<a name="create-waf-table"></a>

このセクションでは、パーティショニングまたはパーティション射影を使用せずに AWS WAF ログのテーブルを作成する方法について説明します。

**注記**  
パフォーマンスおよびコスト上の理由により、クエリにパーティション化されていないスキーマを使用することは推奨されません。詳細については、「AWS Big Data Blog」の「[Amazon Athena のパフォーマンスチューニング Tips トップ 10](https://aws.amazon.com/blogs/big-data/top-10-performance-tuning-tips-for-amazon-athena/)」を参照してください。

**AWS WAF テーブルを作成するには**

1. 次の DDL ステートメントをコピーして Athena コンソール内に貼り付けます。ログ出力と一致するように、必要に応じてフィールドを変更します。ログを保存するバケットに対応するように Amazon S3 バケットの `LOCATION` を変更します。

   このクエリでは、[OpenX JSON SerDe](openx-json-serde.md) を使用します。
**注記**  
SerDe では、各 JSON ドキュメントが、レコード内のフィールドを区切る行終端文字なしの、1 行のテキストに収まっていることを想定しています。JSON テキストがプリティプリント形式の場合、テーブルを作成した後にクエリを実行しようとすると、以下のようなエラーメッセージが表示される場合があります。「HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object」、または「HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT」。詳細については、GitHub の OpenX SerDe のドキュメントで「[JSON Data Files](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)」(JSON データファイル) を参照してください。

   ```
   CREATE EXTERNAL TABLE `waf_logs`(
     `timestamp` bigint,
     `formatversion` int,
     `webaclid` string,
     `terminatingruleid` string,
     `terminatingruletype` string,
     `action` string,
     `terminatingrulematchdetails` array <
                                       struct <
                                           conditiontype: string,
                                           sensitivitylevel: string,
                                           location: string,
                                           matcheddata: array < string >
                                             >
                                        >,
     `httpsourcename` string,
     `httpsourceid` string,
     `rulegrouplist` array <
                         struct <
                             rulegroupid: string,
                             terminatingrule: struct <
                                                 ruleid: string,
                                                 action: string,
                                                 rulematchdetails: array <
                                                                      struct <
                                                                          conditiontype: string,
                                                                          sensitivitylevel: string,
                                                                          location: string,
                                                                          matcheddata: array < string >
                                                                             >
                                                                       >
                                                   >,
                             nonterminatingmatchingrules: array <
                                                                 struct <
                                                                     ruleid: string,
                                                                     action: string,
                                                                     overriddenaction: string,
                                                                     rulematchdetails: array <
                                                                                          struct <
                                                                                              conditiontype: string,
                                                                                              sensitivitylevel: string,
                                                                                              location: string,
                                                                                              matcheddata: array < string >
                                                                                                 >
                                                                      >,
                                                                     challengeresponse: struct <
                                                                               responsecode: string,
                                                                               solvetimestamp: string
                                                                                 >,
                                                                     captcharesponse: struct <
                                                                               responsecode: string,
                                                                               solvetimestamp: string
                                                                                 >
                                                                       >
                                                                >,
                             excludedrules: string
                               >
                          >,
   `ratebasedrulelist` array <
                            struct <
                                ratebasedruleid: string,
                                limitkey: string,
                                maxrateallowed: int
                                  >
                             >,
     `nonterminatingmatchingrules` array <
                                       struct <
                                           ruleid: string,
                                           action: string,
                                           rulematchdetails: array <
                                                                struct <
                                                                    conditiontype: string,
                                                                    sensitivitylevel: string,
                                                                    location: string,
                                                                    matcheddata: array < string >
                                                                       >
                                                                >,
                                           challengeresponse: struct <
                                                               responsecode: string,
                                                               solvetimestamp: string
                                                                >,
                                           captcharesponse: struct <
                                                               responsecode: string,
                                                               solvetimestamp: string
                                                                >
                                             >
                                        >,
     `requestheadersinserted` array <
                                   struct <
                                       name: string,
                                       value: string
                                         >
                                    >,
     `responsecodesent` string,
     `httprequest` struct <
                       clientip: string,
                       country: string,
                       headers: array <
                                   struct <
                                       name: string,
                                       value: string
                                         >
                                    >,
                       uri: string,
                       args: string,
                       httpversion: string,
                       httpmethod: string,
                       requestid: string
                         >,
     `labels` array <
                  struct <
                      name: string
                        >
                   >,
     `captcharesponse` struct <
                           responsecode: string,
                           solvetimestamp: string,
                           failureReason: string
                             >,
     `challengeresponse` struct <
                           responsecode: string,
                           solvetimestamp: string,
                           failureReason: string
                           >,
     `ja3Fingerprint` string,
     `oversizefields` string,
     `requestbodysize` int,
     `requestbodysizeinspectedbywaf` int
   )
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
   STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/prefix/'
   ```

1. Athena コンソールのクエリエディタで `CREATE EXTERNAL TABLE` ステートメントを実行します。これで `waf_logs` テーブルが登録され、その中のデータを Athena からのクエリに使用できるようになります。

# AWS WAF ログのクエリ例
<a name="query-examples-waf-logs"></a>

このセクションの多くのクエリ例では、前に作成したパーティション射影テーブルを使用します。また、要件に応じて例のテーブル名、列の値、その他の変数を変更します。クエリのパフォーマンスを改善してコストを削減するには、フィルター条件にパーティション列を追加します。

**Topics**
+ [カウントリファラー、IP アドレス、一致ルール](query-examples-waf-logs-count.md)
+ [日付と時刻を使用してクエリする](query-examples-waf-logs-date-time.md)
+ [ブロックされたリクエストまたはアドレスをクエリする](query-examples-waf-logs-blocked-requests.md)

# カウントリファラー、IP アドレス、一致ルール
<a name="query-examples-waf-logs-count"></a>

このセクションの例では、対象となるログ項目のカウントをクエリします。
+ [Count the number of referrers that contain a specified term](#waf-example-count-referrers-with-specified-term)
+ [Count all matched IP addresses in the last 10 days that have matched excluded rules](#waf-example-count-matched-ip-addresses)
+ [Group all counted managed rules by the number of times matched](#waf-example-group-managed-rules-by-times-matched)
+ [Group all counted custom rules by number of times matched](#waf-example-group-custom-rules-by-times-matched)

**Example – 指定された用語を含むリファラーの数を計上する**  
次のクエリは、指定された日付範囲内での「amazon」という用語を含むリファラーの数を計上します。  

```
WITH test_dataset AS 
  (SELECT header FROM waf_logs
    CROSS JOIN UNNEST(httprequest.headers) AS t(header) WHERE "date" >= '2021/03/01'
    AND "date" < '2021/03/31')
SELECT COUNT(*) referer_count 
FROM test_dataset 
WHERE LOWER(header.name)='referer' AND header.value LIKE '%amazon%'
```

**Example – 一致する除外ルールがある、過去 10 日間のすべての一致した IP アドレスを計上する**  
次のクエリは、IP アドレスがルールグループ内の除外ルールに一致した過去 10 日間の回数を計上します。  

```
WITH test_dataset AS 
  (SELECT * FROM waf_logs 
    CROSS JOIN UNNEST(rulegrouplist) AS t(allrulegroups))
SELECT 
  COUNT(*) AS count, 
  "httprequest"."clientip", 
  "allrulegroups"."excludedrules",
  "allrulegroups"."ruleGroupId"
FROM test_dataset 
WHERE allrulegroups.excludedrules IS NOT NULL AND from_unixtime(timestamp/1000) > now() - interval '10' day
GROUP BY "httprequest"."clientip", "allrulegroups"."ruleGroupId", "allrulegroups"."excludedrules"
ORDER BY count DESC
```

**Example – カウントされたすべてのマネージドルールをマッチした回数でグループ化する**  
2022 年 10 月 27 日より前にウェブ ACL 設定でルールグループのルールアクションをカウントに設定した場合、AWS WAF はウェブ ACL JSON 内のオーバーライドを `excludedRules` として保存しました。これで、ルールをカウントにオーバーライドする JSON 設定が `ruleActionOverrides` 設定に追加されました。詳しくは、「*AWS WAF デベロッパーガイド*」の「[ルールグループのアクションオーバーライド](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-rule-group-override-options.html)」をご覧ください。新しいログ構造からカウントモードのマネージドルールを抽出するには、次の例のように、`excludedRules` フィールドの代わりに `ruleGroupList` セクションの `nonTerminatingMatchingRules` をクエリします。  

```
SELECT
 count(*) AS count,
 httpsourceid,
 httprequest.clientip,
 t.rulegroupid, 
 t.nonTerminatingMatchingRules
FROM "waf_logs" 
CROSS JOIN UNNEST(rulegrouplist) AS t(t) 
WHERE action <> 'BLOCK' AND cardinality(t.nonTerminatingMatchingRules) > 0 
GROUP BY t.nonTerminatingMatchingRules, action, httpsourceid, httprequest.clientip, t.rulegroupid 
ORDER BY "count" DESC 
Limit 50
```

**Example – カウントされたすべてのカスタムルールをマッチした回数でグループ化する**  
次のクエリは、カウントされたすべてのカスタムルールをマッチした回数でグループ化します。  

```
SELECT
  count(*) AS count,
         httpsourceid,
         httprequest.clientip,
         t.ruleid,
         t.action
FROM "waf_logs" 
CROSS JOIN UNNEST(nonterminatingmatchingrules) AS t(t) 
WHERE action <> 'BLOCK' AND cardinality(nonTerminatingMatchingRules) > 0 
GROUP BY t.ruleid, t.action, httpsourceid, httprequest.clientip 
ORDER BY "count" DESC
Limit 50
```

カスタムルールとマネージドルールグループのログの場所については、「*AWS WAF デベロッパーガイド*」の「[モニタリングとチューニング](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-testing-activities.html)」を参照してください。

# 日付と時刻を使用してクエリする
<a name="query-examples-waf-logs-date-time"></a>

このセクションの例には、日付と時刻の値を使用するクエリが含まれています。
+ [Return the timestamp field in human-readable ISO 8601 format](#waf-example-return-human-readable-timestamp)
+ [Return records from the last 24 hours](#waf-example-return-records-last-24-hours)
+ [Return records for a specified date range and IP address](#waf-example-return-records-date-range-and-ip)
+ [For a specified date range, count the number of IP addresses in five minute intervals](#waf-example-count-ip-addresses-in-date-range)
+ [Count the number of X-Forwarded-For IP in the last 10 days](#waf-example-count-x-forwarded-for-ip)

**Example – 人が読み込み可能な ISO 8601 形式のタイムスタンプフィールドを返す**  
次のクエリは、`from_unixtime` および `to_iso8601` 関数を使用して、`timestamp` フィールドを人が読み込み可能な ISO 8601 形式 (例えば、`1576280412771` ではなく `2019-12-13T23:40:12.000Z` ) で返します。このクエリは、HTTP ソース名、ソース ID、およびリクエストも返します。  

```
SELECT to_iso8601(from_unixtime(timestamp / 1000)) as time_ISO_8601,
       httpsourcename,
       httpsourceid,
       httprequest
FROM waf_logs
LIMIT 10;
```

**Example – 過去 24 時間のレコードを返す**  
次のクエリは、`WHERE` 句でフィルターを使用して、過去 24 時間のレコードに関する HTTP ソース名、HTTP ソース ID、および HTTP リクエストフィールドを返します。  

```
SELECT to_iso8601(from_unixtime(timestamp/1000)) AS time_ISO_8601, 
       httpsourcename, 
       httpsourceid, 
       httprequest 
FROM waf_logs
WHERE from_unixtime(timestamp/1000) > now() - interval '1' day
LIMIT 10;
```

**Example – 指定された日付範囲と IP アドレスのレコードを返す**  
次のクエリは、指定されたクライアント IP アドレスの指定された日付範囲内のレコードをリストします。  

```
SELECT * 
FROM waf_logs 
WHERE httprequest.clientip='53.21.198.66' AND "date" >= '2021/03/01' AND "date" < '2021/03/31'
```

**Example – 指定された日付範囲について、5 分間隔で IP アドレスの数を計上する**  
次のクエリは、特定の日付範囲について、5 分間隔で IP アドレスの数を計上します。  

```
WITH test_dataset AS 
  (SELECT 
     format_datetime(from_unixtime((timestamp/1000) - ((minute(from_unixtime(timestamp / 1000))%5) * 60)),'yyyy-MM-dd HH:mm') AS five_minutes_ts,
     "httprequest"."clientip" 
     FROM waf_logs 
     WHERE "date" >= '2021/03/01' AND "date" < '2021/03/31')
SELECT five_minutes_ts,"clientip",count(*) ip_count 
FROM test_dataset 
GROUP BY five_minutes_ts,"clientip"
```

**Example – 過去 10 日間の X-Forwarded-For IP の数をカウントする**  
次のクエリは、リクエストヘッダーをフィルタリングし、過去 10 日間の X-Forwarded-For IP の数をカウントします。  

```
WITH test_dataset AS
  (SELECT header
   FROM waf_logs
   CROSS JOIN UNNEST (httprequest.headers) AS t(header)
   WHERE from_unixtime("timestamp"/1000) > now() - interval '10' DAY) 
SELECT header.value AS ip,
       count(*) AS COUNT 
FROM test_dataset 
WHERE header.name='X-Forwarded-For' 
GROUP BY header.value 
ORDER BY COUNT DESC
```

日付関数と時刻関数の詳細については、Trino ドキュメントの「[Date and Time Functions and Operators](https://trino.io/docs/current/functions/datetime.html)」(日付と時刻の関数と演算子) を参照してください。

# ブロックされたリクエストまたはアドレスをクエリする
<a name="query-examples-waf-logs-blocked-requests"></a>

このセクションの例では、ブロックされたリクエストまたはアドレスをクエリします。
+ [Extract the top 100 IP addresses blocked by a specified rule type](#waf-example-extract-top-100-blocked-ip-by-rule)
+ [Count the number of times a request from a specified country has been blocked](#waf-example-count-request-blocks-from-country)
+ [Count the number of times a request has been blocked, grouping by specific attributes](#waf-example-count-request-blocks-by-attribute)
+ [Count the number of times a specific terminating rule ID has been matched](#waf-example-count-terminating-rule-id-matches)
+ [Retrieve the top 100 IP addresses blocked during a specified date range](#waf-example-top-100-ip-addresses-blocked-for-date-range)

**Example – 指定されたルールタイプによってブロックされた上位 100 個の IP アドレスを抽出する**  
次のクエリは、指定した日付範囲内で `RATE_BASED` 終了ルールによってブロックされた上位 100 個の IP アドレスを抽出し、計上します。  

```
SELECT COUNT(httpRequest.clientIp) as count,
httpRequest.clientIp
FROM waf_logs
WHERE terminatingruletype='RATE_BASED' AND action='BLOCK' and "date" >= '2021/03/01'
AND "date" < '2021/03/31'
GROUP BY httpRequest.clientIp
ORDER BY count DESC
LIMIT 100
```

**Example – 指定された国からのリクエストがブロックされた回数を計上する**  
次のクエリは、アイルランド (IE) に属し、`RATE_BASED` 終了ルールによってブロックされた IP アドレスからリクエストが到着した回数を数えます。  

```
SELECT 
  COUNT(httpRequest.country) as count, 
  httpRequest.country 
FROM waf_logs
WHERE 
  terminatingruletype='RATE_BASED' AND 
  httpRequest.country='IE'
GROUP BY httpRequest.country
ORDER BY count
LIMIT 100;
```

**Example – リクエストがブロックされた回数を計上し、特定の属性でグループ化する**  
次のクエリは、リクエストがブロックされた回数をカウントし、結果を WebACL、RuleId、ClientIP、および HTTP リクエスト URI によってグループ化します。  

```
SELECT 
  COUNT(*) AS count,
  webaclid,
  terminatingruleid,
  httprequest.clientip,
  httprequest.uri
FROM waf_logs
WHERE action='BLOCK'
GROUP BY webaclid, terminatingruleid, httprequest.clientip, httprequest.uri
ORDER BY count DESC
LIMIT 100;
```

**Example – 特定の終了ルール ID が一致した回数を計上する**  
次のクエリは、特定の終了ルール ID が (`WHERE terminatingruleid='e9dd190d-7a43-4c06-bcea-409613d9506e'`) に一致した回数を計上します。その結果を WebACL、Action、ClientIP、および HTTP Request URI によってグループ化します。  

```
SELECT 
  COUNT(*) AS count,
  webaclid,
  action,
  httprequest.clientip,
  httprequest.uri
FROM waf_logs
WHERE terminatingruleid='e9dd190d-7a43-4c06-bcea-409613d9506e'
GROUP BY webaclid, action, httprequest.clientip, httprequest.uri
ORDER BY count DESC
LIMIT 100;
```

**Example – 指定した日付範囲内でブロックされた上位 100 個の IP アドレスを取得する**  
次のクエリは、指定された日付範囲内でブロックされた上位 100 個の IP アドレスを抽出します。このクエリは、IP アドレスがブロックされた回数もリストします。  

```
SELECT "httprequest"."clientip", "count"(*) "ipcount", "httprequest"."country"
FROM waf_logs
WHERE "action" = 'BLOCK' and "date" >= '2021/03/01'
AND "date" < '2021/03/31'
GROUP BY "httprequest"."clientip", "httprequest"."country"
ORDER BY "ipcount" DESC limit 100
```

Amazon S3 のクエリについては、以下のトピックを参照してください。
+ AWS ナレッジセンターの「[Athena を使用して Amazon S3 サーバーのアクセスログを分析するにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/analyze-logs-athena/)」
+ 「Amazon Simple Storage Service ユーザーガイド」の「[Amazon Athena を使用してリクエストのアクセスログをクエリする](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-s3-access-logs-to-identify-requests.html#querying-s3-access-logs-for-requests)」
+ Amazon Simple Storage Service ユーザーガイドの「[AWS CloudTrail を使用した Amazon S3 リクエストの識別](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudtrail-request-identification.html)」

# Amazon S3 に保存されたウェブサーバーログをクエリする
<a name="querying-web-server-logs"></a>

Athena を使用して、Amazon S3 に保存されているウェブサーバーログをクエリすることができます。このセクションのトピックでは、Athena でテーブルを作成して、さまざまな形式のウェブサーバーログをクエリする方法を説明します。

**Topics**
+ [Amazon S3 に保存されている Apache ログをクエリする](querying-apache-logs.md)
+ [Simple Storage Service (Amazon S3) に保存されているインターネットインフォメーションサーバー (IIS) ログをクエリする](querying-iis-logs.md)

# Amazon S3 に保存されている Apache ログをクエリする
<a name="querying-apache-logs"></a>

Amazon Athena を使用して、Simple Storage Service (Amazon S3) アカウントに保存されている [Apache HTTP サーバーのログファイル](https://httpd.apache.org/docs/2.4/logs.html)をクエリできます。このトピックでは、テーブルスキーマを作成して、一般的なログ形式の Apache [アクセスログ](https://httpd.apache.org/docs/2.4/logs.html#accesslog)ファイルをクエリする方法を説明します。

一般的なログ形式のフィールドには、クライアント IP アドレス、クライアント ID、ユーザー ID、リクエスト受信時のタイムスタンプ、クライアントリクエストのテキスト、サーバステータスコード、およびクライアントに返されたオブジェクトのサイズが含まれます。

以下の例は、Apache の一般的なログ形式を示しています。

```
198.51.100.7 - Li [10/Oct/2019:13:55:36 -0700] "GET /logo.gif HTTP/1.0" 200 232
198.51.100.14 - Jorge [24/Nov/2019:10:49:52 -0700] "GET /index.html HTTP/1.1" 200 2165
198.51.100.22 - Mateo [27/Dec/2019:11:38:12 -0700] "GET /about.html HTTP/1.1" 200 1287
198.51.100.9 - Nikki [11/Jan/2020:11:40:11 -0700] "GET /image.png HTTP/1.1" 404 230
198.51.100.2 - Ana [15/Feb/2019:10:12:22 -0700] "GET /favicon.ico HTTP/1.1" 404 30
198.51.100.13 - Saanvi [14/Mar/2019:11:40:33 -0700] "GET /intro.html HTTP/1.1" 200 1608
198.51.100.11 - Xiulan [22/Apr/2019:10:51:34 -0700] "GET /group/index.html HTTP/1.1" 200 1344
```

## Athena で Apache ログ用のテーブルを作成する
<a name="querying-apache-logs-creating-a-table-in-athena"></a>

Amazon S3 に保存されている Apache ログをクエリする前に、Athena のテーブルスキーマを作成して、Athena がログデータを読み取ることができるようにする必要があります Apache ログ用の Athena テーブルを作成するには、[Grok SerDe](grok-serde.md) を使用できます。Grok SerDe の使用に関する詳細については、「AWS Glue デベロッパーガイド」の「[Grok カスタム分類子の書き込み](https://docs.aws.amazon.com/glue/latest/dg/custom-classifier.html#custom-classifier-grok)」を参照してください。

**Athena で Apache ウェブサーバーログ用のテーブルを作成する**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. 以下の DDL ステートメントを Athena クエリエディタに貼り付けます。`LOCATION 's3://amzn-s3-demo-bucket/apache-log-folder/'` の値を変更して、Amazon S3 内の Apache ログをポイントするようにします。

   ```
   CREATE EXTERNAL TABLE apache_logs (
     client_ip string,
     client_id string,
     user_id string,
     request_received_time string,
     client_request string,
     server_status string,
     returned_obj_size string
     )
   ROW FORMAT SERDE
      'com.amazonaws.glue.serde.GrokSerDe'
   WITH SERDEPROPERTIES (
      'input.format'='^%{IPV4:client_ip} %{DATA:client_id} %{USERNAME:user_id} %{GREEDYDATA:request_received_time} %{QUOTEDSTRING:client_request} %{DATA:server_status} %{DATA: returned_obj_size}$'
      )
   STORED AS INPUTFORMAT
      'org.apache.hadoop.mapred.TextInputFormat'
   OUTPUTFORMAT
      'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
      's3://amzn-s3-demo-bucket/apache-log-folder/';
   ```

1. Athena コンソールでクエリを実行して、`apache_logs` テーブルを登録します。クエリが完了すると、Athena からログをクエリできるようになります。

### クエリの例
<a name="querying-apache-logs-example-select-queries"></a>

**Example – 404 エラーをフィルタリングする**  
以下のクエリ例は、リクエストの受信時刻、クライアントリクエストのテキスト、およびサーバーステータスコードを `apache_logs` テーブルから選択します。`WHERE` 句は、HTTP ステータスコード `404` (ページが見つかりません) をフィルターします。  

```
SELECT request_received_time, client_request, server_status
FROM apache_logs
WHERE server_status = '404'
```
以下の画像は、Athena クエリエディタでのクエリの結果を示しています。  

![\[Athena から Apache ログに対して HTTP 404 エントリをクエリします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-apache-logs-1.png)


**Example – 成功したリクエストをフィルタリングする**  
以下の例のクエリでは、ユーザー ID、リクエスト受信時刻、クライアントリクエストのテキスト、およびサーバーステータスコードを `apache_logs` テーブルから選択しています。`WHERE` 句は、HTTP ステータスコード `200` (成功) をフィルターします。  

```
SELECT user_id, request_received_time, client_request, server_status
FROM apache_logs
WHERE server_status = '200'
```
以下の画像は、Athena クエリエディタでのクエリの結果を示しています。  

![\[Athena から Apache ログに対して HTTP 200 エントリをクエリします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-apache-logs-2.png)


**Example – タイムスタンプでフィルタリングする**  
次の例では、リクエストの受信時間が指定されたタイムスタンプよりも長いレコードをクエリします。  

```
SELECT * FROM apache_logs WHERE request_received_time > 10/Oct/2023:00:00:00
```

# Simple Storage Service (Amazon S3) に保存されているインターネットインフォメーションサーバー (IIS) ログをクエリする
<a name="querying-iis-logs"></a>

Amazon Athena を使用して、Amazon S3 アカウントに保存されている Microsoft インターネットインフォメーションサービス (IIS) ウェブサーバーログをクエリできます。IIS は[さまざまな](https://docs.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms525807(v%3Dvs.90))ログファイル形式を使用しますが、このトピックでは、W3C 拡張および IIS ログファイル形式のログを Athena からクエリするためのテーブルスキーマの作成方法について説明します。

W3C 拡張および IIS ログファイル形式は 1 文字の区切り文字 (それぞれスペースとカンマ) を使用し、引用符で囲まれた値を持たないため、[LazySimpleSerDe](lazy-simple-serde.md) を使用してそれらの Athena テーブルを作成できます。

**Topics**
+ [W3C 拡張ログファイル形式をクエリする](querying-iis-logs-w3c-extended-log-file-format.md)
+ [IIS ログファイル形式をクエリする](querying-iis-logs-iis-log-file-format.md)
+ [NCSA ログファイル形式をクエリする](querying-iis-logs-ncsa-log-file-format.md)

# W3C 拡張ログファイル形式をクエリする
<a name="querying-iis-logs-w3c-extended-log-file-format"></a>

[W3C 拡張](https://docs.microsoft.com/en-us/windows/win32/http/w3c-logging)ログファイルデータ形式には、スペースで区切られたフィールドがあります。W3C 拡張ログに表示されるフィールドは、どのログフィールドを含めるかを選択するウェブサーバー管理者によって決定されます。以下のログデータ例には、`date, time`、`c-ip`、`s-ip`、`cs-method`、`cs-uri-stem`、`sc-status`、`sc-bytes`、`cs-bytes`、`time-taken`、および `cs-version` のフィールドがあります。

```
2020-01-19 22:48:39 203.0.113.5 198.51.100.2 GET /default.html 200 540 524 157 HTTP/1.0
2020-01-19 22:49:40 203.0.113.10 198.51.100.12 GET /index.html 200 420 324 164 HTTP/1.0
2020-01-19 22:50:12 203.0.113.12 198.51.100.4 GET /image.gif 200 324 320 358 HTTP/1.0
2020-01-19 22:51:44 203.0.113.15 198.51.100.16 GET /faq.html 200 330 324 288 HTTP/1.0
```

## Athena で W3C 拡張ログ用のテーブルを作成する
<a name="querying-iis-logs-creating-a-table-in-athena-for-w3c-extended-logs"></a>

W3C 拡張ログをクエリする前に、テーブルスキーマを作成して Athena がログデータを読み取ることができるようにする必要があります。

**Athena で W3C 拡張ログ用のテーブルを作成する**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. 以下の点に注意しながら、以下のような DDL ステートメントを Athena コンソールに貼り付けます。

   1. クエリするログのフィールドに対応するように、例にある列を追加または削除します。

   1. W3C 拡張ログファイル形式の列名にはハイフン (`-`) が含まれていますが、例の `CREATE TABLE` ステートメントは、[Athena の命名規則](tables-databases-columns-names.md)に従って、それらをアンダースコア (`_`) に置き換えます。

   1. スペース区切り文字を指定するには、`FIELDS TERMINATED BY ' '` を使用します。

   1. `LOCATION 's3://amzn-s3-demo-bucket/w3c-log-folder/'` の値を変更して、Amazon S3 内の W3C 拡張ログをポイントするようにします。

   ```
   CREATE EXTERNAL TABLE `iis_w3c_logs`( 
     date_col string, 
     time_col string, 
     c_ip string,
     s_ip string,
     cs_method string, 
     cs_uri_stem string, 
     sc_status string,
     sc_bytes string,
     cs_bytes string,
     time_taken string,
     cs_version string
     ) 
   ROW FORMAT DELIMITED  
     FIELDS TERMINATED BY ' '  
   STORED AS INPUTFORMAT  
     'org.apache.hadoop.mapred.TextInputFormat'  
   OUTPUTFORMAT  
     'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' 
   LOCATION   's3://amzn-s3-demo-bucket/w3c-log-folder/'
   ```

1. Athena コンソールでクエリを実行して、`iis_w3c_logs` テーブルを登録します。クエリが完了すると、Athena からログをクエリできるようになります。

## W3C 拡張ログに対する選択クエリの例
<a name="querying-iis-logs-example-w3c-extended-log-select-query"></a>

以下のクエリ例は、日付、時刻、リクエストターゲット、およびリクエストにかかった時間をテーブル `iis_w3c_logs` から選択します。`WHERE` 句は、HTTP メソッドが `GET` で、HTTP ステータスコードが `200` (成功) のケースをフィルターします。

```
SELECT date_col, time_col, cs_uri_stem, time_taken
FROM iis_w3c_logs
WHERE cs_method = 'GET' AND sc_status = '200'
```

以下の画像は、Athena クエリエディタでのクエリの結果を示しています。

![\[Amazon S3 に保存された W3C 拡張ログファイルの Athena でのクエリ結果例です。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-iis-logs-1.png)


## 日付フィールドと時刻フィールドを組み合わせる
<a name="querying-iis-logs-example-w3c-extended-log-combining-date-and-time"></a>

スペースで区切られた `date` フィールドと `time` フィールドはログソースデータ内の個別のエントリですが、必要に応じてそれらをタイムスタンプに統合できます。[SELECT](select.md) または [CREATE TABLE AS SELECT](create-table-as.md) クエリで [concat(](https://prestodb.io/docs/current/functions/string.html#concat)) および [date\$1parse()](https://prestodb.io/docs/current/functions/datetime.html#date_parse) 関数を使用して、日付と時刻の列を連結し、タイムスタンプ形式に変換します。以下の例では、CTAS クエリを使用して、`derived_timestamp` 列が含まれる新しいテーブルを作成しています。

```
CREATE TABLE iis_w3c_logs_w_timestamp AS
SELECT 
  date_parse(concat(date_col,' ', time_col),'%Y-%m-%d %H:%i:%s') as derived_timestamp, 
  c_ip, 
  s_ip, 
  cs_method, 
  cs_uri_stem, 
  sc_status, 
  sc_bytes, 
  cs_bytes, 
  time_taken, 
  cs_version
FROM iis_w3c_logs
```

テーブルが作成されたら、次の例にあるように、新しいタイムスタンプ列を直接クエリできます。

```
SELECT derived_timestamp, cs_uri_stem, time_taken
FROM iis_w3c_logs_w_timestamp
WHERE cs_method = 'GET' AND sc_status = '200'
```

以下の画像は、クエリの結果を示しています。

![\[生成されたタイムスタンプ列があるテーブルでの W3C 拡張ログファイルのクエリ結果です。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-iis-logs-1a.png)


# IIS ログファイル形式をクエリする
<a name="querying-iis-logs-iis-log-file-format"></a>

W3C 拡張形式とは異なり、[IIS ログファイル形式](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc728311(v%3dws.10))には、固定されたフィールドのセットがあり、区切り文字としてカンマが含まれています。LazySimpleSerDe はカンマを区切り文字として扱い、カンマの後のスペースを次のフィールドの先頭として扱います。

以下の例は、IIS ログファイル形式のサンプルデータを示しています。

```
203.0.113.15, -, 2020-02-24, 22:48:38, W3SVC2, SERVER5, 198.51.100.4, 254, 501, 488, 200, 0, GET, /index.htm, -, 
203.0.113.4, -, 2020-02-24, 22:48:39, W3SVC2, SERVER6, 198.51.100.6, 147, 411, 388, 200, 0, GET, /about.html, -, 
203.0.113.11, -, 2020-02-24, 22:48:40, W3SVC2, SERVER7, 198.51.100.18, 170, 531, 468, 200, 0, GET, /image.png, -, 
203.0.113.8, -, 2020-02-24, 22:48:41, W3SVC2, SERVER8, 198.51.100.14, 125, 711, 868, 200, 0, GET, /intro.htm, -,
```

## Athena で IIS ログファイル用のテーブルを作成する
<a name="querying-iis-logs-creating-a-table-in-athena-for-iis-log-files"></a>

Amazon S3 に保存されている IIS ログファイル形式のログをクエリするには、まずテーブルスキーマを作成して、Athena がログデータを読み取ることができるようにします。

**Athena で IIS ログファイル形式のログ用のテーブルを作成する**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. 以下の点に注意しながら、以下の DDL ステートメントを Athena コンソールに貼り付けます。

   1. カンマ区切り文字を指定するには、`FIELDS TERMINATED BY ','` を使用します。

   1. Amazon S3 内の IIS ログ形式のログファイルをポイントするように、LOCATION 's3://amzn-s3-demo-bucket/*iis-log-file-folder*/' の値を変更します。

   ```
   CREATE EXTERNAL TABLE `iis_format_logs`(
   client_ip_address string,
   user_name string,
   request_date string,
   request_time string,
   service_and_instance string,
   server_name string,
   server_ip_address string,
   time_taken_millisec string,
   client_bytes_sent string,
   server_bytes_sent string,
   service_status_code string,
   windows_status_code string,
   request_type string,
   target_of_operation string,
   script_parameters string
      )
   ROW FORMAT DELIMITED
     FIELDS TERMINATED BY ','
   STORED AS INPUTFORMAT
     'org.apache.hadoop.mapred.TextInputFormat'
   OUTPUTFORMAT
     'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/iis-log-file-folder/'
   ```

1. Athena コンソールでクエリを実行して、`iis_format_logs` テーブルを登録します。クエリが完了すると、Athena からログをクエリできるようになります。

## IIS ログ形式の選択クエリの例
<a name="querying-iis-logs-example-iis-log-format-select-query"></a>

以下のクエリ例は、リクエスト日、リクエスト時刻、リクエストターゲット、およびリクエストにかかったミリ秒単位の時間をテーブル `iis_format_logs` から選択します。`WHERE` 句は、リクエストタイプが `GET` で、HTTP ステータスコードが `200` (成功) のケースをフィルターします。このクエリでは、クエリを正常に行うために `' GET'` および `' 200'` の先頭にスペースが必要であることに注意してください。

```
SELECT request_date, request_time, target_of_operation, time_taken_millisec
FROM iis_format_logs
WHERE request_type = ' GET' AND service_status_code = ' 200'
```

以下の画像は、サンプルデータに対するクエリの結果の例を示しています。

![\[Amazon S3 に保存されている IIS ログファイル形式のログファイルに対する Athena でのクエリの結果例です。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-iis-logs-2.png)


# NCSA ログファイル形式をクエリする
<a name="querying-iis-logs-ncsa-log-file-format"></a>

IIS は [NCSA ロギング](https://docs.microsoft.com/en-us/windows/win32/http/ncsa-logging)形式も使用します。この形式には、スペースで区切られた固定数の ASCII テキスト形式のフィールドがあります。その構造は、Apache アクセスログに使用される一般的なログ形式に似ています。NCSA 共通ログ形式のフィールドには、クライアント IP アドレス、クライアント ID (通常は使用されません)、ドメイン\$1ユーザー ID、リクエスト受信時のタイムスタンプ、クライアントリクエストのテキスト、サーバステータスコード、およびクライアントに返されたオブジェクトのサイズが含まれます。

以下の例は、IIS 用に記録された NCSA 共通ログ形式のデータを示しています。

```
198.51.100.7 - ExampleCorp\Li [10/Oct/2019:13:55:36 -0700] "GET /logo.gif HTTP/1.0" 200 232
198.51.100.14 - AnyCompany\Jorge [24/Nov/2019:10:49:52 -0700] "GET /index.html HTTP/1.1" 200 2165
198.51.100.22 - ExampleCorp\Mateo [27/Dec/2019:11:38:12 -0700] "GET /about.html HTTP/1.1" 200 1287
198.51.100.9 - AnyCompany\Nikki [11/Jan/2020:11:40:11 -0700] "GET /image.png HTTP/1.1" 404 230
198.51.100.2 - ExampleCorp\Ana [15/Feb/2019:10:12:22 -0700] "GET /favicon.ico HTTP/1.1" 404 30
198.51.100.13 - AnyCompany\Saanvi [14/Mar/2019:11:40:33 -0700] "GET /intro.html HTTP/1.1" 200 1608
198.51.100.11 - ExampleCorp\Xiulan [22/Apr/2019:10:51:34 -0700] "GET /group/index.html HTTP/1.1" 200 1344
```

## Athena で IIS NCSA ログ用のテーブルを作成する
<a name="querying-iis-logs-ncsa-creating-a-table-in-athena"></a>

`CREATE TABLE` ステートメントには、[Apache のウェブサーバーログ](querying-apache-logs.md)の場合と同じような [Grok SerDe](grok-serde.md) および grok パターンを使用できます。Apache ログとは異なり、grok パターンは `domain\user_id` 内のバックスラッシュの存在を考慮するために、`%{DATA:user_id}` ではなく `%{USERNAME:user_id}` を 3 番目のフィールドに使用します。Grok SerDe の使用に関する詳細については、「AWS Glue デベロッパーガイド」の「[Grok カスタム分類子の書き込み](https://docs.aws.amazon.com/glue/latest/dg/custom-classifier.html#custom-classifier-grok)」を参照してください。

**Athena で IIS NCSA ウェブサーバーログ用のテーブルを作成する**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) で Athena コンソールを開きます。

1. 以下の DDL ステートメントを Athena クエリエディタに貼り付けます。`LOCATION 's3://amzn-s3-demo-bucket/iis-ncsa-logs/'` の値を変更して、Amazon S3 内の IIS NCSA ログをポイントするようにします。

   ```
   CREATE EXTERNAL TABLE iis_ncsa_logs(
     client_ip string,
     client_id string,
     user_id string,
     request_received_time string,
     client_request string,
     server_status string,
     returned_obj_size string
     )
   ROW FORMAT SERDE
      'com.amazonaws.glue.serde.GrokSerDe'
   WITH SERDEPROPERTIES (
      'input.format'='^%{IPV4:client_ip} %{DATA:client_id} %{DATA:user_id} %{GREEDYDATA:request_received_time} %{QUOTEDSTRING:client_request} %{DATA:server_status} %{DATA: returned_obj_size}$'
      )
   STORED AS INPUTFORMAT
      'org.apache.hadoop.mapred.TextInputFormat'
   OUTPUTFORMAT
      'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
      's3://amzn-s3-demo-bucket/iis-ncsa-logs/';
   ```

1. Athena コンソールでクエリを実行して、`iis_ncsa_logs` テーブルを登録します。クエリが完了すると、Athena からログをクエリできるようになります。

## IIS NCSA ログに対する選択クエリの例
<a name="querying-iis-logs-ncsa-example-select-queries"></a>

**Example – 404 エラーのフィルタリング**  
以下のクエリ例は、リクエストの受信時刻、クライアントリクエストのテキスト、およびサーバーステータスコードを `iis_ncsa_logs` テーブルから選択します。`WHERE` 句は、HTTP ステータスコード `404` (ページが見つかりません) をフィルターします。  

```
SELECT request_received_time, client_request, server_status
FROM iis_ncsa_logs
WHERE server_status = '404'
```
以下の画像は、Athena クエリエディタでのクエリの結果を示しています。  

![\[Athena から HTTP 404 エントリについて IIS NCSA ログをクエリします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-iis-logs-3.png)


**Example – 特定のドメインからの正常に行われたリクエストのフィルタリング**  
以下のクエリ例は、ユーザー ID、リクエスト受信時刻、クライアントリクエストのテキスト、およびサーバーステータスコードを `iis_ncsa_logs` テーブルから選択します。`WHERE` 句は、`AnyCompany` ドメイン内のユーザーから HTTP ステータスコードが `200` (成功) のリクエストをフィルターします。  

```
SELECT user_id, request_received_time, client_request, server_status
FROM iis_ncsa_logs
WHERE server_status = '200' AND user_id LIKE 'AnyCompany%'
```
以下の画像は、Athena クエリエディタでのクエリの結果を示しています。  

![\[Athena から HTTP 200 エントリについて IIS NCSA ログをクエリします。\]](http://docs.aws.amazon.com/ja_jp/athena/latest/ug/images/querying-iis-logs-4.png)
