Deltaテーブルにおけるリキッドクラスタリングの活用

[Use liquid clustering for Delta tables \| Databricks on AWS](https://docs.databricks.com/delta/clustering.html) [2023/7/17時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

:::note warn
**重要！**
Delta Lakeのリキッドクラスタリングは、Databricksランタイム13.2以降でパブリックプレビューとなっています。
:::

Delta Lakeのリキッドクラスタリングは、データレイアウトの決定をシンプルにし、クエリーパフォーマンスを最適化するために、テーブルのパーティションニングと`ZORDER`を置き換えるものです。リキッドクラスタリングは、既存データを書き直す必要なしにクラスタリングキーを再定義する柔軟性を提供し、時間と共に変化する分析ニーズに合わせてデータレイアウトが進化するようになります。

Databricksでは、リキッドクラスタリングが有効化されたDeltaテーブルに対する強化された同時実行性をサポートしています。[Databricksにおける強化同時実行性](#Databricksにおける強化同時実行性)をご覧ください。

:::note alert
**警告！**
リキッドクラスタリングが有効化されたDeltaテーブルを書き込んだり、`OPTIMIZE`するにはDatabricksランタイム13.2以降が必要です。
:::

# リキッドクラスタリングは何に使われるのか？

すべての新規Deltaテーブルではリキッドクラスタリングを推奨します。クラスタリングによってメリットが得られるシナリオの例を示します:

- 高いカーディナリティを持つカラムで頻繁にフィルタリングされるテーブル。
- データ分布で大きな偏りがあるテーブル。
- クイックに成長し、メンテナンスやチューニングを必要とするテーブル。
- 同時書き込み要件のあるテーブル。
- 時間と共に変化するアクセスパターンを持つテーブル。
- 典型的なパーティションキーによって、多すぎるパーティションや少なすぎるパーティションを生み出す可能性のあるテーブル。

# リキッドクラスタリングの有効化

最初にテーブルを作成する際にDelta Lakeリキッドクラスタリングを有効化しなくてはなりません。クラスタリングはパーティショニングや`ZORDER`と互換性がなく、Databricksクライアントはお使いのテーブルのデータに対するすべてのレイアウトや最適化オペレーションを管理しなくてはなりません。

リキッドクラスタリングを有効化するには、以下の例のようにテーブル作成文に`CLUSTER BY`フレーズを追加します:

```sql
-- Create an empty table
CREATE TABLE table1(col0 int, col1 string) USING DELTA CLUSTER BY (col0);

-- Using a CTAS statement
CREATE EXTERNAL TABLE table2 CLUSTER BY (col0)
LOCATION ‘table_location’
AS SELECT * FROM table1;

-- Using a LIKE statement to copy configurations
CREATE TABLE table3 LIKE table1;
```

:::note alert
**警告！**
リキッドクラスタリングが有効化されたテーブルには、作成時に数多くのDeltaテーブルの機能が有効化され、Deltaライターバージョン7とリーダーバージョン3を使用します。テーブルプロトコルのバージョンをダウングレードすることはできず、有効化されたすべてのDeltaリーダープロトコルテーブル機能をサポートしないDelta Lakeクライアントでクラスタリングされたテーブルを読み込むことはできません。[How does Databricks manage Delta Lake feature compatibility?](https://docs.databricks.com/delta/feature-compatibility.html)をご覧ください。
:::

# クラスタリングキーの選択

頻繁に使用されるクエリーフィルターに基づいてクラスタリングキーを選択することをお勧めします。任意の順序でクラスタリングキーを定義することができます。二つのカラムが送還している場合には、クラスタリングキーとしていずれかを追加するだけで十分です。

既存テーブルを変換するには、以下の推奨事項を検討ください:

| 現在のデータ最適化技術 | クラスタリングキーの推奨 |
|:--|:--|
|Hiveスタイルのパーティショニング  |  クラスタリングキーとしてパーティションカラムを使用。 |
|Z-order index   | クラスタリングキーとして`ZORDER BY`カラムを使用。  |
|HiveスタイルのパーティショニングとZ-order   | クラスタリングキーとしてパーティションカラムと`ZORDER BY`カラムを使用。  |
|カーディナリティを削減するためのジェネレーテッドカラム   |  クラスタリングキーとしてオリジナルのカラムを使用し、ジェネレーテッドカラムを作成しない。 |

# Databricksにおける強化同時実行性

他のDeltaテーブルと比較して、クラスタリングされたテーブルに対して強化された同時実行性を提供します。行レベルの競合がない限り、`OPTIMIZE`、`INSERT`、`MERGE`、`UPDATE`、`DELETE`オペレーションを含み同時実行書き込みオペレーションは競合しません。

行レベルの競合の可能性を削減するには、以下の例のように同時実行クエリーをフィルタリングすることができます:

```sql
INSERT INTO table_name REPLACE WHERE column_name = "some_value" SELECT * FROM staging_table;
```

# クラスタリングされたテーブルへのデータの書き込み

リキッドクラスタリングで使用されるすべてのDelta書き込みプロトコルテーブル機能をサポートするDeltaライタークライアントを使用する必要があります。Databricksでは、Databricksランタイム13.2以上を使用する必要があります。

ほとんどのオペレーションは書き込み時に自動でデータをクラスタリングしません。書き込み時にクラスタリングを行うオペレーションには以下のようなものがあります:

- `INSERT INTO`オペレーション
- `CTAS`ステートメント
- Parquetフォーマットからの`COPY INTO`
- `spark.write.format("delta").mode("append")`

:::note info
**注意**
書き込み時のクラスタリングはベストエフォートのアプリケーションです。書き込み時のデータが512GBを超えると、リキッドクラスタリングは書き込み時には適用されません。すべてのオペレーションでリキッドクラスタリングが適用されるわけではないので、すべてのデータが効率的にクラスタリングされるように頻繁に`OPTIMIZE`を実行することをお勧めします。
:::

# クラスタリングの起動方法

クラスタリングを起動するには、Databricksランタイム13.2以降が必要です。以下の例のようにテーブルに対して`OPTIMIZE`を使用します。

```sql
OPTIMIZE table_name;
```

リキッドクラスタリングはインクリメンタルであり、クラスタリングされる必要なデータに対応するのに必要なデータのみを再書き込みすることを意味します。クラスタリングされるべきデータにマッチしないクラスタリングキーを持つデータファイルは再書き込みされません。

ベストなパフォーマンスを得るには、クラスタリングデータに定期的な`OPTIMIZE`ジョブをスケジューリングすることをお勧めします。多くのアップデートやインサートが生じするテーブルに対しては、1時間、2時間ごとに`OPTIMIZE`ジョブをスケジューリングすることをお勧めします。リキッドクラスタリングはインクリメンタルなので、クラスタリングされたテーブルに対するほとんどの`OPTIMIZE`ジョブはクイックに実行されます。

# クラスタリングされたテーブルからのデータの読み込み

削除ベクトルの読み込みをサポートするすべてのDelta Lakeをクライアントを用いてクラスタリングされたテーブルのデータを読み込むことができます。ベストなクエリー結果を得るには、以下の例のようにクエリーフィルターにクラスタリングキーを含めてください。

```sql
SELECT * FROM table_name WHERE cluster_key_column_name = "some_value";
```

# クラスタリングキーの変更

以下の例のように`ALTER TABLE`を実行することで、任意のタイミングでクラスタリングキーを変更することができます。

```sql
ALTER TABLE table_name CLUSTER BY (new_column1, new_column2);
```

クラスタリングキーを変更すると、以降の`OPTIMIZE`と書き込みオペレーションでは新たなクラスタリングキーを使用しますが、既存データは再書き込みされません。

また、以下の例のようにキーを`NONE`を設定することでクラスタリングをオフにすることができます。

```sql
ALTER TABLE table_name CLUSTER BY NONE;
```

クラスタリングキーを`NONE`に設定することで、すでにクラスタリングされているデータを再書き込みしませんが、以降の`OPTIMIZE`オペレーションではクラスタリングキーを使用しなくなります。

# どのようにテーブルがクラスタリングされているのかを確認

以下の例のように、テーブルに対するクラスタリングキーを確認するには`DESCRIBE`を使うことができます。

```sql
DESCRIBE TABLE table_name;

DESCRIBE DETAIL table_name;
```

# 制限

以下の制限があります:

- クラスタリングキーで収集された統計情報を持つカラムのみを指定することができます。デフォルトでは、Deltaテーブルの最初の32カラムの統計情報が収集されます。
- クラスタリングキーとして最大4カラムを指定することができます。
- 構造化ストリーミングワークロードでは、書き込み時のクラスタリングはサポートされていません。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)