Memperbarui skema tabel Delta Lake

Delta Lake memungkinkan Anda memperbarui skema tabel. Jenis perubahan berikut ini didukung:

  • Menambahkan kolom baru (pada posisi arbitrer)
  • Menyusun ulang kolom yang ada
  • Mengganti nama kolom yang ada

Anda dapat membuat perubahan ini secara eksplisit menggunakan DDL atau secara implisit menggunakan DML.

Penting

Pembaruan ke skema tabel Delta adalah operasi yang bertentangan dengan semua operasi penulisan Delta bersamaan.

Saat Anda memperbarui skema tabel Delta, aliran yang dibaca dari tabel tersebut akan berakhir. Jika Anda ingin aliran berlanjut, Anda harus memulai ulang. Untuk metode yang direkomendasikan, lihat Pertimbangan produksi untuk Streaming Terstruktur.

Memperbarui skema secara eksplisit untuk menambahkan kolom

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

Secara default, nullability adalah true.

Untuk menambahkan kolom ke bidang bertumpuk, gunakan:

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

Misalnya, jika skema sebelum berjalan ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1) adalah:

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

skema setelahnya adalah:

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

Catatan

Menambahkan kolom bertumpuk hanya didukung untuk struktur. Array dan peta tidak didukung.

Memperbarui skema secara eksplisit untuk mengubah komentar atau pengurutan kolom

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

Untuk mengubah kolom di bidang bertumpuk, gunakan:

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

Misalnya, jika skema sebelum berjalan ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST adalah:

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

skema setelahnya adalah:

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

Memperbarui skema secara eksplisit untuk mengganti kolom

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

Misalnya, saat menjalankan DDL berikut:

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

jika skema sebelumnya adalah:

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

skema setelahnya adalah:

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

Memperbarui skema secara eksplisit untuk mengganti nama kolom

Penting

Fitur ini ada di Pratinjau Publik.

Catatan

Fitur ini tersedia di Databricks Runtime 10.4 LTS ke atas.

Untuk mengganti nama kolom tanpa menulis ulang data kolom yang ada, Anda harus mengaktifkan pemetaan kolom untuk tabel. Lihat Mengganti nama dan meletakkan kolom dengan pemetaan kolom Delta Lake.

Untuk mengganti nama kolom:

ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name

Untuk mengganti nama bidang bertumpu:

ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field

Misalnya, saat Anda menjalankan perintah berikut:

ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001

Jika skema sebelumnya adalah:

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

Lalu skema setelahnya adalah:

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

Lihat Mengganti nama dan meletakkan kolom dengan pemetaan kolom Delta Lake.

Memperbarui skema secara eksplisit untuk menghilangkan kolom

Penting

Fitur ini ada di Pratinjau Publik.

Catatan

Fitur ini tersedia di Databricks Runtime 11.3 LTS ke atas.

Untuk menghilangkan kolom sebagai operasi khusus metadata tanpa menulis ulang file data apa pun, Anda harus mengaktifkan pemetaan kolom untuk tabel. Lihat Mengganti nama dan meletakkan kolom dengan pemetaan kolom Delta Lake.

Penting

Menghilangkan kolom dari metadata tidak menghapus data yang mendasar untuk kolom dalam file. Untuk menghapus menyeluruh data kolom yang dihilangkan, Anda dapat menggunakan REORG TABLE untuk menulis ulang file. Anda kemudian dapat menggunakan VACUUM untuk menghapus file yang berisi data kolom yang dihilangkan secara fisik.

Untuk menjatuhkan kolom:

ALTER TABLE table_name DROP COLUMN col_name

Untuk menjatuhkan beberapa kolom:

ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)

Memperbarui skema secara eksplisit untuk mengubah jenis atau nama kolom

Anda dapat mengubah jenis atau nama kolom atau menjatuhkan kolom dengan menulis ulang tabel. Untuk melakukan ini, gunakan overwriteSchema opsi .

Contoh berikut menunjukkan perubahan jenis kolom:

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

Contoh berikut menunjukkan perubahan nama kolom:

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

Menambahkan kolom dengan pembaruan skema otomatis

Kolom yang ada di DataFrame tetapi hilang dari tabel secara otomatis ditambahkan sebagai bagian dari transaksi tulis saat:

  • write atau writeStream memiliki .option("mergeSchema", "true")
  • spark.databricks.delta.schema.autoMerge.enabled is true

Ketika kedua opsi ditentukan, opsi dari DataFrameWriter didahulukan. Kolom yang ditambahkan ke akhir struktur tempat mereka hadir. Kasus dipertahankan saat menambahkan kolom baru.

Catatan

  • mergeSchema tidak dapat digunakan dengan INSERT INTO atau .write.insertInto().

Evolusi skema otomatis untuk penggabungan Delta Lake

Evolusi skema memungkinkan pengguna untuk mengatasi ketidakcocokan skema antara tabel target dan sumber yang digabungkan. Ini menangani dua kasus berikut:

  1. Kolom dalam tabel sumber tidak ada dalam tabel target. Kolom baru ditambahkan ke skema target, dan nilainya disisipkan atau diperbarui menggunakan nilai sumber.
  2. Kolom dalam tabel target tidak ada dalam tabel sumber. Skema target dibiarkan tidak berubah; nilai dalam kolom target tambahan dibiarkan tidak berubah (untuk UPDATE) atau diatur ke NULL (untuk INSERT).

Penting

Untuk menggunakan evolusi skema, Anda harus mengatur konfigurasi spark.databricks.delta.schema.autoMerge.enabled sesi Spark ke true sebelum menjalankan merge perintah.

Catatan

  • Di Databricks Runtime 12.2 LTS ke atas, kolom yang ada dalam tabel sumber dapat ditentukan berdasarkan nama dalam tindakan sisipkan atau perbarui. Dalam Databricks Runtime 11.3 LTS dan di bawahnya, hanya INSERT * atau UPDATE SET * tindakan yang dapat digunakan untuk evolusi skema dengan penggabungan.

Berikut adalah beberapa contoh efek operasi merge dengan dan tanpa evolusi skema.

Kolom Kueri (dalam SQL) Perilaku tanpa evolusi skema (default) Perilaku dengan evolusi skema
Kolom target: key, value

Kolom sumber: 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 *
Skema tabel tetap tidak berubah; hanya kolom key, value saja yang diperbarui/disisipkan. Skema tabel diubah menjadi (key, value, new_value). Rekaman yang ada dengan kecocokan value diperbarui dengan dan new_value di sumber. Baris baru disisipkan dengan skema (key, value, new_value).
Kolom target: key, old_value

Kolom sumber: 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 *
Tindakan UPDATE dan INSERT menampilkan kesalahan karena kolom target old_value tidak ada di sumber. Skema tabel diubah menjadi (key, old_value, new_value). Rekaman yang ada dengan kecocokan new_value diperbarui dengan sumber yang tidak old_value berubah. Rekaman baru disisipkan dengan , , new_valuedan NULL yang ditentukan keyuntuk old_value.
Kolom target: key, old_value

Kolom sumber: 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 menampilkan kesalahan karena kolom new_value tidak ada di tabel target. Skema tabel diubah menjadi (key, old_value, new_value). Rekaman yang ada dengan kecocokan new_value diperbarui dengan di sumber yang tidak old_value berubah, dan rekaman yang tidak cocok telah NULL dimasukkan untuk new_value. Lihat catatan (1).
Kolom target: key, old_value

Kolom sumber: 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 menampilkan kesalahan karena kolom new_value tidak ada di tabel target. Skema tabel diubah menjadi (key, old_value, new_value). Rekaman baru disisipkan dengan , , new_valuedan NULL yang ditentukan keyuntuk old_value. Rekaman yang ada telah NULL dimasukkan untuk new_value membiarkan old_value tidak berubah. Lihat catatan (1).

(1) Perilaku ini tersedia di Databricks Runtime 12.2 LTS ke atas; Databricks Runtime 11.3 LTS dan kesalahan di bawah ini dalam kondisi ini.

Mengecualikan kolom dengan penggabungan Delta Lake

Di Databricks Runtime 12.2 LTS ke atas, Anda dapat menggunakan EXCEPT klausul dalam kondisi penggabungan untuk mengecualikan kolom secara eksplisit. Perilaku EXCEPT kata kunci bervariasi tergantung pada apakah evolusi skema diaktifkan atau tidak.

Dengan evolusi skema dinonaktifkan, EXCEPT kata kunci berlaku untuk daftar kolom dalam tabel target dan memungkinkan pengecualian kolom dari UPDATE atau INSERT tindakan. Kolom yang dikecualikan diatur ke null.

Dengan evolusi skema diaktifkan, EXCEPT kata kunci berlaku untuk daftar kolom dalam tabel sumber dan memungkinkan pengecualian kolom dari evolusi skema. Kolom baru di sumber yang tidak ada di target tidak ditambahkan ke skema target jika tercantum dalam EXCEPT klausa. Kolom yang dikecualikan yang sudah ada di target diatur ke null.

Contoh berikut menunjukkan sintaks ini:

Kolom Kueri (dalam SQL) Perilaku tanpa evolusi skema (default) Perilaku dengan evolusi skema
Kolom target: id, title, last_updated

Kolom sumber: 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)
Baris yang cocok diperbarui dengan mengatur last_updated bidang ke tanggal saat ini. Baris baru disisipkan menggunakan nilai untuk id dan title. Bidang yang dikecualikan last_updated diatur ke null. Bidang review diabaikan karena tidak ada di target. Baris yang cocok diperbarui dengan mengatur last_updated bidang ke tanggal saat ini. Skema berevolusi untuk menambahkan bidang review. Baris baru disisipkan menggunakan semua bidang sumber kecuali last_updated yang diatur ke null.
Kolom target: id, title, last_updated

Kolom sumber: 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 menampilkan kesalahan karena kolom internal_count tidak ada di tabel target. Baris yang cocok diperbarui dengan mengatur last_updated bidang ke tanggal saat ini. Bidang review ditambahkan ke tabel target, tetapi internal_count bidang diabaikan. Baris baru yang disisipkan telah last_updated diatur ke null.

Evolusi skema otomatis untuk array struktur

Delta MERGE INTO mendukung penyelesaian bidang struktur berdasarkan skema nama dan skema yang berevolusi untuk array struktur. Dengan aktifnya evolusi skema, skema tabel target akan berevolusi untuk array struktur, yang juga dapat berfungsi dengan setiap struktur berlapis di dalam array.

Catatan

Di Databricks Runtime 12.2 LTS ke atas, bidang struct yang ada di tabel sumber dapat ditentukan berdasarkan nama dalam perintah sisipkan atau perbarui. Dalam Databricks Runtime 11.3 LTS dan di bawahnya, hanya INSERT * atau UPDATE SET * perintah yang dapat digunakan untuk evolusi skema dengan penggabungan.

Berikut adalah beberapa contoh efek operasi gabung dengan dan tanpa evolusi skema untuk array struktur.

Skema sumber Skema target Perilaku tanpa evolusi skema (default) Perilaku dengan evolusi skema
array<struct<b: string, a: string>> array<struct<a: int, b: int>> Skema tabel tidak berubah. Kolom akan diselesaikan berdasarkan nama dan diperbarui atau disisipkan. Skema tabel tidak berubah. Kolom akan diselesaikan berdasarkan nama dan diperbarui atau disisipkan.
array<struct<a: int, c: string, d: string>> array<struct<a: string, b: string>> update dan insert menampilkan kesalahan karena c dan d tidak ada di tabel target. Skema tabel diubah menjadi array<struct<a: string, b: string, c: string, d: string>>. c dan d dimasukkan sebagai NULL untuk entri yang sudah ada dalam tabel target. update dan insert mengisi entri dalam tabel sumber dengan a yang ditransimisikan ke string dan b sebagai NULL.
array<struct<a: string, b: struct<c: string, d: string>>> array<struct<a: string, b: struct<c: string>>> update dan insert menampilkan kesalahan karena d tidak ada di tabel target. Skema tabel diubah menjadi array<struct<a: string, b: struct<c: string, d: string>>>. d dimasukkan sebagai NULL untuk entri yang sudah ada dalam tabel target.

NullType Menangani kolom dalam pembaruan skema

Karena Parquet tidak mendukung NullType, NullType kolom dijatuhkan dari DataFrame saat menulis ke tabel Delta, tetapi masih disimpan dalam skema. Ketika tipe data yang berbeda diterima untuk kolom itu, Delta Lake menggabungkan skema ke tipe data baru. Jika Delta Lake menerima NullType untuk kolom yang ada, skema lama dipertahankan dan kolom baru dijatuhkan selama penulisan.

NullType dalam streaming tidak didukung. Karena Anda harus mengatur skema saat menggunakan streaming, ini seharusnya sangat jarang. NullType juga tidak diterima untuk jenis yang kompleks seperti ArrayType dan MapType.

Mengganti skema tabel

Secara default, menimpa data dalam tabel tidak menimpa skema. Saat menimpa tabel menggunakan mode("overwrite") tanpa replaceWhere, Anda mungkin masih ingin menimpa skema data yang sedang ditulis. Anda mengganti skema dan partisi tabel dengan mengatur opsi overwriteSchema ke true:

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

Penting

Anda tidak dapat menentukan overwriteSchema kapan true menggunakan timpa partisi dinamis.