Delta Lake で生成された列
プレビュー
この機能は パブリック プレビュー段階です。
Delta Lake は、Delta テーブル内の他の列に対するユーザー指定の関数に基づいて値が自動的に生成される特殊な種類の列である生成列をサポートしています。 生成されたカラムを持つテーブルに書き込むときに、カラムに値を明示的に指定しない場合、 Delta Lake は自動的に値をコンピュートします。 たとえば、タイムスタンプ列から日付列 (テーブルを日付でパーティション分割するため) を自動的に生成できます。テーブルへの書き込みでは、タイムスタンプ列のデータを指定するだけで済みます。 ただし、明示的に値を指定する場合、値は制約(<value> <=> <generation expression>) IS TRUE
を満たす必要があり、そうでない場合は書き込みがエラーで失敗します。
生成されたカラムを使用して作成されたテーブルは、デフォルトよりもテーブルライタープロトコルのバージョンが高くなります。「Delta Lake 機能の互換性とプロトコル」を参照して、テーブル プロトコルのバージョン管理と、テーブル プロトコル バージョンの上位バージョンを使用することの意味を理解してください。
生成された列を含むテーブルを作成する
次の例は、生成されたカラムを持つテーブルを作成する方法を示しています:
- SQL
- Python
- Scala
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()
生成された列は、通常の列であるかのように格納されます。つまり、それらはストレージを占有します。
生成される列には、次の制限が適用されます。
- 生成式では、次の種類の関数を除き、同じ引数値が与えられたときに常に同じ結果を返す Spark の任意の SQL 関数を使用できます。
- ユーザー定義関数
- 集計関数
- ウィンドウ関数
- 複数の行を返す関数
Delta Lake では、パーティション列が次のいずれかの式で定義されている場合は常に、クエリーのパーティションフィルターを生成できます。
Photon は、Databricks Runtime 10.4 LTS 以下で必要です。 Photon は、Databricks Runtime 11.3 LTS 以降では必要ありません。
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
- Python
- Scala
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)
)
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()
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()
ID 列のScalaとPython APIsは、Databricks Runtime 16.0 以降で使用できます。
ID カラムを持つテーブルを作成するためのすべての SQL 構文オプションについては、 CREATE TABLE [USING]を参照してください。
オプションで、次の項目を指定できます。
- 開始値。
- ステップサイズ。正または負の値を指定できます。
開始値とステップ サイズの両方が デフォルト から 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
、または ID 列CHANGE
することはできません。- 既存のレコードの ID 列の値を更新することはできません。
既存のレコードの IDENTITY
値を変更するには、レコードを削除して新しいレコードとして INSERT
する必要があります。