Delta Lake で生成されたカラム

プレビュー

この機能はパブリックプレビュー段階です。

Delta Lake では、Delta テーブル内の他の列に対するユーザー指定の関数に基づいて値が自動的に生成される特殊な型の列である生成列がサポートされています。 生成された列を持つテーブルに書き込むときに、それらの値を明示的に指定しない場合、Delta Lake は自動的に値を圧縮します。 たとえば、タイムスタンプ列から日付列 (テーブルを日付でパーティション分割するため) を自動的に生成できます。テーブルへの書き込みでは、タイムスタンプ列のデータを指定するだけで済みます。 しかし、明示的に値を指定する場合、その値は制約(<value> <=> <generation expression>) IS TRUEを満たさなければなりません。

重要

生成された列で作成されたテーブルのテーブルライタープロトコルのバージョンは、デフォルトよりも高くなります。テーブルプロトコルのバージョニングと、テーブルプロトコルのバージョンが高いことの意味については、Databricksはどのようにデルタレイクの機能の互換性を管理しているのかを参照してください。

生成列を含むテーブルを作成する

次の例は、生成されたカラムを持つテーブルを作成する方法を示しています:

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 では、パーティション列が次のいずれかの式で定義されている場合は常に、クエリーのパーティションフィルターを生成できます。

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 列を宣言するための基本的な構文を示しています。

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 カラムを持つ新しいテーブルを作成し、既存のデータを設定するには、次の手順を実行します。

  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 列によって表をパーティション化することはできません。

  • ALTER TABLE を使用して ID 列ADDREPLACE、またはCHANGEすることはできません。

  • 既存のレコードの ID 列の値は更新できません。

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