تحديث مخطط جدول 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(...)
)
تمكين تطور المخطط
يمكنك تمكين تطور المخطط عن طريق القيام بأحد الإجراءات التالية:
.option("mergeSchema", "true")
قم بتعيين إلى Spark DataFramewrite
أوwriteStream
العملية. راجع تمكين تطور المخطط للكتابات لإضافة أعمدة جديدة.- استخدم
MERGE WITH SCHEMA EVOLUTION
بناء الجملة. راجع بناء جملة تطور المخطط للدمج. - تعيين تكوين
spark.databricks.delta.schema.autoMerge.enabled
Spark إلىtrue
ل SparkSession الحالي.
توصي 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
يسمح تطور المخطط للمستخدمين بحل عدم تطابق المخطط بين الجدول الهدف والجدول المصدر في الدمج. وهو يعالج الحالتين التاليتين:
- عمود في الجدول المصدر غير موجود في الجدول الهدف. تتم إضافة العمود الجديد إلى المخطط الهدف، ويتم إدراج قيمه أو تحديثها باستخدام قيم المصدر.
- عمود في الجدول الهدف غير موجود في الجدول المصدر. لم يطرأ أي تغيير على المخطط الهدف؛ يتم إما ترك القيم في العمود الهدف الإضافي دون تغيير (ل
UPDATE
) أو تعيينها إلىNULL
(لINSERT
).
يجب تمكين تطور المخطط التلقائي يدويا. راجع تمكين تطور المخطط.
إشعار
في 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 * |
يظل مخطط الجدول دون تغيير؛ يتم تحديث/إدراج الأعمدة key value فقط. |
يتم تغيير مخطط الجدول إلى (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
استخدام الكتابة فوق القسم الديناميكي.