Freigeben über


Generierte Spalten in Delta Lake

Wichtig

Dieses Feature befindet sich in der Public Preview.

Delta Lake unterstützt generierte Spalten, bei denen es sich um einen speziellen Spaltentyp handelt, dessen Werte automatisch basierend auf einer benutzerspezifischen Funktion für andere Spalten in der Delta-Tabelle generiert werden. Wenn Sie in eine Tabelle mit generierten Spalten schreiben und keine expliziten Werte dafür angeben, berechnet Delta Lake die Werte automatisch. Beispielsweise können Sie automatisch eine Datumsspalte (für die Partitionierung der Tabelle nach Datum) aus der Zeitstempelspalte generieren. Alle Schreibvorgänge in der Tabelle müssen nur die Daten für die Zeitstempelspalte angeben. Wenn Sie dafür jedoch explizit Werte angeben, müssen die Werte die Einschränkung (<value> <=> <generation expression>) IS TRUE erfüllen, andernfalls verursacht der Schreibvorgang einen Fehler.

Wichtig

Tabellen, die mit generierten Spalten erstellt wurden, verfügen über eine höhere Tabellen-Writer-Protokollversion als die Standardversion. Siehe Wie verwaltet Azure Databricks die Kompatibilität der Delta Lake-Features?, um die Tabellenprotokollversionsverwaltung zu verstehen und zu erfahren, was es bedeutet, eine höhere Tabellenprotokollversion zu haben.

Erstellen einer Tabelle mit generierten Spalten

Im folgenden Beispiel wird das Erstellen einer Tabelle mit generierten Spalten veranschaulicht:

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

Generierte Spalten werden genau wie normale Spalten gespeichert. Das heißt, sie belegen Speicher.

Die folgenden Einschränkungen gelten für generierte Spalten:

  • Ein Generierungsausdruck kann alle SQL-Funktionen in Spark verwenden, die bei Angabe derselben Argumentwerte immer dasselbe Ergebnis zurückgeben. Hierbei bilden folgende Funktionstypen eine Ausnahme:
    • Benutzerdefinierte Funktionen.
    • Aggregatfunktionen.
    • Fensterfunktionen.
    • Funktionen, die mehrere Zeilen zurückgeben.

Delta Lake kann Partitionsfilter für eine Abfrage generieren, wenn eine Partitionsspalte durch einen der folgenden Ausdrücke definiert wird:

Hinweis

Photon ist in Databricks Runtime 10.4 LTS und früher erforderlich. Photon ist in Databricks Runtime 11.3 LTS und höher nicht erforderlich.

  • CAST(col AS DATE) und der Typ von col ist TIMESTAMP.
  • YEAR(col) und der Typ von col ist TIMESTAMP.
  • Zwei Partitionsspalten, die durch YEAR(col), MONTH(col) den Typ col definiert sind TIMESTAMP.
  • Drei Partitionsspalten, die durch YEAR(col), MONTH(col), DAY(col) den Typ col definiert sind TIMESTAMP.
  • Vier Partitionsspalten, die durch YEAR(col), MONTH(col), DAY(col), HOUR(col) den Typ col definiert sind TIMESTAMP.
  • SUBSTRING(col, pos, len) und der Typ von col ist STRING.
  • DATE_FORMAT(col, format) und der Typ von col ist TIMESTAMP.
    • Sie können nur Datumsformate mit den folgenden Mustern verwenden: yyyy-MM und yyyy-MM-dd-HH.
    • In Databricks Runtime 10.4 LTS und höher können Sie auch das folgende Muster verwenden: yyyy-MM-dd.

Wenn eine Partitionsspalte durch einen der vorherigen Ausdrücke definiert wird und daten mithilfe der zugrunde liegenden Basisspalte eines Generierungsausdrucks gefiltert werden, untersucht Delta Lake die Beziehung zwischen der Basisspalte und der generierten Spalte und füllt Partitionsfilter basierend auf der generierten Partitionsspalte nach Möglichkeit auf. Hier ist ein Beispiel mit der folgenden Tabelle angegeben:

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

Wenn Sie dann die folgende Abfrage ausführen:

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

Delta Lake generiert automatisch einen Partitionsfilter, sodass die vorherige Abfrage nur die Daten in der Partition date=2020-10-01 liest, auch wenn kein Partitionsfilter angegeben ist.

Hier ist ein weiteres Beispiel mit der folgenden Tabelle angegeben:

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)

Wenn Sie dann die folgende Abfrage ausführen:

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

Delta Lake generiert automatisch einen Partitionsfilter, sodass die vorherige Abfrage nur die Daten in der Partition year=2020/month=10/day=01 liest, auch wenn kein Partitionsfilter angegeben ist.

Sie können eine EXPLAIN-Klausel verwenden und den bereitgestellten Plan überprüfen, um festzustellen, ob Delta Lake automatisch Partitionsfilter generiert.

Verwenden von Identitätsspalten in Delta Lake

Wichtig

Durch das Deklarieren einer Identitätsspalte in einer Delta-Tabelle werden gleichzeitige Transaktionen deaktiviert. Verwenden Sie Identitätsspalten nur in Anwendungsfällen, in denen keine gleichzeitigen Schreibvorgänge in die Zieltabelle erforderlich sind.

Identitätsspalten in Delta Lake sind eine generierte Spalte, die eindeutige Werte für jeden in eine Tabelle eingefügten Datensatz zuweist. Das folgende Beispiel zeigt die grundlegende Syntax, die bei einer CREATE TABLE-Anweisung verwendet wird, um eine Identitätsspalte zu deklarieren:

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

Hinweis

Scala- und Python-APIs für Identitätsspalten sind in Databricks Runtime 16.0 und höher verfügbar.

Informationen zum Erstellen von Tabellen mit Identitätsspalten finden Sie unter CREATE TABLE [USING].

Optional können Sie Folgendes angeben:

  • Einen Anfangswert
  • Eine Schrittgröße, die positiv oder negativ sein kann

Sowohl der Startwert als auch die Schrittgröße werden standardmäßig 1festgelegt. Sie können keine Schrittgröße angeben 0.

Die von Identitätsspalten zugewiesenen Werte sind eindeutig und inkrementiert in Richtung des angegebenen Schritts und in Vielfachen der angegebenen Schrittgröße, aber es wird nicht garantiert, dass sie zusammenhängend sind. Beispiel: Alle Werte mit einem Anfangswert von 0 und einer Schrittgröße von 2 sind positiv, allerdings werden einige gerade Zahlen möglicherweise übersprungen.

Bei der Verwendung der GENERATED BY DEFAULT AS IDENTITY-Klausel können Werte für die Identitätsspalte durch Einfügevorgänge angegeben werden. Ändern Sie die Klausel in GENERATED ALWAYS AS IDENTITY, um die Möglichkeit zum manuellen Festlegen von Werten außer Kraft zu setzen.

Identitätsspalten unterstützen nur den BIGINT-Typ, und Vorgänge schlagen fehl, wenn der zugewiesene Wert den von BIGINT unterstützten Bereich überschreitet.

Informationen zum Synchronisieren von Identitätsspaltenwerten mit Daten finden Sie unter ALTER TABLE ... COLUMN-Klausel.

CTAS und Identitätsspalten

Bei Verwendung einer CTAS-Anweisung (CREATE TABLE table_name AS SELECT) können Sie keine Schemas, Einschränkungen für Identitätsspalten oder andere Tabellenspezifikationen definieren.

Gehen Sie wie folgt vor, um eine neue Tabelle mit einer Identitätsspalte zu erstellen und sie mit vorhandenen Daten aufzufüllen:

  1. Erstellen Sie eine Tabelle mit dem richtigen Schema, einschließlich der Definition der Identitätsspalte und anderer Tabelleneigenschaften.
  2. Führen Sie einen INSERT-Vorgang aus.

Im folgenden Beispiel wird die Identitätsspalte mit dem DEFAULT-Schlüsselwort definiert. Wenn die in die Tabelle eingefügten Daten gültige Werte für die Identitätsspalte enthalten, werden diese Werte verwendet.

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;

Einschränkungen bei Identitätsspalten

Beim Arbeiten mit Identitätsspalten gelten die folgenden Einschränkungen:

  • Gleichzeitige Transaktionen werden für Tabellen mit aktivierten Identitätsspalten nicht unterstützt.
  • Sie können eine Tabelle nicht durch eine Identitätsspalte partitionieren.
  • Sie können ALTER TABLE nicht verwenden, um die Befehle ADD, REPLACE oder CHANGE für eine Identitätsspalte auszuführen.
  • Sie können den Wert einer Identitätsspalte nicht für einen vorhandenen Datensatz aktualisieren.

Hinweis

Um den IDENTITY-Wert für einen vorhandenen Datensatz zu ändern, müssen Sie den Datensatz löschen und ihn mithilfe von INSERT als neuen Datensatz einfügen.