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 voncol
istTIMESTAMP
.YEAR(col)
und der Typ voncol
istTIMESTAMP
.- Zwei Partitionsspalten, die durch
YEAR(col), MONTH(col)
den Typcol
definiert sindTIMESTAMP
. - Drei Partitionsspalten, die durch
YEAR(col), MONTH(col), DAY(col)
den Typcol
definiert sindTIMESTAMP
. - Vier Partitionsspalten, die durch
YEAR(col), MONTH(col), DAY(col), HOUR(col)
den Typcol
definiert sindTIMESTAMP
. SUBSTRING(col, pos, len)
und der Typ voncol
istSTRING
.DATE_FORMAT(col, format)
und der Typ voncol
istTIMESTAMP
.- Sie können nur Datumsformate mit den folgenden Mustern verwenden:
yyyy-MM
undyyyy-MM-dd-HH
. - In Databricks Runtime 10.4 LTS und höher können Sie auch das folgende Muster verwenden:
yyyy-MM-dd
.
- Sie können nur Datumsformate mit den folgenden Mustern verwenden:
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 1
festgelegt. 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:
- Erstellen Sie eine Tabelle mit dem richtigen Schema, einschließlich der Definition der Identitätsspalte und anderer Tabelleneigenschaften.
- 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 BefehleADD
,REPLACE
oderCHANGE
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.