Skip to main content
التحديث خفيف الوزن لا يزال حاليًا في المرحلة التجريبية. إذا واجهت أي مشكلات، يُرجى فتح issue في مستودع ClickHouse.
تعمل عبارة UPDATE خفيفة الوزن على تحديث الصفوف في الجدول [db.]table التي تطابق التعبير filter_expr. وسُمّيت “lightweight update” لتمييزها عن استعلام ALTER TABLE ... UPDATE، وهي عملية ثقيلة تعيد كتابة أعمدة كاملة في أجزاء البيانات. وهي متاحة فقط لعائلة محركات الجداول MergeTree.
يجب أن يكون filter_expr من النوع UInt8. يحدّث هذا الاستعلام قيم الأعمدة المحددة إلى قيم التعبيرات المقابلة في الصفوف التي تكون فيها قيمة filter_expr غير صفرية. تُحوَّل القيم إلى نوع العمود باستخدام العامل CAST. لا يُدعم تحديث الأعمدة المستخدمة في حساب المفتاح الأساسي أو مفتاح التقسيم. تَقصُر عبارة IN PARTITION التحديثَ على التقسيمات المُدرجة. وبدونها، في جداول عائلة ReplicatedMergeTree، وعندما يكون الإعداد optimize_mutations_with_partition_pruning مُفعَّلًا (وهو الوضع الافتراضي)، يكتشف ClickHouse تلقائيًا شروط مفتاح التقسيم في filter_expr ويحدّث التقسيمات المتأثرة فقط. أما في جداول MergeTree غير المنسوخة، فاستخدم عبارة IN PARTITION صريحة لقصر التحديث على تقسيمات محددة.

أمثلة

التحديثات خفيفة الوزن تظهر فورًا في الاستعلامات

يجعل UPDATE خفيف الوزن القيم المحدَّثة مرئية فورًا في استعلامات SELECT من خلال تطبيق أجزاء التصحيح (patch parts). فلا تحتاج الاستعلامات إلى انتظار عملية دمج (merge) لقراءة القيم المحدَّثة. وأجزاء التصحيح هي نوع خاص من أجزاء البيانات (data parts) يحتوي على الأعمدة والصفوف المحدَّثة فقط، وإنشاؤها لا يعدّل البيانات الأصلية فيزيائيًا في التخزين على الفور. وتشبه عملية التحديث استعلام INSERT ... SELECT ...، حيث ينتظر استعلام UPDATE حتى يكتمل إنشاء جزء التصحيح قبل أن يعود. الظهور في الاستعلامات والتجسيد المادي أمران منفصلان:
  • الظهور في الاستعلامات: تطبّق استعلامات SELECT التصحيحات لقراءة القيم المحدَّثة قبل أن تُجسَّد تلك التصحيحات داخل أجزاء البيانات الأصلية.
  • التجسيد المادي: تدمج عمليات الدمج والتعديلات (merges and mutations) اللاحقة القيم المحدَّثة في أجزاء البيانات.
  • التنظيف: تُزال أجزاء التصحيح تلقائيًا بمجرد أن تُجسَّد التصحيحات في جميع الأجزاء النشطة (active parts).
وللاطلاع على اتساق التحديثات المتزامنة، راجع العمليات المتزامنة.

متطلبات التحديثات خفيفة الوزن

تدعم التحديثات خفيفة الوزن محركات MergeTree وReplacingMergeTree وCollapsingMergeTree وVersionedCollapsingMergeTree، بالإضافة إلى إصداراتها Replicated وShared. لاستخدام التحديثات خفيفة الوزن، يجب تمكين التجسيد المادي على العمودين _block_number و_block_offset باستخدام إعدادات الجدول enable_block_number_column وenable_block_offset_column.

عمليات الحذف الخفيفة

يمكن تنفيذ استعلام DELETE خفيف الوزن باعتباره UPDATE خفيفًا بدلًا من عملية mutation من نوع ALTER UPDATE. ويُتحكَّم في آلية تنفيذ DELETE خفيف الوزن من خلال الإعداد lightweight_delete_mode.

اعتبارات الأداء

مزايا التحديثات خفيفة الوزن:
  • زمن استجابة التحديث مماثل لزمن استجابة استعلام INSERT ... SELECT ...
  • لا تُكتب سوى الأعمدة والقيم المُحدَّثة، وليس الأعمدة كاملةً في أجزاء البيانات
  • لا حاجة إلى انتظار اكتمال عمليات الدمج/التعديلات الجارية حاليًا، لذلك يكون زمن استجابة التحديث متوقعًا
  • يمكن تنفيذ التحديثات خفيفة الوزن بالتوازي
التأثيرات المحتملة على الأداء:
  • تضيف عبئًا إضافيًا على استعلامات SELECT التي تحتاج إلى تطبيق التصحيحات
  • لن تُستخدم فهارس التخطي للأعمدة في أجزاء البيانات التي توجد عليها تصحيحات يجب تطبيقها. ولن تُستخدم الإسقاطات إذا كانت هناك أجزاء التصحيح في الجدول، بما في ذلك أجزاء البيانات التي لا توجد عليها تصحيحات يجب تطبيقها.
  • قد تؤدي التحديثات الصغيرة المتكررة جدًا إلى ظهور الخطأ “too many parts”. ويُنصح بتجميع عدة تحديثات في استعلام واحد، على سبيل المثال بوضع معرّفات التحديثات في عبارة IN واحدة داخل عبارة WHERE
  • صُممت التحديثات خفيفة الوزن لتحديث عدد صغير من الصفوف (حتى نحو 10% من الجدول). وإذا كنت بحاجة إلى تحديث كمية أكبر، فيُنصح باستخدام ALTER TABLE ... UPDATE mutation

العمليات المتزامنة

لا تنتظر التحديثات خفيفة الوزن اكتمال عمليات الدمج/التعديلات الجارية حاليًا، بخلاف التعديلات الثقيلة. ويُتحكَّم في اتساق التحديثات خفيفة الوزن المتزامنة من خلال الإعدادات update_sequential_consistency وupdate_parallel_mode.

أذونات UPDATE

يتطلب UPDATE امتياز ALTER UPDATE. لتمكين عبارات UPDATE على جدول محدد لمستخدم معيّن، شغّل:

تفاصيل التنفيذ

أجزاء التصحيح هي نفسها الأجزاء العادية، لكنها لا تحتوي إلا على الأعمدة المحدَّثة وعدة أعمدة خاصة بالنظام:
  • _part - اسم الجزء الأصلي
  • _part_offset - رقم الصف في الجزء الأصلي
  • _block_number - رقم block الخاص بالصف في الجزء الأصلي
  • _block_offset - إزاحة block الخاصة بالصف في الجزء الأصلي
  • _data_version - إصدار بيانات البيانات المحدَّثة (رقم block المخصَّص لاستعلام UPDATE)
في المتوسط، يضيف ذلك نحو 40 بايتًا (بيانات غير مضغوطة) من العبء الإضافي لكل صف محدَّث في أجزاء التصحيح. وتساعد أعمدة النظام في العثور على الصفوف في الجزء الأصلي التي يجب تحديثها. وترتبط أعمدة النظام بـ الأعمدة الافتراضية في الجزء الأصلي، والتي تُضاف عند القراءة إذا كان يلزم تطبيق أجزاء التصحيح. وتُرتَّب أجزاء التصحيح حسب _part و _part_offset. تنتمي أجزاء التصحيح إلى تقسيمات مختلفة عن الجزء الأصلي. ويكون معرّف التقسيم لجزء التصحيح هو patch-<hash of column names in patch part>-<original_partition_id>. لذلك تُخزَّن أجزاء التصحيح ذات الأعمدة المختلفة في تقسيمات مختلفة. فعلى سبيل المثال، ستنشئ ثلاثة تحديثات SET x = 1 WHERE <cond> و SET y = 1 WHERE <cond> و SET x = 1, y = 1 WHERE <cond> ثلاثة أجزاء تصحيح في ثلاثة تقسيمات مختلفة. يمكن دمج أجزاء التصحيح فيما بينها لتقليل عدد التصحيحات المطبَّقة على استعلامات SELECT وتقليل العبء الإضافي. ويستخدم دمج أجزاء التصحيح خوارزمية الدمج الاستبدالية مع _data_version بوصفه version column. لذلك تحتفظ أجزاء التصحيح دائمًا بأحدث إصدار لكل صف محدَّث في الجزء. لا تنتظر تحديثات خفيفة الوزن انتهاء عمليات الدمج وعمليات التعديل الجارية حاليًا، بل تستخدم دائمًا snapshot الحالية من data parts لتنفيذ تحديث وإنتاج جزء تصحيح. وبسبب ذلك، يمكن أن توجد حالتان عند تطبيق أجزاء التصحيح. فعلى سبيل المثال، إذا قرأنا الجزء A، فسنحتاج إلى تطبيق جزء التصحيح X:
  • إذا كان X يحتوي على الجزء A نفسه. ويحدث هذا إذا لم يكن A مشاركًا في عملية دمج عند تنفيذ UPDATE.
  • إذا كان X يحتوي على الجزأين B و C، اللذين يغطيهما الجزء A. ويحدث هذا إذا كانت هناك عملية دمج (B, C) -> A قيد التشغيل عند تنفيذ UPDATE.
ولهاتين الحالتين، توجد طريقتان لتطبيق أجزاء التصحيح، على الترتيب:
  • استخدام merge على الأعمدة المرتَّبة _part و _part_offset.
  • استخدام join على العمودين _block_number و _block_offset.
ويكون وضع join أبطأ ويتطلب ذاكرة أكبر من وضع merge، لكنه يُستخدم بوتيرة أقل.

محتوى ذي صلة

آخر تعديل في ٢٦ سبتمبر ٢٠٢٦