次の方法で共有


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-MMyyyy-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 構文オプションをすべて表示するには、CREATE TABLE [USING]を参照してください。

必要に応じて、次の内容を指定できます。

  • 開始値。
  • 正または負のステップ サイズ。

開始値とステップ サイズの両方が既定で 10のステップ サイズを指定することはできません。

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 列を含む新しいテーブルを作成し、既存のデータを設定するには、次の操作を行います。

  1. ID 列の定義やその他のテーブル プロパティなど、適切なスキーマを持つテーブルを作成します。
  2. 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 列の ADDREPLACECHANGE に使用できません。
  • 既存のレコードの ID 列の値を更新することはできません。

Note

既存のレコードの IDENTITY 値を変更するには、そのレコードを削除し、それを新しいレコードとして INSERT する必要があります。