AWS Glueのカラムレベルの統計情報を試してみた

# 背景・目的
[AWS Glue Data Catalog now supports generating column-level statistics](https://aws.amazon.com/about-aws/whats-new/2023/11/aws-glue-data-catalog-generating-column-level-statistics/)にあるように、Glueカタログでカラムレベルの統計情報がサポートされたようです。
これにより、AthenaやRedshift Spectrum等のCBOと統合されるようになりましたので、試してみたいと思います。

# まとめ
- Redshift　SpectrumやAthenaなどの分析サービスで利用ができます。
- 下記のファイルフォーマットが対象です。
    - Parquet
    - ORC
    - JSON
    - ION
    - CSV
    - XML
- 対象の統計項目は下記になります。
    - 最小値
    - 最大値
    - Null 値の合計
    - 個別の値の合計
    - 値の平均長
    - true 値の合計出現数
- 考慮事項は下記のとおりです。
    - サンプリングを使用すると、不正確な統計情報が作られる。
    - 異なるバージョンの統計を保存しない。
    - テーブル毎に一度に1つの統計生成タスクのみ実行する。
- 下記の統計の生成をサポートしていません。
    - Lake Formationのセルベースのアクセス制御を備えたテーブル
    - トランザクションデータレイク
        - Delta Lake
        - Iceberg
        - Hudi
    - フェデレーション内のテーブル
        - Hiveメタストア
        - Redshift データシェアリング
    - ネストされたカラム、配列、構造体
    - 別のアカウントから共有されたテーブル
- 2023/11/19時点で下記のリージョンでのみ利用可能です。
    - 米国東部 (バージニア北部)
    - 米国東部 (オハイオ)
    - 米国西部 (オレゴン)
    - 欧州 (アイルランド)
    - アジアパシフィック (東京、大阪) 




# 概要
まずは、どのようなものか、[Working with column statistics](https://docs.aws.amazon.com/glue/latest/dg/column-statistics.html)を元に整理してみます。

下記のファイルフォーマットで列レベルの統計を計算できるようです。
- Parquet
- ORC
- JSON
- ION
- CSV
- XML

下記の統計を生成します。
- 最小値
- 最大値
- Null 値の合計
- 個別の値の合計
- 値の平均長
- true 値の合計出現数等

Redshift　SpectrumやAthenaなどの分析サービスで、上記の列統計を使用してクエリの実行計画を生成し、パフォーマンスを向上させる最適なプランが選択できるようになります。


## 考慮事項と制限事項
[Considerations and limitations](https://docs.aws.amazon.com/ja_jp/glue/latest/dg/column-stats-notes.html)をもとに整理しています。

- 考慮事項
    - サンプリングを使用すると、不正確な統計情報が作られる。
    - 異なるバージョンの統計を保存しない。
    - テーブル毎に一度に1つの統計生成タスクのみ実行する。
- 下記の統計の生成をサポートしていない。
    - Lake Formationのセルベースのアクセス制御を備えたテーブル
    - トランザクションデータレイク
        - Delta Lake
        - Iceberg
        - Hudi
    - フェデレーション内のテーブル
        - Hiveメタストア
        - Redshift データシェアリング
    - ネストされたカラム、配列、構造体
    - 別のアカウントから共有されたテーブル

# 実践
## 前提
### IAMロールの設定
列統計の生成、更新を行うためには、IAMロールの作成が必要です。

1. IAMロールの画面で、ロールの作成をクリックします。
1. 下記を入力し、「次へ」をクリックします。
    - AWSのサービス
    - ユースケース：Glue
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/dce1e96d-257a-1a40-2c59-8ef7431cd097.png)

1. ポリシーの追加で、AWS管理の「AWSGlueServiceRole」を選択し、「作成」をクリックします。
1. 作成したロールにインラインポリシーを追加します。下記のJSONを貼り付けて、作成します。
    ```
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "S3BucketAccess",
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket",
                    "s3:GetObject"
                ],
                "Resource": [
                    "arn:aws:s3:::<bucket>/*",
                    "arn:aws:s3:::<bucket>"
                ]
            }
         ]
    }                           
    ```



### データの準備
#### ファイルアップロード
1. [Redshiftのドキュメント](https://docs.aws.amazon.com/ja_jp/redshift/latest/gsg/rs-gsg-create-sample-db.html)に添付されているサンプルのデータセット[tickitdb.zip](https://docs.aws.amazon.com/ja_jp/redshift/latest/gsg/samples/tickitdb.zip)をダウンロードします。

1. いくつかのファイルのうち、最も大きいサイズのlisting_pipe.txtを使用します。
    ```
    $
    total 57072
    -rw-rw-r--@ 1 XXXX  YYY    445838 10 16  2019 allevents_pipe.txt
    -rw-rw-r--@ 1 XXXX  YYY   5893626 10 16  2019 allusers_pipe.txt
    -rw-rw-r--@ 1 XXXX  YYY       465 10 16  2019 category_pipe.txt
    -rw-rw-r--@ 1 XXXX  YYY     14534 10 16  2019 date2008_pipe.txt
    -rw-rw-r--@ 1 XXXX  YYY  11585036 10 16  2019 listings_pipe.txt
    -rw-rw-r--@ 1 XXXX  YYY  11260097 10 16  2019 sales_tab.txt
    -rw-rw-r--@ 1 XXXX  YYY      7988 10 16  2019 venue_pipe.txt
    $ 
    ```

1. S3にアップロードします。


#### データベースとテーブルの作成
1. GlueのData Catalogを開きます。
1. データベース名を「tickitdb」とし、データベースを作成します。
1. テーブル名を「listing」とし、「Next」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/89922dd5-5790-0c18-1549-5cc02e28977b.png)

1. スキーマを設定し、「Next」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/4250af4e-98a0-9f51-e5e9-f1b1cb5065b5.png)

1. 確認画面で、「Create」をクリックします。

### データの確認
1. Athenaのクエリエディタを開きます。
1. 下記のクエリを実行しAthenaで読み取れるか確認します。
    ```
    SELECT listid,sellerid,eventid,dateid,numtickets,priceperticket,totalprice,listtime FROM "tickitdb"."listing" limit 10;
    ```
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f9596aaf-93f6-ec60-7cb4-048730934915.png)




## 統計情報を生成する
### 事前確認
1. 事前に列統計を確認するため、作成したGlueのテーブルを確認します。
1. テーブルの「Cloumn statics」タブをクリックします。なにもないことがわかります。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/519e8231-ca17-a61f-efb1-133dfa79a18c.png)


### 統計を生成
1. 当該テーブルのActionのプルダウンから、「Generate statistics」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/9823039f-6ce8-80cf-3500-4262c786fe64.png)

1. 下記を選択し、「Generate statistics」をクリックします。
    - Columnは全て
    - Rowは全て
    - IAMロールは、作成したものを選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/edfc000b-9f49-d3ba-608b-aae0c6b8b797.png)

1. 4分程度で完了しました。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/24038b22-5f73-59e3-0f3b-8aa2dc018ce5.png)

### 確認
1. 確認できました。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/96096f98-342c-a0f7-ea3c-4b8296781b0e.png)


# 考察
Glueデータカタログで統計情報が扱えるようになったことがわかりました。
今回は、性能について確認しませんでしたが、今後は、複雑なクエリを用意し、実行計画の差異や、もう少し大きいデータを用意して性能の違いを確認したいと思います。

# 参考
https://docs.aws.amazon.com/ja_jp/glue/latest/dg/column-statistics.html

https://aws.amazon.com/blogs/big-data/speed-up-queries-with-cost-based-optimizer-in-amazon-athena/