Aktualisieren eines Delta Lake-Tabellenschemas

Mit Delta Lake können Sie das Schema einer Tabelle aktualisieren. Die folgenden Typen von Änderungen werden unterstützt:

  • Hinzufügen neuer Spalten (an beliebigen Positionen)
  • Neuanordnen vorhandener Spalten
  • Umbenennen vorhandener Spalten

Sie können diese Änderungen explizit über die DDL oder implizit über die DML vornehmen.

Wichtig

Ein Update auf ein Delta-Tabellenschema ist ein Vorgang, der mit allen gleichzeitigen Delta-Schreibvorgängen in Konflikt steht.

Wenn Sie ein Delta-Tabellenschema aktualisieren, werden Streams, die aus dieser Tabelle lesen, beendet. Wenn der Stream fortgesetzt werden soll, müssen Sie ihn neu starten. Empfohlene Methoden finden Sie unter Produktionsüberlegungen für strukturiertes Streaming.

Explizites Aktualisieren des Schemas zum Hinzufügen von Spalten

ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)

Die NULL-Zulässigkeit ist standardmäßig auf true festgelegt.

Um einem geschachtelten Feld eine Spalte hinzuzufügen, verwenden Sie folgenden Befehl:

ALTER TABLE table_name ADD COLUMNS (col_name.nested_col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)

Wenn das Schema vor der Ausführung von ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1) z. B. folgendermaßen lautet:

- root
| - colA
| - colB
| +-field1
| +-field2

lautet das Schema nach der Ausführung folgendermaßen:

- root
| - colA
| - colB
| +-field1
| +-nested
| +-field2

Hinweis

Das Hinzufügen geschachtelter Spalten wird nur für Strukturen unterstützt. Arrays und Zuordnungen werden nicht unterstützt.

Explizites Aktualisieren des Schemas zum Ändern des Kommentars oder der Reihenfolge von Spalten

ALTER TABLE table_name ALTER [COLUMN] col_name (COMMENT col_comment | FIRST | AFTER colA_name)

Um eine Spalte in einem geschachtelten Feld zu ändern, verwenden Sie folgenden Befehl:

ALTER TABLE table_name ALTER [COLUMN] col_name.nested_col_name (COMMENT col_comment | FIRST | AFTER colA_name)

Wenn das Schema vor der Ausführung von ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST z. B. folgendermaßen lautet:

- root
| - colA
| - colB
| +-field1
| +-field2

lautet das Schema nach der Ausführung folgendermaßen:

- root
| - colA
| - colB
| +-field2
| +-field1

Explizites Aktualisieren des Schemas zum Ersetzen von Spalten

ALTER TABLE table_name REPLACE COLUMNS (col_name1 col_type1 [COMMENT col_comment1], ...)

Bei der Ausführung der folgenden DDL-Anweisung:

ALTER TABLE boxes REPLACE COLUMNS (colC STRING, colB STRUCT<field2:STRING, nested:STRING, field1:STRING>, colA STRING)

wenn das Schema vorher folgendermaßen lautet:

- root
| - colA
| - colB
| +-field1
| +-field2

lautet das Schema nach der Ausführung folgendermaßen:

- root
| - colC
| - colB
| +-field2
| +-nested
| +-field1
| - colA

Explizites Aktualisieren des Schemas zum Umbenennen von Spalten

Wichtig

Dieses Feature befindet sich in der Public Preview.

Hinweis

Dieses Feature ist in Databricks Runtime 10.2 und höher verfügbar.

Um Spalten umzubenennen, ohne vorhandene Daten der Spalten neu zu schreiben, müssen Sie die Spaltenzuordnung für die Tabelle aktivieren. Weitere Informationen finden Sie unter Rename and drop columns with Delta Lake column mapping (Umbenennen und Löschen von Spalten mit Delta Lake-Spaltenzuordnung).

So benennen Sie eine Spalte um

ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name

So benennen Sie ein geschachteltes Feld um

ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field

Bei der Ausführung des folgenden Befehls:

ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001

wenn das Schema vorher folgendermaßen lautet:

- root
| - colA
| - colB
| +-field1
| +-field2

lautet das Schema nach der Ausführung folgendermaßen:

- root
| - colA
| - colB
| +-field001
| +-field2

Weitere Informationen finden Sie unter Rename and drop columns with Delta Lake column mapping (Umbenennen und Löschen von Spalten mit Delta Lake-Spaltenzuordnung).

Explizites Aktualisieren des Schemas zum Löschen von Spalten

Wichtig

Dieses Feature befindet sich in der Public Preview.

Hinweis

Dieses Feature ist ab Databricks Runtime 11.0 verfügbar.

Wenn Sie Spalten im Rahmen eines reinen Metadatenvorgangs löschen möchten, ohne Datendateien neu zu schreiben, müssen Sie die Spaltenzuordnung für die Tabelle aktivieren. Weitere Informationen finden Sie unter Rename and drop columns with Delta Lake column mapping (Umbenennen und Löschen von Spalten mit Delta Lake-Spaltenzuordnung).

Wichtig

Wenn Sie eine Spalte über Metadaten löschen, werden die zugrunde liegenden Daten für die Spalte in Dateien nicht gelöscht. Zum Löschen der Daten der gelöschten Spalte können Sie REORG TABLE verwenden, um Dateien neu zu schreiben. Anschließend können Sie VACUUM verwenden, um die Dateien, die die Daten der gelöschten Spalte enthalten, physisch zu löschen.

So löschen Sie eine Spalte

ALTER TABLE table_name DROP COLUMN col_name

So löschen Sie mehrere Spalten

ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)

Explizites Aktualisieren des Schemas zum Ändern des Spaltentyps oder -namens

Sie können den Typ oder Namen einer Spalte ändern oder eine Spalte löschen, indem Sie die Tabelle neu schreiben. Verwenden Sie hierzu die Option overwriteSchema.

Das folgende Beispiel zeigt das Ändern eines Spaltentyps:

(spark.read.table(...)
  .withColumn("birthDate", col("birthDate").cast("date"))
  .write
  .mode("overwrite")
  .option("overwriteSchema", "true")
  .saveAsTable(...)
)

Das folgende Beispiel zeigt das Ändern eines Spaltennamens:

(spark.read.table(...)
  .withColumnRenamed("dateOfBirth", "birthDate")
  .write
  .mode("overwrite")
  .option("overwriteSchema", "true")
  .saveAsTable(...)
)

Hinzufügen von Spalten mit der automatischen Schemaaktualisierung

Spalten, die im DataFrame vorhanden sind, aber in der Tabelle fehlen, werden unter folgenden Bedingungen automatisch im Rahmen einer Schreibtransaktion hinzugefügt:

  • Für write oder writeStream gilt .option("mergeSchema", "true").
  • spark.databricks.delta.schema.autoMerge.enabled ist gleich true.

Wenn beide Optionen angegeben werden, besitzt die DataFrameWriter-Option Vorrang. Die hinzugefügten Spalten werden am Ende der Struktur angefügt, in der sie vorhanden sind. Die Groß-/Kleinschreibung wird beim Anfügen einer neuen Spalte beibehalten.

Hinweis

  • mergeSchema kann nicht mit INSERT INTO oder .write.insertInto() verwendet werden.

Automatische Schemaentwicklung für Delta Lake-Merge

Die Schemaentwicklung ermöglicht es Benutzern, Schemakonflikte zwischen der Ziel- und der Quelltabelle beim Zusammenführen zu beheben. Es werden die folgenden beiden Fälle behandelt:

  1. Eine Spalte in der Quelltabelle ist in der Zieltabelle nicht vorhanden. Die neue Spalte wird dem Zielschema hinzugefügt, und ihre Werte werden mithilfe der Quellwerte eingefügt oder aktualisiert.
  2. Eine Spalte in der Zieltabelle ist in der Quelltabelle nicht vorhanden. Das Zielschema bleibt unverändert. Die Werte in der zusätzlichen Zielspalte bleiben entweder unverändert (für UPDATE) oder werden auf NULL (für INSERT) festgelegt.

Wichtig

Um die Schemaentwicklung zu verwenden, müssen Sie die Spark-Sitzungskonfigurationspark.databricks.delta.schema.autoMerge.enabled auf true festlegen, bevor Sie den Befehl merge ausführen.

Hinweis

  • In Databricks Runtime 12.2 und höher können Spalten, die in der Quelltabelle vorhanden sind, in Einfüge- oder Updateaktionen durch den Namen angegeben werden. In Databricks Runtime 12.1 und niedriger können nur INSERT *- oder UPDATE SET *-Aktionen für die Schemaentwicklung mit Merge verwendet werden.

Hier sind einige Beispiele für die Auswirkungen eines merge-Vorgangs mit und ohne Schemaentwicklung.

Spalten Abfrage (in SQL) Verhalten ohne Schemaentwicklung (Standard) Verhalten mit Schemaentwicklung
Zielspalten: key, value

Quellspalten: key, value, new_value
MERGE INTO target_table t
USING source_table s
ON t.key = s.key
WHEN MATCHED
THEN UPDATE SET *
WHEN NOT MATCHED
THEN INSERT *
Das Tabellenschema bleibt unverändert. Nur die Spalten key und value werden aktualisiert/eingefügt. Das Tabellenschema wird in (key, value, new_value) geändert. Vorhandene Datensätze mit Übereinstimmungen werden mit value und new_value in der Quelle aktualisiert. Neue Zeilen werden mit dem Schema (key, value, new_value) eingefügt.
Zielspalten: key, old_value

Quellspalten: key, new_value
MERGE INTO target_table t
USING source_table s
ON t.key = s.key
WHEN MATCHED
THEN UPDATE SET *
WHEN NOT MATCHED
THEN INSERT *
Die Aktionen UPDATE und INSERT lösen einen Fehler aus, weil die Zielspalte old_value in der Quelle nicht enthalten ist. Das Tabellenschema wird in (key, old_value, new_value) geändert. Vorhandene Datensätze mit Übereinstimmungen werden mit new_value in der Quelle aktualisiert, während old_value unverändert bleibt. Neue Datensätze werden mit dem angegebenen key, new_valueund NULL für old_valueeingefügt.
Zielspalten: key, old_value

Quellspalten: key, new_value
MERGE INTO target_table t
USING source_table s
ON t.key = s.key
WHEN MATCHED
THEN UPDATE SET new_value = s.new_value
UPDATE löst einen Fehler aus, weil die Spalte new_value in der Zieltabelle nicht enthalten ist. Das Tabellenschema wird in (key, old_value, new_value) geändert. Vorhandene Datensätze mit Übereinstimmungen werden mit dem new_value in der Quelle aktualisiert, wobei old_value unverändert bleibt, und bei nicht übereinstimmenden Datensätze wurde NULL als new_value eingegeben. Siehe den Hinweis (1).
Zielspalten: key, old_value

Quellspalten: key, new_value
MERGE INTO target_table t
USING source_table s
ON t.key = s.key
WHEN NOT MATCHED
THEN INSERT (key, new_value) VALUES (s.key, s.new_value)
INSERT löst einen Fehler aus, weil die Spalte new_value in der Zieltabelle nicht enthalten ist. Das Tabellenschema wird in (key, old_value, new_value) geändert. Neue Datensätze werden mit dem angegebenen key, new_valueund NULL für old_valueeingefügt. Bei vorhandenen Datensätzen wurde NULL als new_value eingegeben, wobei old_value unverändert gelassen wurde. Siehe den Hinweis (1).

(1) Dieses Verhalten ist in Databricks Runtime 12.2 und höher verfügbar; in Databricks Runtime 12.1 und niedriger wird in diesem Fall ein Fehler angezeigt.

Ausschließen von Spalten mit Delta Lake-Merges

In Databricks Runtime 12.0 und höher können Sie EXCEPT-Klauseln in Mergebedingungen verwenden, um Spalten explizit auszuschließen. Das Verhalten des Schlüsselworts EXCEPT hängt davon ab, ob die Schemaentwicklung aktiviert ist oder nicht.

Wenn die Schemaentwicklung deaktiviert ist, gilt das EXCEPT-Schlüsselwort für die Liste der Spalten in der Zieltabelle und ermöglicht den Ausschluss von Spalten von UPDATE- oder INSERT-Aktionen. Ausgeschlossene Spalten werden auf null festgelegt.

Wenn die Schemaentwicklung aktiviert ist, gilt das EXCEPT-Schlüsselwort für die Liste der Spalten in der Quelltabelle und ermöglicht es, Spalten von der Schemaentwicklung auszuschließen. Eine neue Spalte in der Quelle, die im Ziel nicht vorhanden ist, wird dem Zielschema nicht hinzugefügt, wenn sie in der EXCEPT-Klausel aufgeführt ist. Ausgeschlossene Spalten, die bereits im Ziel vorhanden sind, werden auf null festgelegt.

Die folgenden Beispiele veranschaulichen diese Syntax:

Spalten Abfrage (in SQL) Verhalten ohne Schemaentwicklung (Standard) Verhalten mit Schemaentwicklung
Zielspalten: id, title, last_updated

Quellspalten: id, title, review, last_updated
MERGE INTO target t
USING source s
ON t.id = s.id
WHEN MATCHED
THEN UPDATE SET last_updated = current_date()
WHEN NOT MATCHED
THEN INSERT * EXCEPT (last_updated)
Übereinstimmende Zeilen werden aktualisiert, indem das Feld last_updated auf das aktuelle Datum festgelegt wird. Neue Zeilen werden mithilfe von Werten für id und titleeingefügt. Das ausgeschlossene Feld last_updated ist auf null festgelegt. Das Feld review wird ignoriert, da es nicht im Ziel enthalten ist. Übereinstimmende Zeilen werden aktualisiert, indem das Feld last_updated auf das aktuelle Datum festgelegt wird. Das Schema wurde weiterentwickelt, um das Feld reviewhinzuzufügen. Neue Zeilen werden unter Verwendung aller Quellfelder mit Ausnahme von last_updated eingefügt, das auf null festgelegt ist.
Zielspalten: id, title, last_updated

Quellspalten: id, title, review, internal_count
MERGE INTO target t
USING source s
ON t.id = s.id
WHEN MATCHED
THEN UPDATE SET last_updated = current_date()
WHEN NOT MATCHED
THEN INSERT * EXCEPT (last_updated, internal_count)
INSERT löst einen Fehler aus, weil die Spalte internal_count in der Zieltabelle nicht enthalten ist. Übereinstimmende Zeilen werden aktualisiert, indem das Feld last_updated auf das aktuelle Datum festgelegt wird. Das Feld review wird der Zieltabelle hinzugefügt, aber das Feld internal_count wird ignoriert. Bei neu eingefügten Zeilen wird last_updated auf null festgelegt.

Automatische Schemaentwicklung für Strukturarrays

Delta MERGE INTO unterstützt das Auflösen von Strukturfeldern anhand des Namens und das Entwickeln von Schemas für Arrays von Strukturen. Wenn die Schemaentwicklung aktiviert wurde, werden Zieltabellenschemas für Arrays von Strukturen weiterentwickelt. Das funktioniert auch bei geschachtelten Strukturen innerhalb von Arrays.

Hinweis

In Databricks Runtime 12.2 und höher können Strukturfelder, die in der Quelltabelle vorhanden sind, in Einfüge- oder Updatebefehlen durch den Namen angegeben werden. In Databricks Runtime 12.1 und niedriger können nur die Befehle INSERT * oder UPDATE SET * für die Schemaentwicklung mit Merge verwendet werden.

Im Folgenden finden Sie einige Beispiele für die Auswirkungen von Zusammenführungsvorgängen mit und ohne Schemaentwicklung bei Arrays von Strukturen.

Quellschema Zielschema Verhalten ohne Schemaentwicklung (Standard) Verhalten mit Schemaentwicklung
array<struct<b: string, a: string>> array<struct<a: int, b: int>> Das Tabellenschema bleibt unverändert. Spalten werden anhand des Namens aufgelöst und aktualisiert oder eingefügt. Das Tabellenschema bleibt unverändert. Spalten werden anhand des Namens aufgelöst und aktualisiert oder eingefügt.
array<struct<a: int, c: string, d: string>> array<struct<a: string, b: string>> update und insert lösen Fehler aus, weil c und d in der Zieltabelle nicht enthalten sind. Das Tabellenschema wird in „array<struct<a: string, b: string, c: string, d: string>>“ geändert. c und d werden für vorhandene Einträge in der Zieltabelle als NULL eingefügt. update und insert füllen Einträge in der Quelltabelle mit a, umgewandelt in „string“, und b als NULL.
array<struct<a: string, b: struct<c: string, d: string>>> array<struct<a: string, b: struct<c: string>>> update und insert lösen Fehler aus, weil d in der Zieltabelle nicht enthalten ist. Das Zielschema wird in „array<struct<a: string, b: struct<c: string, d: string>>>“ geändert. d wird für vorhandene Einträge in der Zieltabelle als NULL eingefügt.

Handhabung von NullType-Spalten bei Schemaaktualisierungen

Da Parquet NullType nicht unterstützt, werden NullType-Spalten beim Schreiben in Delta-Tabellen aus dem DataFrame gelöscht, aber weiterhin im Schema gespeichert. Wenn ein anderer Datentyp für diese Spalte empfangen wird, führt Delta Lake das Schema mit dem neuen Datentyp zusammen. Wenn Delta Lake einen NullType für eine vorhandene Spalte empfängt, wird das alte Schema beibehalten, und die neue Spalte wird während des Schreibvorgangs gelöscht.

NullType wird im Streaming nicht unterstützt. Da Sie bei Verwendung von Streaming Schemas festlegen müssen, sollte dieser Fall sehr selten vorkommen. NullType wird außerdem für komplexe Typen wie ArrayType und MapType nicht akzeptiert.

Ersetzen von Tabellenschemas

Standardmäßig wird das Schema durch das Überschreiben der Daten in einer Tabelle nicht überschrieben. Wenn Sie eine Tabelle mit mode("overwrite") ohne replaceWhere überschreiben, möchten Sie vielleicht dennoch das Schema der geschriebenen Daten überschreiben. Sie ersetzen das Schema und die Partitionierung der Tabelle, indem Sie die Option overwriteSchema auf true festlegen:

df.write.option("overwriteSchema", "true")

Wichtig

Sie können overwriteSchema nicht als true angeben, wenn Sie die dynamische Partitionsüberschreibung verwenden.