【Snowflake】Snowflakeのパフォーマンス改善 ~ クラスタリングキー ~

■ はじめに

https://dk521123.hatenablog.com/entry/2022/12/07/111847
https://dk521123.hatenablog.com/entry/2023/02/27/120943

の続き。

 今回は、クラスタリングキーおよび
その周辺に関わるマイクロパーティションについて
自分なりにまとめてみる

目次

【0】自分の中でのざっくりした勝手な理解
【1】ニアゼロメンテナンス
 1)マイクロパーティション
 2)データクラスタリング
【2】クラスタリングキー
 1)クラスタリングキーの有効性(利点)
 2)使用上の注意
 3)どういった場合に指定した方がいい?
 4)クラスタリングキーの操作
 5)自動クラスタリング

【0】自分の中でのざっくりした勝手な理解

調べながら、つらつらと書いたら、
もの凄く長くなってしまった(【1】以降)ので、
まずは、自分が理解したざっくりしたことを書いておく。

マイクロパーティションに関するざっくり理解

* Snowflake では、デフォルトで「マイクロパーティション」という
 ストレージ単位で自動的にデータ分割される
 => これにより、無駄なデータスキャンを極力省き、
  パフォーマンス向上になっている

データクラスタリングに関するざっくり理解

* Snowflake では、デフォルトで
 データ間の類似度に基づいてデータをグループ分けしてくれる
 => これにより、「マイクロパーティション」で言ってた
 『無駄なデータスキャンを極力省き』を効率に行える
 => ちょっと違うかもしれないが、OSの「デフラグ」みたいな感じ?

クラスタリングキーに関するざっくり理解

* 「マイクロパーティション」と「データクラスタリング」により、
 クエリのパフォーマンス向上をデフォルトで行ってくれるが
 時間の経過とともに、非常に大きなテーブル(行数ではなくテーブル内のデータ量)
 において、一部のテーブル行のデータがにクラスタ化されなくなる場合があり、
 パフォーマンスが劣化する

 => 解決するために、テーブルに併せた項目について、
  クラスタリングキーを指定し、対策することが可能

【1】ニアゼロメンテナンス

Snowflakeでは、以下が自動で適用される
~~~~~~~
1)マイクロパーティション
2)データクラスタリング
~~~~~~~
 => 上記の仕組みにより、スキャン対象データを減らし、
  大量データのクエリ効率に役立つ
 => Snowflakeが掲げる「ニアゼロメンテナンス」を実現
 (ただし、あくまで「ニアゼロ(Near Zero=おおよそ無し)」)

公式サイトより
https://www.snowflake.com/snowflake-cloud-data-platform/?lang=ja

~~~~~~~
サービスとしてのニアゼロメンテナンス

Snowflakeは他のソリューションと違い、
お客様によるメンテナンスがほとんど必要ありません。
構築、インデックス作成、パーティショニングスキームの管理といった
従来のデータベースタスクが不要になります。
~~~~~~~

1)マイクロパーティション

Snowflake は、コンピュートとストレージが分離したアーキテクチャを採用
そのため、データの読み込みがボトルネックとなるケースが多い

 => Snowflakeでは、マイクロパーティショニングを採用することによって
  効果的なプルーニングを可能にし、不要な読み込みを回避

 => そのため、snowflakeのパフォーマンンスを改善する上で
  マイクロパーティションは重要になる

マイクロパーティションとは?
https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions#what-are-micro-partitions

* Snowflakeテーブル内のすべてのデータは
 連続したストレージ単位で自動的に分割される

 => この単位を「マイクロパーティション (Micro-partitions)」という
 => 自体は、小規模なファイル群
 => Snowflake の特徴のひとつ

利点
https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions#benefits-of-micro-partitioning

[1] Hiveのような従来なパーティションと違って
 Snowflake内で自動的に行われる

[2] 非常に効率的な DML および
 きめ細かいプルーニング(※1)により、
 クエリを高速化してくれる

[3] 値の範囲内で重複する可能性があり、
 均一に小さいサイズと組み合わせて、
 スキュー(Skew;データの偏り)を防ぐ

[4] 列指向により列のみを効率的にスキャン

[5] Snowflakeは、各マイクロパーティションの列に対して
 最も効率的な圧縮アルゴリズムを自動的に決定

※1:クエリプルーニング (Query pruning)
https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions#query-pruning

* クエリ実行時に、不要とわかっているパーティションを読みに行かない
 => ストレージIOを減らし、パフォーマンスを向上してくれる

cf. Pruning = 枝刈り、間引き

特徴

* マイクロパーティション1個の容量は、圧縮ファイルで約16MB
* 列指向ストレージ
* 不変(immutable)

データ構造

* まずは、公式サイトの以下の図が分かりやすいかも。
 => ただし、実際のデータ構造ではない
 => Snowflakeがマイクロパーティションで使用する
  データクラスタリングの小規模な概念的表現としてのみ意図した図

https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions#what-is-data-clustering

* マイクロパーティションの分割単位は、「行」
* マイクロパーティションの内部では、「列」ごとにデータがまとめて圧縮

2)データクラスタリング

データ間の類似度にもとづいて、
データ(例えば、日付や地理的地域など)をグループ分けする

https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions#what-is-data-clustering

【2】クラスタリングキー

 Snowflake では、非常に大きなテーブルなどで、
マイクロパーティションが構成されなくなった場合に、
明示的にクラスタリングキーを指定することができる

https://docs.snowflake.com/ja/user-guide/tables-clustering-keys

1)クラスタリングキーの有効性(利点)

https://docs.snowflake.com/ja/user-guide/tables-clustering-keys#benefits-of-defining-clustering-keys-for-very-large-tables

[1] クエリのスキャン効率が向上することにより
 データをスキップすること効率的になりパフォーマンス向上

[2] クラスタリングのないテーブルよりも列圧縮が向上

[3] クラスタリングキーを削除/変更しない限り、追加の管理は必要ない
 => 後述「5)自動クラスタリング」を参照

2)使用上の注意

https://docs.snowflake.com/ja/user-guide/tables-clustering-keys#strategies-for-selecting-clustering-keys

* 無暗やたらと全てのテーブルに適用するものではない
 => クラスタリングを維持するコストがかかるため

* 1テーブルに対して、最大3 or 4列を推奨
 => 推奨値を超えると、利益よりもコストが増加する傾向があるため

* カーディナリティが非常に低い列(例:男性か女性かのみを示す列)は、
 クラスタリングキーとして直接使用する候補には 適していない

https://docs.snowflake.com/ja/user-guide/tables-clustering-keys#label-considerations-for-choosing-clustering

* クラスタリングキーを適用する前に、
 対象テーブルで代表的なクエリセットを
 パフォーマンステストしておき、記録として残しておいた方がいい
 => 適用後、同じクエリでテストし、比較することにより、
  コストに見合うパフォーマンスだったかの検討材料になる

3)どういった場合に指定した方がいい?

* テーブルがTB級の巨大なテーブルで、クエリパフォーマンスが悪い場合

https://docs.snowflake.com/ja/user-guide/tables-clustering-keys#label-considerations-for-choosing-clustering

* 平均クラスタリング深度が大きい場合

平均クラスタリング深度(Clustering Average Depth)とは?

* どの程度マイクロパーティションが
 オーバーラップ(一部の範囲のみ重なる)しているかを図る指標
 => 理想的なマイクロパーティション状態としては、
  他のマイクロパーティションとオーバーラップしていない状態が良い
 => 1以上の数値で、この値が大きいほど理想状態から離れていることになる

SYSTEM$CLUSTERING_INFORMATION
https://docs.snowflake.com/ja/sql-reference/functions/system_clustering_information

テーブルの平均クラスタリング深度を含むクラスタリング情報を返す

どういった列をクラスタリングキーとして指定する?

[1] SQLでWHEREになり易い列
 => 例えば、1ヶ月間の請求日
 「WHERE invoice_date BETWEEN '2023-01-01' AND '2023-01-31'」
 で絞るなどをよく行うテーブルに関しては、
 その列をクラスタリングキーとして指定する

[2] (追加のクラスタキーの余地がある場合)結合述語で頻繁に使用される列
 => 例えば、「・・・FROM t1 JOIN t2 ON t1.id = t2.user_id」
  だと、「id」「user_id」をクラスタリングキーとして指定する

4)クラスタリングキーの操作

クラスタリングキーの確認

 「SHOW TABLES;」で
「cluster_by (テーブルのクラスタリングキーとして定義された列)」
を確認する

https://docs.snowflake.com/ja/sql-reference/sql/show-tables#output

CREATE TABLE
https://docs.snowflake.com/en/sql-reference/sql/create-table

-- CLUSTER BY ( <expr> [ , <expr> , ... ]) で定義する
CREATE TABLE sample_table (
  date timestamp,
  id varchar(10),
  name varchar(10)
) CLUSTER BY (date, id); -- ★ここ★

-- 確認
show tables like 'sample_table';

ALTER TABLE

-- [1] 変更: CLUSTER BY ( expr [ , expr , ... ] )
ALTER TABLE sample_table CLUSTER BY (date, id);

-- [2] 一時停止: SUSPEND RECLUSTER
ALTER TABLE sample_table SUSPEND RECLUSTER;

-- [3] 再開: RESUME RECLUSTER
ALTER TABLE sample_table RESUME RECLUSTER;

-- [4] 削除: DROP CLUSTERING KEY
ALTER TABLE sample_table DROP CLUSTERING KEY;

5)自動クラスタリング

* クラスタリングキーのメンテナンスは、
 自動クラスタリングをONにしておくと、自動で実施される
 => 「AUTOMATIC_CLUSTERING」として課金

https://docs.snowflake.com/ja/user-guide/tables-auto-reclustering

補足:手動再クラスタリング(非推奨)

* 手動でもできるらしいが、非推奨
 => 詳細は、以下の公式ドキュメントを参照

https://docs.snowflake.com/ja/user-guide/tables-clustering-manual

自動クラスタリングON/OFFの確認

* 「SHOW TABLES;」で「automatic_clustering」で「ON/OFF」を確認する

https://docs.snowflake.com/ja/sql-reference/sql/show-tables#output

自動クラスタリング を有効にする
https://docs.snowflake.com/ja/user-guide/tables-auto-reclustering#enabling-automatic-clustering-for-a-table

より抜粋
~~~~~~~~~~~~~~~
多くの場合、テーブルの自動クラスタリングを有効にするためのタスクは必要ありません。
テーブルに クラスタリングキー を定義するだけです。
~~~~~~~~~~~~~~~
 => 『テーブルに クラスタリングキー を定義するだけ』で
  デフォルトで自動クラスタリングが有効になる

自動クラスタリングの一時停止

-- ALTER TABLE 文の「SUSPEND RECLUSTER」句を指定
ALTER TABLE sample_table SUSPEND RECLUSTER;

https://docs.snowflake.com/ja/user-guide/tables-auto-reclustering#suspending-automatic-clustering-for-a-table

自動クラスタリングの再開

-- ALTER TABLE 文の「RESUME RECLUSTER」句を指定
ALTER TABLE sample_table RESUME RECLUSTER;

https://docs.snowflake.com/ja/user-guide/tables-auto-reclustering#resuming-automatic-clustering-for-a-table

参考文献

https://dev.classmethod.jp/articles/snowflake-advent-calendar-2019-18-micropartition-and-dataclustering/
https://zenn.dev/ryotas_data/articles/a709dadb4717d4
マイクロパーティション
https://zenn.dev/holywater044/articles/972876054c75bc
https://zenn.dev/aaizawa/articles/18663675a5b188
クラスタリング
https://www.intage-ts.com/entry/2020/12/22/124000
https://qiita.com/manabian/items/499b5d51bdfd8ffb36b3
https://dev.classmethod.jp/articles/20220207-snowflake-clustering/

関連記事

Snowflake ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/02/130111
Snowflake ~ 入門編 / Hello world
https://dk521123.hatenablog.com/entry/2021/11/22/212520
Snowflakeのパフォーマンス改善 ~ データロードの改善 ~
https://dk521123.hatenablog.com/entry/2022/12/07/111847
Snowflakeのパフォーマンス改善 ~ 検索最適化サービス ~
https://dk521123.hatenablog.com/entry/2023/02/27/120943