تحديث مخطط جدول Delta Lake

يتيح لك Delta Lake تحديث مخطط جدول. يتم دعم الأنواع التالية من التغييرات:

  • إضافة أعمدة جديدة (في مواضع عشوائية)
  • إعادة ترتيب الأعمدة الموجودة
  • إعادة تسمية الأعمدة الموجودة

يمكنك إجراء هذه التغييرات بشكل صريح باستخدام DDL أو ضمنيا باستخدام DML.

هام

تحديث مخطط جدول Delta هو عملية تتعارض مع جميع عمليات كتابة دلتا المتزامنة.

عند تحديث مخطط جدول Delta، يتم إنهاء عمليات الدفق التي تقرأ من هذا الجدول. إذا كنت تريد أن يستمر الدفق، فيجب إعادة تشغيله. للحصول على الأساليب الموصى بها، راجع اعتبارات الإنتاج للبث المنظم.

تحديث المخطط بشكل صريح لإضافة أعمدة

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

بشكل افتراضي، قابلية القيم الخالية هي true.

لإضافة عمود إلى حقل متداخل، استخدم:

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

على سبيل المثال، إذا كان المخطط قبل التشغيل ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1) هو:

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

المخطط بعد هو:

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

إشعار

إضافة أعمدة متداخلة معتمدة فقط للبنى. الصفائف والخرائط غير معتمدة.

تحديث المخطط بشكل صريح لتغيير تعليق العمود أو ترتيبه

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

لتغيير عمود في حقل متداخل، استخدم:

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

على سبيل المثال، إذا كان المخطط قبل التشغيل ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST هو:

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

المخطط بعد هو:

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

تحديث المخطط بشكل صريح لاستبدال الأعمدة

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

على سبيل المثال، عند تشغيل DDL التالي:

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

إذا كان المخطط من قبل هو:

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

المخطط بعد هو:

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

تحديث المخطط بشكل صريح لإعادة تسمية الأعمدة

إشعار

تتوفر هذه الميزة في Databricks Runtime 10.4 LTS وما فوق.

لإعادة تسمية الأعمدة دون إعادة كتابة أي من البيانات الموجودة في الأعمدة، يجب تمكين تعيين العمود للجدول. راجع إعادة تسمية الأعمدة وإفلاتها باستخدام تعيين عمود Delta Lake.

لإعادة تسمية عمود:

ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name

لإعادة تسمية حقل متداخل:

ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field

على سبيل المثال، عند تشغيل الأمر التالي:

ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001

إذا كان المخطط من قبل هو:

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

ثم المخطط بعد هو:

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

راجع إعادة تسمية الأعمدة وإفلاتها باستخدام تعيين عمود Delta Lake.

تحديث المخطط بشكل صريح لإسقاط الأعمدة

إشعار

تتوفر هذه الميزة في Databricks Runtime 11.3 LTS وما فوق.

لإسقاط الأعمدة كلعملية بيانات تعريف فقط دون إعادة كتابة أي ملفات بيانات، يجب تمكين تعيين العمود للجدول. راجع إعادة تسمية الأعمدة وإفلاتها باستخدام تعيين عمود Delta Lake.

هام

لا يؤدي إسقاط عمود من بيانات التعريف إلى حذف البيانات الأساسية للعمود في الملفات. لإزالة بيانات العمود الذي تم إسقاطه، يمكنك استخدام REORG TABLE لإعادة كتابة الملفات. يمكنك بعد ذلك استخدام فراغ لحذف الملفات التي تحتوي على بيانات العمود التي تم إسقاطها فعليا.

لإسقاط عمود:

ALTER TABLE table_name DROP COLUMN col_name

لإفلات أعمدة متعددة:

ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)

تحديث المخطط بشكل صريح لتغيير نوع العمود أو الاسم

يمكنك تغيير نوع العمود أو اسمه أو إسقاط عمود عن طريق إعادة كتابة الجدول. للقيام بذلك، استخدم overwriteSchema الخيار .

يوضح المثال التالي تغيير نوع عمود:

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

يوضح المثال التالي تغيير اسم عمود:

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

تمكين تطور المخطط

يمكنك تمكين تطور المخطط عن طريق القيام بأحد الإجراءات التالية:

توصي Databricks بتمكين تطور المخطط لكل عملية كتابة بدلا من تعيين تكوين Spark.

عند استخدام الخيارات أو بناء الجملة لتمكين تطور المخطط في عملية الكتابة، يكون لهذا الأسبقية على تكوين Spark.

إشعار

لا توجد عبارة تطور مخطط للبيانات INSERT INTO .

تمكين تطور المخطط للكتابات لإضافة أعمدة جديدة

تتم إضافة الأعمدة الموجودة في الاستعلام المصدر ولكنها مفقودة من الجدول الهدف تلقائيا كجزء من معاملة الكتابة عند تمكين تطور المخطط. راجع تمكين تطور المخطط.

يتم الاحتفاظ بالحالة عند إلحاق عمود جديد. تتم إضافة أعمدة جديدة إلى نهاية مخطط الجدول. إذا كانت الأعمدة الإضافية في بنية، يتم إلحاقها بنهاية البنية في الجدول الهدف.

يوضح المثال التالي استخدام الخيار مع mergeSchema Auto Loader. راجع ما هو المحمل التلقائي؟.

(spark.readStream
  .format("cloudFiles")
  .option("cloudFiles.format", "json")
  .option("cloudFiles.schemaLocation", "<path-to-schema-location>")
  .load("<path-to-source-data>")
  .writeStream
  .option("mergeSchema", "true")
  .option("checkpointLocation", "<path-to-checkpoint>")
  .trigger(availableNow=True)
  .toTable("table_name")
)

يوضح المثال التالي استخدام mergeSchema الخيار مع عملية كتابة الدفعة:

(spark.read
  .table(source_table)
  .write
  .option("mergeSchema", "true")
  .mode("append")
  .saveAsTable("table_name")
)

تطور المخطط التلقائي لدمج Delta Lake

يسمح تطور المخطط للمستخدمين بحل عدم تطابق المخطط بين الجدول الهدف والجدول المصدر في الدمج. وهو يعالج الحالتين التاليتين:

  1. عمود في الجدول المصدر غير موجود في الجدول الهدف. تتم إضافة العمود الجديد إلى المخطط الهدف، ويتم إدراج قيمه أو تحديثها باستخدام قيم المصدر.
  2. عمود في الجدول الهدف غير موجود في الجدول المصدر. لم يطرأ أي تغيير على المخطط الهدف؛ يتم إما ترك القيم في العمود الهدف الإضافي دون تغيير (ل UPDATE) أو تعيينها إلى NULLINSERT).

يجب تمكين تطور المخطط التلقائي يدويا. راجع تمكين تطور المخطط.

إشعار

في Databricks Runtime 12.2 LTS وما فوق، يمكن تحديد الأعمدة وحقول البنية الموجودة في الجدول المصدر بالاسم في إجراءات الإدراج أو التحديث. في Databricks Runtime 11.3 LTS والإصدارات أدناه، يمكن استخدام الإجراءات أو UPDATE SET * فقط INSERT * لتطور المخطط مع الدمج.

في Databricks Runtime 13.3 LTS وما فوق، يمكنك استخدام تطور المخطط مع البنيات المتداخلة داخل الخرائط، مثل map<int, struct<a: int, b: int>>.

بناء جملة تطور المخطط للدمج

في Databricks Runtime 15.2 وما فوق، يمكنك تحديد تطور المخطط في عبارة دمج باستخدام واجهات برمجة تطبيقات جدول SQL أو Delta:

SQL

MERGE WITH SCHEMA EVOLUTION INTO target
USING source
ON source.key = target.key
WHEN MATCHED THEN
  UPDATE SET *
WHEN NOT MATCHED THEN
  INSERT *
WHEN NOT MATCHED BY SOURCE THEN
  DELETE

Python

from delta.tables import *

(targetTable
  .merge(sourceDF, "source.key = target.key")
  .withSchemaEvolution()
  .whenMatchedUpdateAll()
  .whenNotMatchedInsertAll()
  .whenNotMatchedBySourceDelete()
  .execute()
)

Scala

import io.delta.tables._

targetTable
  .merge(sourceDF, "source.key = target.key")
  .withSchemaEvolution()
  .whenMatched()
  .updateAll()
  .whenNotMatched()
  .insertAll()
  .whenNotMatchedBySource()
  .delete()
  .execute()

مثال على عمليات الدمج مع تطور المخطط

فيما يلي بعض الأمثلة على تأثيرات merge التشغيل مع تطور المخطط وبدونه.

الأعمدة الاستعلام (في SQL) السلوك دون تطور المخطط (افتراضي) السلوك مع تطور المخطط
الأعمدة الهدف: key, value

أعمدة المصدر: 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 *
يظل مخطط الجدول دون تغيير؛ يتم تحديث/إدراج الأعمدة keyvalue فقط. يتم تغيير مخطط الجدول إلى (key, value, new_value). يتم تحديث السجلات الموجودة ذات التطابقات مع value و new_value في المصدر. يتم إدراج صفوف جديدة مع المخطط (key, value, new_value).
الأعمدة الهدف: key, old_value

أعمدة المصدر: 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 *
UPDATE وتطرح INSERT الإجراءات خطأ لأن العمود old_value الهدف ليس في المصدر. يتم تغيير مخطط الجدول إلى (key, old_value, new_value). يتم تحديث السجلات الموجودة ذات التطابقات مع new_value ترك في المصدر old_value دون تغيير. يتم إدراج سجلات جديدة مع keyالمحدد و new_valueو NULL ل old_value.
الأعمدة الهدف: key, old_value

أعمدة المصدر: 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 يطرح خطأ لأن العمود new_value غير موجود في الجدول الهدف. يتم تغيير مخطط الجدول إلى (key, old_value, new_value). يتم تحديث السجلات الموجودة ذات التطابقات مع new_value ترك في المصدر old_value دون تغيير، وقد NULL تم إدخال السجلات غير المتطابقة ل new_value. راجع الملاحظة (1).
الأعمدة الهدف: key, old_value

أعمدة المصدر: 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 يطرح خطأ لأن العمود new_value غير موجود في الجدول الهدف. يتم تغيير مخطط الجدول إلى (key, old_value, new_value). يتم إدراج سجلات جديدة مع keyالمحدد و new_valueو NULL ل old_value. تم NULL إدخال السجلات الموجودة لتركها old_value new_value دون تغيير. راجع الملاحظة (1).

(1) يتوفر هذا السلوك في Databricks Runtime 12.2 LTS وما فوق؛ Databricks Runtime 11.3 LTS وتحت الخطأ في هذا الشرط.

استبعاد الأعمدة باستخدام دمج Delta Lake

في Databricks Runtime 12.2 LTS وما فوق، يمكنك استخدام EXCEPT العبارات في شروط الدمج لاستبعاد الأعمدة بشكل صريح. يختلف سلوك EXCEPT الكلمة الأساسية اعتمادا على ما إذا كان قد تم تمكين تطور المخطط أم لا.

مع تعطيل تطور المخطط، EXCEPT تنطبق الكلمة الأساسية على قائمة الأعمدة في الجدول الهدف وتسمح باستبعاد الأعمدة من UPDATE أو INSERT الإجراءات. يتم تعيين الأعمدة المستبعدة إلى null.

مع تمكين تطور المخطط، EXCEPT تنطبق الكلمة الأساسية على قائمة الأعمدة في الجدول المصدر وتسمح باستبعاد الأعمدة من تطور المخطط. لا تتم إضافة عمود جديد في المصدر غير موجود في الهدف إلى المخطط الهدف إذا كان مدرجا في العبارة EXCEPT . يتم تعيين الأعمدة المستبعدة الموجودة بالفعل في الهدف إلى null.

توضح الأمثلة التالية بناء الجملة هذا:

الأعمدة الاستعلام (في SQL) السلوك دون تطور المخطط (افتراضي) السلوك مع تطور المخطط
الأعمدة الهدف: id, title, last_updated

أعمدة المصدر: 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)
يتم تحديث الصفوف المتطابقة عن طريق تعيين last_updated الحقل إلى التاريخ الحالي. يتم إدراج صفوف جديدة باستخدام قيم و id title. يتم تعيين الحقل last_updated المستبعد إلى null. يتم تجاهل الحقل review لأنه ليس في الهدف. يتم تحديث الصفوف المتطابقة عن طريق تعيين last_updated الحقل إلى التاريخ الحالي. تم تطوير المخطط لإضافة الحقل review. يتم إدراج صفوف جديدة باستخدام كافة الحقول المصدر باستثناء last_updated التي تم تعيينها إلى null.
الأعمدة الهدف: id, title, last_updated

أعمدة المصدر: 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 يطرح خطأ لأن العمود internal_count غير موجود في الجدول الهدف. يتم تحديث الصفوف المتطابقة عن طريق تعيين last_updated الحقل إلى التاريخ الحالي. review تتم إضافة الحقل إلى الجدول الهدف، ولكن internal_count يتم تجاهل الحقل. تم last_updated تعيين الصفوف الجديدة المدرجة إلى null.

التعامل مع NullType الأعمدة في تحديثات المخطط

نظرا لأن Parquet لا يدعم NullType، NullType يتم إسقاط الأعمدة من DataFrame عند الكتابة في جداول Delta، ولكن لا تزال مخزنة في المخطط. عند تلقي نوع بيانات مختلف لهذا العمود، يدمج Delta Lake المخطط بنوع البيانات الجديد. إذا تلقى NullType Delta Lake لعمود موجود، يتم الاحتفاظ بالمخطط القديم ويتم إسقاط العمود الجديد أثناء الكتابة.

NullType في البث غير مدعوم. نظرا لأنه يجب عليك تعيين المخططات عند استخدام دفق هذا يجب أن يكون نادرا جدا. NullType غير مقبول أيضا لأنواع معقدة مثل ArrayType و MapType.

استبدال مخطط الجدول

بشكل افتراضي، لا يؤدي الكتابة فوق البيانات في جدول إلى الكتابة فوق المخطط. عند الكتابة فوق جدول باستخدام mode("overwrite") بدون replaceWhere، قد لا تزال ترغب في الكتابة فوق مخطط البيانات التي تتم كتابتها. يمكنك استبدال مخطط الجدول وتقسيمه عن طريق تعيين overwriteSchema الخيار إلى true:

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

هام

لا يمكنك تحديد overwriteSchema عند true استخدام الكتابة فوق القسم الديناميكي.