Skip to main content
تتيح الدوال المعرّفة من قبل المستخدم (UDF) للمستخدمين توسيع إمكانات ClickHouse بما يتجاوز ما توفره أكثر من ألف دالة جاهزة. في ClickHouse Cloud، توجد عدة طرق لإنشاء الدوال المعرّفة من قبل المستخدم وإدارتها:
  1. باستخدام SQL
  2. باستخدام وحدة التحكم والشيفرة الخاصة بك
  3. باستخدام Cloud واجهة برمجة تطبيقات (تجريبي)
  4. باستخدام Terraform (تجريبي)
تتوفر Executable UDFs على AWS وGCP وAzure، وهي مفعّلة تلقائيًا لكل مؤسسة دون الحاجة إلى أي إعداد إضافي. كما أنها لا تُحتسب تكلفتها بشكل منفصل، إذ تعمل عمليات UDF داخل وحدات pod الخاصة بالخدمة، وتستهلك موارد CPU والذاكرة المخصصة للخدمة نفسها.

الدوال المعرّفة من قبل المستخدم في SQL

يمكن إنشاء UDFs في SQL باستخدام عبارة CREATE FUNCTION انطلاقًا من تعبير lambda. في هذا المثال، سننشئ دالة معرّفة من قبل المستخدم قابلة للتنفيذ وبسيطة باسم isBusinessHours. ستتحقق الدالة مما إذا كان طابع زمني معيّن يقع ضمن ساعات العمل المعتادة، وستُرجع true إذا كان كذلك، وإلا false.
  1. سجّل الدخول إلى Cloud Console وافتح SQL Console
  2. اكتب استعلام SQL التالي لإنشاء الدالة isBusinessHours:
  1. نفّذ ما يلي لاختبار UDF الذي أنشأته للتو:
من المفترض أن تظهر لك النتيجة التالية:
  1. يمكنك استخدام الأمر DROP FUNCTION لإزالة دالة UDF التي أنشأتها للتو:
مهمإن UDFs في ClickHouse Cloud لا ترث الإعدادات على مستوى المستخدم. وتُنفَّذ باستخدام إعدادات النظام الافتراضية.
هذا يعني:
  • لا تنتقل الإعدادات على مستوى الجلسة (المعيَّنة عبر عبارة SET) إلى سياق تنفيذ UDF
  • لا ترث UDFs إعدادات ملف تعريف المستخدم
  • لا تنطبق الإعدادات على مستوى الاستعلام ضمن تنفيذ UDF

الدوال المُعرَّفة من قبل المستخدم القابلة للتنفيذ

تُشغِّل Executable UDFs الشيفرة الخاصة بك في عملية معزولة إلى جانب كل نسخة متماثلة من خدمتك. يمكنك تحميل برنامج نصي بلغة بايثون يعمل على بيئة التشغيل python3.11، أو ملف ثنائي مُصرَّف مسبقًا يعمل على بيئة التشغيل Native. في هذا المثال، سننشئ الدالة البسيطة نفسها المُعرَّفة من قبل المستخدم والقابلة للتنفيذ isBusinessHours، والتي تتحقق مما إذا كان timestamp معيّن يقع ضمن ساعات العمل المعتادة. سبق أن أنشأناها باستخدام SQL، ولكن هذه المرة سننشئها باستخدام بايثون ونُعدّها عبر وحدة التحكم.
1

أنشئ ملف بايثون

أنشئ ملفًا جديدًا باسم main.py على جهازك المحلي:
بيئة تشغيل بايثون هي python3.11. إذا كان البرنامج النصي المكتوب بلغة بايثون يستورد حزمًا من جهات خارجية، فأدرجها في ملف requirements.txt وسيتولى ClickHouse Cloud تثبيتها نيابةً عنك على كلتا معماريتي CPU اللتين يعمل عليهما ClickHouse Cloud ‏(x86-64 وARM64). ويمكنك بدلًا من ذلك تضمين التبعيات مباشرةً في ملف ZIP، لكن عليك حينئذٍ تضمين الحزم المخزنة مؤقتًا لكلتا المعماريتين، ولذلك يُعدّ استخدام requirements.txt الخيار الأبسط. على سبيل المثال:
يتوقع ClickHouse Cloud وجود الملف main.py داخل ملف zip الذي ستُحمّله عبر وحدة التحكم في الخطوة التالية. إذا سمّيت الملف باسم آخر، فستواجه error.
2

اجمع التبعيات والملفات المحلية في حزمة

في هذا الدليل العملي، الذي لا يتضمن أي تبعيات أو ملفات إضافية، يكفي أن يحتوي الأرشيف على main.py فقط:
لتضمين حزم التبعيات وأي ملفات محلية إضافية (مثل requirements.txt أو ملفات wheel أو ملفات التهيئة أو ملفات البيانات)، ضعها في الدليل نفسه الذي يحتوي على main.py، ثم شغّل الأمر zip من داخل هذا الدليل ليكون main.py في جذر الأرشيف:
يمكنك الإشارة إلى الدليل الأساسي للمسار المحلي المضمَّن في شيفرة بايثون باستخدام os.path.dirname(os.path.abspath(__file__)). يُعيد ذلك المسار المطلق للدليل الذي يوجد فيه ملف main.py داخل أرشيف ZIP، مما يتيح لك الوصول إلى الملفات الأخرى المضمَّنة:
يفيد ذلك عندما تحتاج إلى:
  • الوصول إلى ملفات التهيئة المضمّنة مع UDF الخاصة بك
  • تحميل حزم wheel للتبعيات المخصصة
  • الرجوع إلى نصوص برمجية أو ملفات بيانات إضافية
لا يُسمح بالروابط الرمزيةيرفض ClickHouse Cloud أرشيفات UDF التي تحتوي على روابط رمزية. تأكد من أن حزمة ZIP لا تحتوي إلا على ملفات وأدلة عادية، إذ ستفشل عمليات التحميل التي تتضمن روابط رمزية في اجتياز التحقق.
3

أنشئ دالة UDF عبر وحدة التحكم

  1. من الصفحة الرئيسية لوحدة تحكم ClickHouse Cloud، انقر على اسم مؤسستك في القائمة الموجودة أسفل يسار الشاشة.
  2. اختر User-defined functions من القائمة.
  3. في صفحة الدوال المعرّفة من قبل المستخدم، انقر على Set up a UDF. ستُفتح لوحة التهيئة على الجانب الأيمن من الشاشة.
  4. أدخل اسم الدالة. في هذا المثال، استخدم isBusinessHours.
  5. اختر نوع الدالة، إما Executable pool أو Executable:
    • Executable pool: تُشغَّل مجموعة من العمليات طويلة الأمد مرة واحدة، ثم يُعاد استخدامها عبر الكتل والاستعلامات. يُوصى بهذا الخيار لجميع أعباء العمل تقريبًا.
    • Executable: تُشغَّل عملية جديدة لكل كتلة بيانات تجري معالجتها. لا تستخدم هذا الخيار إلا إذا كان من الضروري ألّا تحتفظ العملية بأي حالة بين الاستدعاءات.
  6. اختر Runtime type. في هذا المثال، أبقِ القيمة python3.11. أو اختر Native لتحميل ملف ثنائي مُصرَّف مسبقًا بدلًا من ذلك؛ راجع بيئة التشغيل Native.
  7. في هذا المثال، استخدم الإعدادات الافتراضية. للاطلاع على القائمة الكاملة لمعلمات التكوين وقيمها الافتراضية في Cloud، راجع مرجع التهيئة.
  8. انقر على Browse File لتحميل ملف .zip الذي أنشأته في بداية هذا الدليل العملي.
  9. أضف وسيطة جديدة. في هذا المثال، أضف الوسيطة timestamp من النوع DateTime.
  10. اختر نوع القيمة المُرجَعة. في هذا المثال، اختر Bool.
  11. انقر على Create UDF. سيظهر مربع حوار يعرض الحالة الحالية للإصدار.
    • في حال وجود أي مشكلات، تتغير الحالة إلى error.
    • وفي غير ذلك، تنتقل الحالة من building إلى provisioning. يجب أن تكون خدمتك نشطة حتى يكتمل التجهيز. إذا كانت خدمتك في وضع الخمول، فانقر على Wake Up Service في لوحة UDF details بجوار اسم الخدمة.
    • عند اكتمال العملية، تتغير الحالة إلى deployed.
4

اختبر دالة UDF الخاصة بك

  1. ارجع إلى الصفحة الرئيسية لـ SQL Console بالنقر على Settings - return to your service view في الزاوية العلوية اليسرى من الصفحة
  2. انقر على SQL Console في القائمة اليسرى
  3. اكتب الاستعلام التالي:
من المفترض أن تظهر لك النتيجة التالية:
5

أنشئ إصدارًا جديدًا

لتغيير شيفرة UDF أو إعداداتها، أنشئ إصدارًا جديدًا، إذ إن الإصدارات غير قابلة للتعديل. تقتصر وظيفة لوحة Edit على تحديد الخدمات التي تُسنَد إليها UDF؛ ولن يؤدي تحميل ملف من خلالها إلى استبدال الشيفرة المنشورة.
  1. من الصفحة الرئيسية لوحدة تحكم ClickHouse Cloud، انقر على اسم مؤسستك في القائمة الموجودة أسفل اليسار.
  2. اختر User-defined functions من القائمة.
  3. انقر على النقاط الثلاث ضمن عمود Actions الخاص بـ UDF المسماة isBusinessHours، ثم انقر على Create new version
  4. حمّل ملف zip يحتوي على الشيفرة المعدّلة أو غيّر الإعدادات، ثم اختر الخدمات التي ستتلقى الإصدار الجديد، وانقر على Create new version
لا يرث الإصدار الجديد ارتباطات الخدمات الخاصة بالإصدار السابق. وتتضمن لوحة الإصدار الجديد أداة لاختيار الخدمات، ما يتيح لك اختبار الإصدار على خدمة واحدة، ثم الترقية إليه أو التراجع عنه في كل خدمة على حدة. ولا يمكن للخدمة أن تحتفظ إلا بإصدار واحد من الدالة في كل مرة.بالنسبة إلى UDF من نوع executable_pool، تظل عمليات المجمّع طويلة الأمد تشغّل الإصدار السابق إلى أن يُعاد تحميل المجمّع. استخدم الإجراء Reload UDF المجاور للخدمة في لوحة UDF، والذي ينفّذ الأمر SYSTEM RELOAD FUNCTION ON CLUSTER default isBusinessHours على تلك الخدمة.لقد أضفت بنجاح أول دالة معرّفة من قبل المستخدم عبر وحدة التحكم، وتحققت من أنها تعمل، وتعرّفت على كيفية إنشاء إصدار جديد منها عند الحاجة.

بيئة التشغيل Native (الملفات التنفيذية المُصرَّفة)

تتيح لك بيئة التشغيل Native تحميل ملف تنفيذي مُصرَّف مسبقًا بدلًا من برنامج نصي بلغة بايثون. اضبط نوع بيئة التشغيل على Native عند إنشاء الـ UDF (runtime: native في واجهة برمجة التطبيقات). لن يُثبَّت لك أي شيء في بيئة العزل، لذا يجب تضمين كل ما يحتاجه الملف التنفيذي أثناء التصريف. اللغات المدعومة حاليًا: Rust وGo وC++، إضافةً إلى JavaScript المُصرَّفة إلى ملف تنفيذي باستخدام Bun. اختُبر Bun على الإصدارين 1.4.0 و1.4.2، وقد لا تعمل الإصدارات الأخرى. يجب أن يحتوي الأرشيف على ملف تنفيذي واحد لكل معمارية CPU، يوضع كلٌّ منها في مجلد مستقل:
المعماريتان كلتاهما مطلوبتان لأن خدمات ClickHouse Cloud تعمل على كلتيهما. يجب أن يكون اسم الملف التنفيذي main تحديدًا، ويُشغَّل دون أي وسيطات؛ لذا مرّر الوضع أو الأمر الفرعي بوصفه وسيطة دالة عادية بدلًا من ذلك. يُوصى بشدة باستخدام ملفات تنفيذية مرتبطة ارتباطًا ساكنًا، فهي لا تعتمد على مكتبات النظام في المضيف، التي قد تختلف نداءات النظام فيها من إصدار خادم إلى آخر، كما أن سياسة نداءات النظام في بيئة العزل مضبوطة لتلائمها. أما الملفات التنفيذية المرتبطة ارتباطًا ديناميكيًا فلا تعمل إلا إذا كانت مرتبطة بمكتبة glibc وحدها، ومبنية على glibc 2.35 أو إصدار أقدم. وتجدر الإشارة إلى أن شيفرة JavaScript المُصرَّفة باستخدام Bun تكون دائمًا مرتبطة ارتباطًا ديناميكيًا.
حدّد مسارات ملفات البيانات نسبةً إلى الملف التنفيذيتُنشر الملفات الموجودة في مجلد المعمارية بجوار الملف التنفيذي، لكن العملية لا تبدأ في ذلك الدليل. لذا حدّد مساراتها نسبةً إلى مسار الملف التنفيذي نفسه، وليس نسبةً إلى دليل العمل مطلقًا: في Go استخدم filepath.Dir(os.Args[0]) أو os.Executable()، وفي Rust استخدم std::env::current_exe(). وإذا كان أحد الملفات المطلوبة مفقودًا، فاكتب رسالة إلى stderr واخرج برمز خروج غير صفري بدلًا من اللجوء بصمت إلى سلوك بديل.
لا يمكن تمكين الوصول إلى الشبكة لدوال UDF من نوع Native، إذ يقتصر الوصول الصادر إلى الشبكة على بيئة تشغيل بايثون. راجع الوصول إلى الشبكة. ابنِ الملف التنفيذي لكلتا المعماريتين. في Rust، أضف الهدفين كليهما مرة واحدة، ثم ابنِ كلًّا منهما:
بلغة Go:
انسخ كل ناتج إلى amd64/main وarm64/main قبل ضغط المجلدات. بروتوكول الاتصال مطابق لما هو عليه في بيئة تشغيل بايثون: إذ تقرأ العملية الوسيطات من stdin وتكتب النتائج إلى stdout بالصيغة التي جرت تهيئتها. راجع الصيغ وترويسات المقاطع. يحتوي المستودع llm-token-udf على دوال UDF من نوع Native مكتوبة بلغتي Rust وGo، إلى جانب نصوص برمجية لإنشاء الإصدار.

مرجع التهيئة

تتوفر الإعدادات التالية في وحدة التحكم وفي واجهة برمجة التطبيقات. القيم الافتراضية المذكورة هي القيم الافتراضية في ClickHouse Cloud، وتختلف في بعض الحالات عن القيم الافتراضية في الإصدار مفتوح المصدر. يتولى ClickHouse Cloud إدارة إعدادات الإصدار مفتوح المصدر التالية، ولا يمكن تغييرها لكل UDF على حدة: command_termination_timeout وlifetime وstderr_reaction وcheck_exit_code وexecute_direct. القيمة الافتراضية لـ pool_size في الإصدار مفتوح المصدر هي 16، في حين أنها 3 في Cloud. للاطلاع على القائمة الكاملة للإصدار مفتوح المصدر، راجع الدوال المعرّفة من قبل المستخدم القابلة للتنفيذ. يجب أن تطابق أسماء الدوال النمط ^[A-Za-z][A-Za-z0-9_]*$، وأن تكون فريدة داخل المؤسسة، ولا يجوز أن تكرر اسم دالة مدمجة في ClickHouse؛ إذ ترفض واجهة برمجة التطبيقات الأسماء المحجوزة. ويجب أن يكون لكل وسيطة اسم يتبع النمط نفسه، وتشترط واجهة برمجة التطبيقات وTerraform ذلك في جميع الصيغ. تُرفض الأرشيفات التي تحتوي على روابط رمزية.

الصيغ وترويسات المقاطع

تُعدّ TabSeparated الصيغة الافتراضية والأبسط، وتتطلب إفلات علامات الجدولة وفواصل الأسطر والشرطات المائلة العكسية على كلا الجانبين. أما RowBinary فهي آمنة للبيانات الثنائية وتتجنب تنسيق النصوص وتحليلها على جانب ClickHouse، لذا يُفضَّل استخدامها مع السلاسل النصية الكبيرة. عند تفعيل Send chunk header، يكتب ClickHouse قبل كل مقطع عدد الصفوف نصًا عشريًا متبوعًا بـ \n، ثم الصفوف بالصيغة المُهيَّأة. وينبغي للعملية أن تقرأ هذا العدد من الصفوف بالضبط، وتكتب العدد نفسه من النتائج، ثم تُجري التفريغ مرة واحدة. أما من دون هذا الخيار، فإن العملية التي تقرأ صيغة موجّهة بالصفوف مثل TabSeparated أو RowBinary أو JSONEachRow وتخزّن مخرجاتها مؤقتًا لا تملك أي وسيلة لمعرفة نهاية الكتلة، فيتعلّق الاستعلام حتى انتهاء مهلة القراءة. لذا فعّل هذا الخيار لأي UDF من هذا النوع لا يُجري التفريغ بعد كل صف. أما صيغة Native فتتضمن حدود الكتل أصلًا، ولذلك يمكن لـ UDF يستخدم Native أن يقرأ كتلة واحدة ويكتب كتلة واحدة ثم يُجري التفريغ دون الحاجة إلى الترويسة.

الوصول إلى الشبكة

يقتصر الوصول إلى الشبكة على بيئة تشغيل بايثون؛ إذ لا يمكن تمكينه لدوال UDF من نوع Native. تُبنى دوال Python UDF التي تُنشأ في وحدة التحكم مع تمكين الوصول إلى الشبكة تلقائيًا، ولا يوجد في وحدة التحكم أي إعداد للتحكم في ذلك. أما في واجهة برمجة التطبيقات، فيُتيح الحقل sandboxType الاختيار بين القيمة netenable التي تسمح بالاتصالات الصادرة، والقيمة basic التي لا تسمح بها؛ ويوفر Terraform provider الخيار نفسه عبر sandbox_type. يسمح الوصول إلى الشبكة بالاتصالات الصادرة إلى نقاط النهاية على الإنترنت العام، بينما تُحظر الاتصالات بالشبكات الخاصة وعناوين link-local والعناوين الداخلية. ولا تمتلك بيئة العزل (sandbox) أي هوية سحابية: فلا دور للمثيل، ولا نقطة نهاية للبيانات الوصفية، ولا متغيرات بيئة موروثة؛ لذا لا تملك دالة UDF من بيانات الاعتماد إلا ما تزودها به أنت. ويُطبَّق الوصول إلى الشبكة عند بناء إصدار دالة UDF، ولذلك إذا كان لديك إصدار أُنشئ دون تمكينه، فعليك إنشاء إصدار جديد. لا يتوفر حتى الآن مخزن Secret لدوال UDF. ضمِّن ملف إعدادات داخل ملف zip، واقرأه بمسار نسبي إلى __file__؛ ولا تضع المفاتيح في SQL مطلقًا.

حد الذاكرة

يحدد حد الذاكرة الحد الأقصى للذاكرة المتاحة لكل عملية داخل بيئة العزل (sandbox)، بوحدة MiB. وإذا لم يُعيَّن، تُطبَّق القيمة الافتراضية لبيئة العزل وهي 4 GiB. يسري هذا الحد على مساحة العناوين الافتراضية لا على الذاكرة المقيمة، لذا تحتاج بيئات التشغيل التي تحجز نطاقات عناوين كبيرة إلى هامش إضافي يتجاوز استخدامها الفعلي بفارق كبير. فعلى سبيل المثال، تحجز Go أكثر من 1 GiB بكثير من مساحة العناوين عند بدء التشغيل. وعندما تتجاوز عملية ما هذا الحد، يفشل تخصيص الذاكرة داخلها: إذ تنتهي دالة Python UDF مع تتبّع أخطاء MemoryError، ويفشل الاستعلام وتُضمَّن مخرجات stderr هذه في رسالة الخطأ.

الدوال الحتمية وذاكرة التخزين المؤقت للاستعلامات

تُعامَل أي UDF افتراضيًا على أنها غير حتمية. لذا يفشل الاستعلام الذي يستدعي إحداها مع use_query_cache = 1 بالخطأ QUERY_CACHE_USED_WITH_NONDETERMINISTIC_FUNCTIONS، ما لم يُغيَّر الإعداد query_cache_nondeterministic_function_handling. لا تفعِّل خيار حتمي إلا إذا كانت الدالة تُعيد دائمًا النتيجة نفسها للوسيطات نفسها. عندئذٍ يصبح بإمكان ذاكرة التخزين المؤقت للاستعلامات تخزين نتائج الاستعلامات التي تستدعيها وإعادة تقديمها. غير أن وجود دوال أخرى غير حتمية في الاستعلام نفسه، مثل now أو today أو rand، يظل يمنع التخزين المؤقت في ظل المعالجة الافتراضية throw؛ إذ يؤدي ضبط query_cache_nondeterministic_function_handling = 'save' إلى تخزين هذه الاستعلامات مؤقتًا على أي حال، بينما تؤدي القيمة 'ignore' إلى تنفيذها دون تخزين مؤقت.

عمليات إعادة تشغيل الخدمة

يؤدي الإرفاق الأول إلى إعادة تشغيل الخدمةيؤدي إرفاق أول UDF بخدمة ما إلى إضافة حاوية مساعدة إلى وحدات pod الخاصة بالخدمة وإجراء إعادة تشغيل متدرجة. أما إرفاق دوال UDF أخرى بعد ذلك فلا يستلزم إعادة التشغيل. وتؤدي إزالة آخر UDF من الخدمة إلى إعادة تشغيل متدرجة أخرى. لذا خطّط لتوقيت الإرفاق الأول بما يتناسب مع ذلك.

المراقبة

يسجّل ClickHouse 26.6 والإصدارات الأحدث استخدام الموارد لدوال UDF التنفيذية في ثمانية عدّادات، تبدأ جميعها بالبادئة ExecutableUserDefinedFunction. على مستوى كل استعلام، تظهر هذه العدّادات كعناصر في column ProfileEvents من نوع Map ضمن system.query_log. أما على مستوى الخادم بأكمله، فتظهر كصفوف في system.events بقيم تراكمية منذ بدء تشغيل الخادم، وكأعمدة ProfileEvent_<name> في system.metric_log بقيم مُعايَنة على فترات زمنية. وفيما يلي لواحق العدّادات: يتضمّن system.asynchronous_metrics المقياسين ExecutableUserDefinedFunctionProcesses وExecutableUserDefinedFunctionMemoryResidentBytes. ويمثّل الأخير مجموع VmRSS لعمليات UDF القائمة حاليًا، وهو قيمة حدّ أعلى، لأن الصفحات المشتركة تُحتسب مرة واحدة لكل عملية.
يقتصر system.query_log.memory_usage على قياس عملية خادم ClickHouse، ولا يشمل عمليات UDF.

إرشادات الأداء

استخدم executable_pool؛ إذ يؤدي استخدام executable إلى تشغيل عملية جديدة لكل كتلة من البيانات، فتتكرر تكلفة بدء التشغيل مع كل كتلة. لكل استدعاء تكلفة ثابتة. فإذا كانت قيمة ExecutableUserDefinedFunctionInvocations مرتفعة جدًا مقارنةً بعدد الصفوف المعالَجة، فارفع قيمة preferred_block_size_bytes لذلك الاستعلام كي تحمل كل كتلة عددًا أكبر من الصفوف. لا يستخدم الاستعلام الواحد في الوقت نفسه أكثر من max_threads من عمليات المجمّع، لذا فإن زيادة حجم المجمّع على max_threads لا تعود بأي فائدة على ذلك الاستعلام. ابدأ بحجم صغير، ثم ارفع حجم المجمّع حين تصبح قيمة ExecutableUserDefinedFunctionPoolWaitMicroseconds ملحوظة. يعبر كل صف حدود العملية. لذا فالدوال المعرّفة من قِبل المستخدم (UDFs) مخصّصة للمنطق الذي يتعذّر التعبير عنه بلغة SQL، لا للمعالجة البسيطة لكل صف التي يمكن إنجازها بدالة مدمجة أو بدالة UDF مكتوبة بلغة SQL.

استكشاف الأخطاء وإصلاحها

عند فشل UDF، يفشل الاستعلام ويُعيد رمز الخطأ 754 (UDF_EXECUTION_FAILED). تتضمّن رسالة الخطأ مخرجات stderr الخاصة بالعملية الفرعية، لذا اكتب معلومات التشخيص فيه وأنهِ العملية برمز خروج غير صفري:
الحالات الشائعة:
  • يتوقف الاستعلام عن الاستجابة، ثم يفشل بسبب انتهاء المهلة: خزّنت العملية مخرجاتها مؤقتًا بصيغة قائمة على الصفوف دون تفعيل Send chunk header. فعّل هذا الخيار ونفّذ التفريغ مرة واحدة لكل مقطع، أو مرة واحدة لكل كتلة عند استخدام صيغة Native.
  • رمز الإرجاع 1 مع تتبّع MemoryError (بايثون): تجاوزت العملية حد الذاكرة. ارفع قيمة حد الذاكرة أو قلّل استهلاك الذاكرة لكل عملية.
  • إخفاقات متقطعة مع النوع executable تحت ضغط الحمل العالي: انتقل إلى executable_pool.
  • حالة الإصدار هي error: الملف main.py (بايثون) أو الملفان amd64/main وarm64/main (Native) غير موجودة في جذر ملف zip، أو يحتوي الأرشيف على روابط رمزية.
  • تعذّر إنشاء الدالة: الاسم يتعارض مع اسم دالة مدمجة.

إدارة UDFs باستخدام Cloud واجهة برمجة تطبيقات

تتوفر عمليات دورة الحياة الخاصة بوحدة التحكم برمجيًا أيضًا عبر ClickHouse Cloud واجهة برمجة تطبيقات. تتيح لك نقاط نهاية UDF إعداد برامج نصية لتحميل أرشيفات المصدر، وإنشاء الدالات والإصدارات، وإرفاقها بالخدمات وفصلها عنها، وحذف الإصدارات والدالات. لا تتضمن واجهة برمجة التطبيقات عملية لإعادة التحميل: بعد إرفاق إصدار جديد من UDF من نوع executable_pool بخدمة، شغّل SYSTEM RELOAD FUNCTION ON CLUSTER default <name> عبر SQL على تلك الخدمة لكي تعتمد عمليات المجمّع الإصدار الجديد.
نقاط النهاية هذه في مرحلة Beta، وقد يتغير عقد واجهة برمجة تطبيقات.
سير العمل المعتاد لإنشاء UDF ونشرها عبر واجهة برمجة تطبيقات هو:
  1. أنشئ URL للتحميل للحصول على URL تحميل application/zip موقّع مسبقًا، ثم حمّل أرشيف ZIP إليه. لا يمكن استخدام كل معرّف تحميل إلا لمحاولة إنشاء واحدة، سواء لـ UDF أو لإصدار؛ اطلب URL تحميل جديدًا عند إعادة المحاولة.
  2. أنشئ UDF من الأرشيف المُحمَّل، مع تحديد اسم الدالة وبيئة التشغيل والوسيطات ونوع الإرجاع.
  3. أرفق UDF بخدمة. إذا لم يُحدَّد الإصدار، يُرفق أحدث إصدار جاهز. يجب أن تكون الخدمة قيد التشغيل؛ ويمكن إيقاظ الخدمات الخاملة أولًا.
حقول الطلب التي تحدد الإمكانات الموضحة أعلاه هي: المجموعة الكاملة من نقاط النهاية: راجع مرجع UDF واجهة برمجة تطبيقات للاطلاع على مخططات الطلبات والاستجابات.

إدارة UDFs باستخدام Terraform

يتضمن موفّر Terraform الرسمي لـ ClickHouse موردين لإدارة UDFs كبنية تحتية معرّفة بالشيفرة:
  • يدير clickhouse_udf الدالة نفسها. ويأخذ أرشيف ZIP يتضمن شيفرة مصدر الدالة وينشر إصدارًا جديدًا كلما تغيّر hash الأرشيف، مع انتظار اكتمال عملية البناء.
  • يرفق clickhouse_udf_attachment إصدار UDF بخدمة. لا يمكن أن تحتوي الخدمة إلا على إصدار واحد من الدالة في الوقت نفسه. يمكنك تثبيت رقم إصدار محدد، أو الإشارة إلى clickhouse_udf.<name>.version لترقية الخدمات تلقائيًا إلى أحدث إصدار.
تتوفر هذه الموارد في إصدار الموفّر 3.24.0 والإصدارات الأحدث. وهي في حالة beta، وقد يتغير سلوكها في إصدارات الموفّر المستقبلية.
على سبيل المثال، لنشر UDF‏ isBusinessHours من المثال السابق باستخدام Terraform:
بالإضافة إلى السمات المطلوبة الموضحة أعلاه، يقبل المورد clickhouse_udf الخيارات format وpool_size وmax_command_execution_time وcommand_read_timeout وcommand_write_timeout وsend_chunk_header وsandbox_type وsandbox_version وreturn_name وfail_on_build_error؛ راجع توثيق المورد للاطلاع على المخطط الكامل. لاختبار إصدار جديد على خدمة تطوير قبل وصوله إلى بيئة الإنتاج، اجعل أحد الإرفاقين يتتبّع أحدث إصدار، وثبّت الآخر على قيمة متغير. يتبع إرفاق التطوير كل إصدار جديد تلقائيًا، في حين لا ينتقل إرفاق الإنتاج إلى إصدار آخر إلا عند تغيير var.prod_udf_version:
لا يتيح الموفّر حتى الآن الخاصية deterministic ولا حدّ الذاكرة. فكلاهما يُضبط عند إنشاء الإصدار، ولذلك لا يمكن أن تتضمنهما الإصدارات التي ينشرها الموفّر. لاستخدامهما، أنشئ تلك الإصدارات عبر وحدة التحكم أو واجهة برمجة التطبيقات بدلًا من ذلك.
لا تنجح عملية الإرفاق إلا للإصدارات الجاهزة، وقد تستغرق عدة دقائق؛ وتُفعَّل الخدمات الخاملة تلقائيًا. كذلك لا يعيد الموفّر تحميل المجمّعات: بالنسبة إلى UDFs من النوع executable_pool، شغّل SYSTEM RELOAD FUNCTION ON CLUSTER default <name> على الخدمة بعد أن يتغيّر الإصدار المرفق. يؤدي حذف مورد clickhouse_udf إلى إزالة جميع إصدارات الدالة وفصلها عن جميع الخدمات.