Use Delta Lake generated columns | Databricks on AWS [2022/10/28時点]の翻訳です。
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
プレビュー
本機能はパブリックプレビューです。
本機能はDatabricksランタイム8.3以降で使用できます。
Delta Lakeでは、Deltaテーブルの他のカラムに対するユーザー定義関数に基づいて自動的に生成される値を持つ特殊なタイプのカラムをサポートしています。generated columnを有するテーブルに書き込みを行う際、それらのカラムに対して明示的に値を指定する必要はなく、Delta Lakeは自動で値を計算します。例えば、(日付でテーブルをパーティショニングするために)タイムスタンプのカラムから自動で日付のカラムを生成することができます。テーブルに書き込みを行う際に必要なのはタイムスタンプのカラムのデータを指定することだけです。しかし、明示的に値を指定する際には、値は制約(<value> <=> <generation expression>) IS TRUE
を満足する必要があり、そうでない場合には書き込みはエラーとなり失敗します。
重要!
generated columnを持つテーブルでは、デフォルトよりも新しいテーブルライタープロトコルが必要となります。テーブルプロトコルのバージョンが何で、新しいテーブルプロトコルのバージョンを設定することが何を意味するのかを理解するためには、Delta Lakeのテーブルプロトコルのバージョン管理をご覧ください。
以下のサンプルでgenerated columnを持つテーブルの作成方法を説明しています。
CREATE TABLE default.people10m (
id INT,
firstName STRING,
middleName STRING,
lastName STRING,
gender STRING,
birthDate TIMESTAMP,
dateOfBirth DATE GENERATED ALWAYS AS (CAST(birthDate AS DATE)),
ssn STRING,
salary INT
)
DeltaTable.create(spark) \
.tableName("default.people10m") \
.addColumn("id", "INT") \
.addColumn("firstName", "STRING") \
.addColumn("middleName", "STRING") \
.addColumn("lastName", "STRING", comment = "surname") \
.addColumn("gender", "STRING") \
.addColumn("birthDate", "TIMESTAMP") \
.addColumn("dateOfBirth", DateType(), generatedAlwaysAs="CAST(birthDate AS DATE)") \
.addColumn("ssn", "STRING") \
.addColumn("salary", "INT") \
.execute()
DeltaTable.create(spark)
.tableName("default.people10m")
.addColumn("id", "INT")
.addColumn("firstName", "STRING")
.addColumn("middleName", "STRING")
.addColumn(
DeltaTable.columnBuilder("lastName")
.dataType("STRING")
.comment("surname")
.build())
.addColumn("lastName", "STRING", comment = "surname")
.addColumn("gender", "STRING")
.addColumn("birthDate", "TIMESTAMP")
.addColumn(
DeltaTable.columnBuilder("dateOfBirth")
.dataType(DateType)
.generatedAlwaysAs("CAST(dateOfBirth AS DATE)")
.build())
.addColumn("ssn", "STRING")
.addColumn("salary", "INT")
.execute()
generated columnは通常のカラムと同じように格納されます。すなわち、ストレージを消費します。
generated columnには以下の制約があります。
- 生成のエクスプレッションには、以下のタイプの関数を除いて同じ引数を与えた際に同じ結果を常に返却するSparkにおけるSQL関数を使用することができます。
- ユーザー定義関数
- 集計関数
- ウィンドウ関数
- 複数の行を返す関数
- Databricksランタイム8.4以降でのPythonサポートでは、Delta Lakeはパーティションカラムが以下のエクスプレッションのいずれかで定義された際には常に、クエリーに対するパーティションフィルターを生成することができます。
-
CAST(col AS DATE)
およびcol
の型がTIMESTAMP
-
YEAR(col)
およびcol
の型がTIMESTAMP
-
YEAR(col)
,MONTH(col)
によって2つのパーティションカラムが定義され、col
の型がTIMESTAMP
-
YEAR(col)
,MONTH(col)
,DAY(col)
によって3つのパーティションカラムが定義され、col
の型がTIMESTAMP
-
YEAR(col)
,MONTH(col)
,DAY(col)
,HOUR(col)
によって4つのパーティションカラムが定義され、col
の型がTIMESTAMP
-
SUBSTRING(col, pos, len)
であり、col
の型がSTRING
-
DATE_FORMAT(col, format)
であり、col
の型がTIMESTAMP
上述のエクスプレッションのいずれかでパーティションカラムが定義され、生成エクスプレッションのベースとなるカラムを用いてクエリーがデータをフィルタリングする際、Delta Lakeはベースのカラムと生成されたカラムの関係性を参照し、可能であれば生成されたパーティションカラムに基づいてパーティションフィルターを生成します。例えば、以下のテーブルを考えます。
CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
eventDate date GENERATED ALWAYS AS (CAST(eventTime AS DATE))
)
PARTITIONED BY (eventType, eventDate)
そして、以下のクエリーを実行します。
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"
Delta Lakeはパーティションフィルターが指定されていない場合でも、上述のクエリーがパーティションdate=2020-10-01
のデータのみを読み込むように、パーティションフィルターを自動で生成します。
別の例として以下のテーブルを考えます。
CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
year INT GENERATED ALWAYS AS (YEAR(eventTime)),
month INT GENERATED ALWAYS AS (MONTH(eventTime)),
day INT GENERATED ALWAYS AS (DAY(eventTime))
)
PARTITIONED BY (eventType, year, month, day)
そして、以下のクエリーを実行します。
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"
Delta Lakeはパーティションフィルターが指定されていない場合でも、上述のクエリーがパーティションyear=2020/month=10/day=01
のデータのみを読み込むように、パーティションフィルターを自動で生成します。
Delta Lakeが自動でパーティションフィルターを生成しているのかどうかを確認するために、EXPLAIN句を用いて実行計画を確認することができます。