Delta Lake で生成された列
重要
この機能はパブリック プレビュー段階にあります。
Delta Lake では、生成された列がサポートされています。これは、Delta テーブル内の他の列に対するユーザー指定の関数に基づいて値が自動的に生成される、特殊なタイプの列です。 生成された列を含むテーブルに書き込み、その値を明示的に指定していない場合、Delta Lake が自動的に値を計算します。 たとえば、テーブルを日付でパーティション分割するために、タイムスタンプ列から日付列を自動的に生成できます。テーブルへ書き込みするとき必要なのは、タイムスタンプ列のデータを指定するだけです。 ただし、明示的にそれらの値を指定する場合、値は制約 (<value> <=> <generation expression>) IS TRUE
を満たす必要があります。そうしなければ、書き込みは失敗し、エラーが発生します。
重要
生成された列を使用して作成されたテーブルでは、テーブル ライター プロトコルのバージョンは既定より上位になります。 テーブル プロトコルのバージョン管理と、テーブル プロトコルのバージョンを上位のバージョンにする意味については、「Azure Databricks で Delta Lake 機能の互換性を管理する方法」を参照してください。
生成された列を含むテーブルを作成する
次の例では、列が生成されたテーブルの作成方法を示しています。
SQL
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
)
Python
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()
Scala
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()
生成された列は、通常の列と同じように格納されます。 つまり、ストレージを占有します。
生成される列には、次の制限が適用されます。
- 生成式が使用できる Spark のあらゆる SQL 関数が、同じ引数値が指定された時、常に同じ結果を返します。ただし、次の種類の関数は除きます。
- ユーザー定義関数。
- 集計関数。
- ウィンドウ関数。
- 複数の行を返す関数。
パーティション列が次のいずれかの式で定義されている場合は常に、Delta Lake でクエリのパーティション フィルターを生成できます。
Note
Databricks Runtime 10.4 LTS 以下では Photon が必要です。 Databricks Runtime 11.3 LTS 以降では Photon は不要です。
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
。- 日付形式は、
yyyy-MM
とyyyy-MM-dd-HH
のパターンのみ使用できます。 - Databricks Runtime 10.4 LTS 以降では、
yyyy-MM-dd
のパターンを使用することもできます。
- 日付形式は、
パーティション列が上記のいずれかの式で定義され、基になる生成式のベース列を使用してクエリでデータがフィルター処理される場合、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
内のデータのみを読み取ります。
EXPLAIN 句を使用して指定されたプランを確認すると、Delta Lake でパーティション フィルターが自動的に生成されるかどうかを確認できます。
Delta Lake で ID 列を使用する
重要
Delta テーブルで ID 列を宣言すると、同時実行トランザクションが無効になります。 ID 列は、ターゲット テーブルへの同時書き込みが不要なユース ケースでのみ使用してください。
Delta Lake ID 列は、テーブルに挿入された各レコードに一意の値を割り当てる、生成された列の一種です。 次の例は、create table ステートメント中に ID 列を宣言するための基本的な構文を示しています。
SQL
CREATE TABLE table_name (
id_col1 BIGINT GENERATED ALWAYS AS IDENTITY,
id_col2 BIGINT GENERATED ALWAYS AS IDENTITY (START WITH -1 INCREMENT BY 1),
id_col3 BIGINT GENERATED BY DEFAULT AS IDENTITY,
id_col4 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH -1 INCREMENT BY 1)
)
Python
from delta.tables import DeltaTable, IdentityGenerator
from pyspark.sql.types import LongType
DeltaTable.create()
.tableName("table_name")
.addColumn("id_col1", dataType=LongType(), generatedAlwaysAs=IdentityGenerator())
.addColumn("id_col2", dataType=LongType(), generatedAlwaysAs=IdentityGenerator(start=-1, step=1))
.addColumn("id_col3", dataType=LongType(), generatedByDefaultAs=IdentityGenerator())
.addColumn("id_col4", dataType=LongType(), generatedByDefaultAs=IdentityGenerator(start=-1, step=1))
.execute()
Scala
import io.delta.tables.DeltaTable
import org.apache.spark.sql.types.LongType
DeltaTable.create(spark)
.tableName("table_name")
.addColumn(
DeltaTable.columnBuilder(spark, "id_col1")
.dataType(LongType)
.generatedAlwaysAsIdentity().build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col2")
.dataType(LongType)
.generatedAlwaysAsIdentity(start = -1L, step = 1L).build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col3")
.dataType(LongType)
.generatedByDefaultAsIdentity().build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col4")
.dataType(LongType)
.generatedByDefaultAsIdentity(start = -1L, step = 1L).build())
.execute()
Note
ID 列用の Scala API と Python API は、Databricks Runtime 16.0 以降で使用できます。
ID 列を持つテーブルを作成するための SQL 構文オプションをすべて表示するには、
必要に応じて、次の内容を指定できます。
- 開始値。
- 正または負のステップ サイズ。
開始値とステップ サイズの両方が既定で 1
。 0
のステップ サイズを指定することはできません。
ID 列によって割り当てられる値は、一意であり、指定したステップの方向と、指定したステップ サイズの倍数で増加しますが、連続する保証はありません。 たとえば、開始値が 0
でステップ サイズが 2
の場合、すべての値は正の偶数ですが、一部の偶数はスキップされる可能性があります。
句 GENERATED BY DEFAULT AS IDENTITY
を使用する場合、挿入操作で ID 列の値を指定できます。 手動で値を設定する機能をオーバーライドするように句を GENERATED ALWAYS AS IDENTITY
に変更します。
ID 列では BIGINT
型のみがサポートされ、割り当てられた値が BIGINT
でサポートされている範囲を超えた場合に操作は失敗します。
ID 列の値とデータの同期については、「 ALTER TABLE ..」を参照してください。COLUMN 句。
CTAS 列と ID 列
CREATE TABLE table_name AS SELECT
(CTAS) ステートメントを使用する場合、スキーマ、ID 列の制約、またはその他のテーブル仕様を定義することはできません。
ID 列を含む新しいテーブルを作成し、既存のデータを設定するには、次の操作を行います。
- ID 列の定義やその他のテーブル プロパティなど、適切なスキーマを持つテーブルを作成します。
INSERT
操作を実行します。
次の例では、DEFAULT
キーワードを使用して ID 列を定義します。 テーブルに挿入されたデータに ID 列の有効な値が含まれている場合は、これらの値が使用されます。
CREATE OR REPLACE TABLE new_table (
id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 5),
event_date DATE,
some_value BIGINT
);
-- Inserts records including existing IDs
INSERT INTO new_table
SELECT id, event_date, some_value FROM old_table;
-- Insert records and generate new IDs
INSERT INTO new_table
SELECT event_date, some_value FROM new_records;
ID 列の制限事項
ID 列を操作する場合、次の制限があります。
- ID 列が有効になっているテーブルでは、同時実行トランザクションはサポートされていません。
- ID 列でテーブルをパーティション分割することはできません。
ALTER TABLE
は、ID 列のADD
、REPLACE
、CHANGE
に使用できません。- 既存のレコードの ID 列の値を更新することはできません。
Note
既存のレコードの IDENTITY
値を変更するには、そのレコードを削除し、それを新しいレコードとして INSERT
する必要があります。