Snowflakeにおけるパフォーマンスチューニング：クラスタリング

# はじめに
Snowflakeにおけるパフォーマンスチューニングには複数の方法があります。
その１つのクラスタリングについて、勉強した内容をまとめておこうと思います。

# Snowflakeにおけるクラスタリングとは
Snowflakeでは、テーブルのデータをマイクロパーティションという単位に区切って保存します。
クラスタリングを設定すると、<font color="Red">同じ値を持つレコード同士が、同じマイクロパーティションに保存される</font>ようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/987191bd-d8ad-5e15-ee3c-ecac1b7671b1.png)

# なぜクラスタリングでクエリのパフォーマンスが改善できるのか
Snowflakeは、どのデータがどのマイクロパーティションに入っているかをメタデータを使って把握してます。

WHERE句を指定してクエリを実行すると、Snowflakeはクエリ結果に必要なデータが入っているマイクロパーティションを読込み、必要なデータを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/4cb03dda-99b7-1562-e8a9-cf01ded4776b.png)

クラスタリングされていると、同じ値を持つレコードが同じマイクロパーティションに保存されるので、<font color="Red">読込むマイクロパーティションの数が少なくなり、クエリのレスポンスタイムを短縮</font>できます。

以下の例は、クラスタリングの設定前後での読込みに必要なマイクロパーティションの数の違いを表してます。
[col_1]=0001に一致するレコードを取得する際、クラスタリングが設定されていると、[col_1]=0001に一致するレコードが、<font color="Red">全てマイクロパーティション①に保存されるため、読込むマイクロパーティションを減らす</font>ことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/131b7a6f-9ee1-ff98-980c-ee15b1d8c5f2.png)

# クラスタリングを設定するには
　以下のDDLでテーブルの列をクラスタリングキーに指定することで設定できます。
```
alter table <テーブル名> cluster by (クラスタリングキーに指定する列名);
```
<font color="Red">複数の列をクラスタリングキーに設定</font>することもできます。

# どのようなテーブルにクラスタリングを設定すべきか
　以下の条件を満たしているテーブルでパフォーマンスの改善が期待できます。
　**・テーブルの容量がTB以上であること**
　**・テーブル内の一部のレコードを取得するようなクエリが行われていること**
　(例：特定の年月日に該当するレコードを使って分析するようなファクトテーブル)

# どの列をクラスタリングキーに指定すべきか
　複数の列をクラスタリングキーに設定することが推奨されてます。(最大で4列)
　以下1～2の優先順位でクラスタリングキーを選定します。

　**1.クエリのWHERE句で頻繁に使われる列**
　**2.他のテーブルと結合する際に結合キーとなる列**

　<font color="Red">複数の列をクラスタリングキーに指定する際、CLUSTER BY句で指定する列の順番に注意</font>する必要があります。
　<font color="Red">カーディナリティが低い列から順番に指定する</font>方がパフォーマンスが向上します。

　カーディナリティとは、列の値の種類の多さを示します。
　例えば、0もしくは1のどちらかを示すフラグの列であれば、値の種類は2つなのでカーディナリティは低いと言えます。
　IDのような主キーに使われるような列は、値の種類は多く、カーディナリティは高いと言えます。

# クラスタリングを利用する際の注意点
　**・クレジット消費を伴う**

Insert等でテーブルにレコードを追加すると、追加直後のレコードは適切なマイクロパーティションに保存されません。
クラスタリングキーで同じ値を持つレコードと同じマイクロパーティションに保存するために、Snowflakeが自動処理で追加されたレコードを移動させます。（<font color="Red">自動クラスタリング</font>と呼びます）

レコードの移動には、ウェアハウスが使われるため、クレジット消費が伴います。
頻繁にDMLが行われる場合、クラスタリングをメンテナンスするためのコストが上昇する点に注意が必要です。

以下は、自動クラスタリングによるクラスタリングのメンテナンスを表してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/3bba7585-516e-fd79-032d-a9ae52626b17.png)

# クラスタリングの効果の検証
クラスタリングにより、クエリのレスポンスタイムがどれだけ短縮できるかを以下の手順で検証しました。

**<検証手順>**
　手順1：クラスタリング設定前のクエリのレスポンスタイムを計測する
　手順2：クラスタリングを設定する
　手順3：クラスタリング設定後のクエリのレスポンスタイムを計測する

**<検証条件>**
　・検証対象のテーブル：catalog_sales_clustering (容量：約1TB)
　・実行するクエリ：WHERE句にクラスタリングキーを指定したクエリ(14,339,964,710行中、12行を取得する)
　・利用するウェアハウス：Sサイズ
　・リザルトキャッシュ：利用しない

**<検証結果>**
⇒クエリのレスポンスタイムを1/100以下に短縮できた。
　・クラスタリング設定<font color="blue">前</font>：<font color="blue">3分56秒</font>
　・クラスタリング設定<font color="Red">後</font>：<font color="Red">2.2秒</font>

以下は、手順に従って行った検証です。
**手順1：クラスタリング設定前のクエリのレスポンスタイムを計測する**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/06f4998e-1082-e10d-4a58-f68840dce5f1.png)

**手順2：クラスタリングを設定する**
　WHERE句に指定する以下3列をカーディナリティの低い(固有値の種類が少ない)列から順番にCLUSTER BY句に指定する。

　1.CS_SOLD_DATE_SK（固有値の数：1,871）
　2.CS_SOLD_TIME_SK（固有値の数：85,763）
　3.CS_SHIP_CUSTOMER_SK（固有値の数：64,303,076）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/9a2d4e62-ceaf-c58b-b579-7e6f049568c3.png)

**手順3：クラスタリング設定後のクエリのレスポンスタイムを計測する**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925708/de207dab-e531-64ae-581b-8391923a6c5a.png)


# 参考にしたサイト
* [Snowflakeドキュメント](https://docs.snowflake.com/ja/user-guide/tables-clustering-keys)

# ご案内
株式会社ジールでは、「ITリテラシーがない」「初期費用がかけられない」「親切・丁寧な支援がほしい」「ノーコード・ローコードがよい」「運用・保守の手間をかけられない」などのお客様の声を受けて、オールインワン型データ活用プラットフォーム「ZEUSCloud」を月額利用料にてご提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/?utm_source=qiita&utm_medium=referral&utm_campaign=qiita_zeuscloud_content-area