メインコンテンツまでスキップ

Delta Lakeのジェネレーテッドカラム

備考

プレビュー

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

Delta Lakeの生成された列は、テーブル内の他の列に対するユーザー定義式から値を自動的にコンピュートし、格納します。生成された列に値を指定せずにテーブルに書き込むと、Delta Lake はそれらを自動的にコンピュートします。値を指定する場合、それらは(<value> <=> <generation expression>) IS TRUEを満たす必要があります。そうしないと、書き込みは失敗します。Databricksの制約を参照してください。

たとえば、price_with_taxのデータを指定する書き込みを必要とせずに、base_price * 1.1からprice_with_tax列をコンピュートできます。

通常の列と同様に、生成された列はテーブルの基になるデータファイルに物理的に格納されます。

注記

生成された列を有効にすると、テーブルライタープロトコルがアップグレードされます。これは、外部の Delta Lake クライアントとの互換性に影響を与える可能性があります。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
)

サポートされている式​

生成式は、同じ入力に対して常に同じ結果を返す決定論的なSQL関数を使用できます。例えば:

  • 算術演算: base_price * 1.1
  • 文字列関数:CONCAT(first_name, ' ', last_name) SUBSTRING(col, 1, 3)
  • 日付関数:CAST(birthDate AS DATE)、 YEAR(eventTime)

以下の関数タイプはサポートされていません:

  • ユーザー定義関数
  • 集計関数
  • ウィンドウ関数
  • 複数の行を返す関数

パーティションフィルター生成​

注記

Databricks は、すべての新しい Delta Lake テーブルにリキッドクラスタリングを推奨しています。「テーブルにリキッドクラスタリングを使用する」を参照してください。

生成された列を使用してテーブルをパーティション化し、ベース列に対してクエリを実行すると、Delta Lake は可能な場合、パーティションフィルターを自動的に導出します。生成されたパーティション列で明示的にフィルター処理する必要はありません。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。

例: 単一のパーティション​

たとえば、次のテーブルがあるとします。

SQL
CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
eventDate date GENERATED ALWAYS AS (CAST(eventTime AS DATE))
)
PARTITIONED BY (eventType, eventDate)

その後に以下のクエリーを実行する場合:

SQL
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" AND eventTime <= "2020-10-01 12:00:00"

Delta Lake は、パーティションフィルターが指定されていなくても、以前のクエリがパーティション date=2020-10-01 のデータのみを読み取るように、自動的にパーティションフィルターを生成します。

EXPLAIN 句を使用し、指定されたプランを確認して、Delta Lake がパーティション フィルターを自動的に生成するかどうかを確認します。

例:複数のパーティション​

たとえば、次のテーブルがあるとします。

SQL
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)

その後に以下のクエリーを実行する場合:

SQL
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" AND eventTime <= "2020-10-01 12:00:00"

Delta Lake は、パーティションフィルターが指定されていなくても、以前のクエリがパーティション year=2020/month=10/day=01 のデータのみを読み取るように、自動的にパーティションフィルターを生成します。

EXPLAIN 句を使用し、指定されたプランを確認して、Delta Lake がパーティション フィルターを自動的に生成するかどうかを確認します。

ID 列​

重要

Delta Lake テーブルで ID 列を宣言すると、並列トランザクションは無効になります。ターゲットテーブルへの並列書き込みが不要なユースケースでのみ、ID 列を使用してください。ID 列の制限を参照してください。

Delta Lake の 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)
)
注記

ID 列のScalaとPython APIは、Databricks Runtime 16.0 以降で使用できます。

ID 列を持つテーブルを作成するためのすべての SQL 構文オプションについては、「CREATE TABLE [USING]」を参照してください。

オプションで、以下の項目を指定できます:

  • 開始値です。
  • ステップサイズ。正または負の値を指定できます。

開始値とステップサイズは両方とも1がデフォルトです。0 のステップサイズを指定することはできません。

ID列によって割り当てられる値は一意であり、指定されたステップの方向に、指定されたステップサイズの倍数でインクリメントされますが、連続していることは保証されません。例えば、開始値が0でステップサイズが2の場合、すべての値は正の偶数ですが、一部の偶数はスキップされる可能性があります。

句GENERATED BY DEFAULT AS IDENTITYを使用する場合、INSERT操作では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 列の有効な値が含まれている場合、これらの値が使用されます。

SQL
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 (id, event_date, some_value)
SELECT id, event_date, some_value FROM old_table;

-- Insert records and generate new IDs
INSERT INTO new_table (event_date, some_value)
SELECT event_date, some_value FROM new_records;

ID列の制限​

ID 列の操作には、次の制限があります:

  • ID カラムが有効なテーブルでは、並列トランザクションはサポートされていません。
  • テーブルをID列でパーティション分割することはできません。
  • ALTER TABLEを使用してADD、REPLACE、またはCHANGEのID列を操作することはできません。
  • 既存のレコードのID列の値を更新することはできません。
注記

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

生成列と列マスク​

生成された列は、列マスクが適用されている列を参照できません。生成された値が、マスクによって保護されている基になるデータを明らかにするためです。エラーが発生し、クエリーは失敗します。「行フィルターと列マスク」を参照してください。

エラーの例を次に示します

  • マスクされた列を参照する式を持つジェネレーテッドカラムを作成することはできません。COLUMN_MASKS_GENERATED_COLUMN_UNSUPPORTED を発生します。

    SQL
    CREATE TABLE tbl (
    a INT MASK masking_function,
    generated_col INT GENERATED ALWAYS AS (a + 1)
    ) USING DELTA;
  • すでに生成された列が参照している列には、列マスクを適用できません。以下を発生 COLUMN_MASKS_REFERENCED_BY_GENERATED_COLUMN.ADD_MASK。

    SQL
    CREATE TABLE tbl (
    a INT,
    generated_col INT GENERATED ALWAYS AS (a + 1)
    ) USING DELTA;

    ALTER TABLE tbl ALTER COLUMN a SET MASK masking_function;
  • 生成された列が既にマスクされた列を参照しているテーブルからの読み取りもブロックされます。「COLUMN_MASKS_REFERENCED_BY_GENERATED_COLUMN.READ_BLOCKED」が発生します。

これらのエラーをすべて解決するには、生成された列とマスクされた列が重複しないようにテーブルを再設計する必要があります。