إذا كنت بحاجة إلى أي مساعدة، يُرجى فتح issue في الـ repository أو طرح سؤال في قناة Slack العامة لـ ClickHouse.
الترخيص
متطلبات البيئة
مصفوفة توافق الإصدارات
الميزات الرئيسية
- يأتي مزوّدًا بضمانات exactly-once جاهزة للاستخدام. ويعتمد على ميزة أساسية جديدة في ClickHouse باسم KeeperMap (تُستخدم كمخزن للحالة بواسطة الموصل)، ما يتيح معمارية مبسطة للغاية.
- دعم مخازن الحالة التابعة لجهات خارجية: يستخدم حاليًا In-memory افتراضيًا، ويمكنه أيضًا استخدام KeeperMap (ستتم إضافة Redis قريبًا).
- تكامل أصيل: يطوّره ClickHouse ويتولى صيانته ودعمه.
- يُختبَر باستمرار على ClickHouse Cloud.
- يدعم إدراج البيانات بمخطط مُعلن أو بدون مخطط.
- يدعم جميع أنواع البيانات في ClickHouse.
إرشادات التثبيت
اجمع بيانات الاتصال الخاصة بك
تتوفر تفاصيل خدمة ClickHouse Cloud الخاصة بك في ClickHouse Cloud console.
حدِّد خدمة ثم انقر على Connect:

curl.

إرشادات التثبيت العامة
- نزّل أرشيف ZIP يحتوي على ملف JAR الخاص بالموصل من صفحة Releases في مستودع ClickHouse Kafka Connect Sink.
- استخرج محتويات ملف ZIP وانسخها إلى الموقع المطلوب.
- أضف path يتضمن دليل المكوّن الإضافي إلى إعداد plugin.path في ملف خصائص Connect للسماح لـ Confluent Platform بالعثور على المكوّن الإضافي.
- وفّر اسم الموضوع وhostname الخاص بـ ClickHouse instance وpassword في config.
- أعد تشغيل Confluent Platform.
- إذا كنت تستخدم Confluent Platform، فسجّل الدخول إلى واجهة المستخدم الخاصة بـ Confluent Control Center للتحقق من أن ClickHouse Sink متاح في قائمة الموصلات المتاحة.
خيارات التهيئة
- تفاصيل الاتصال: اسم المضيف (مطلوب) والمنفذ (اختياري)
- بيانات اعتماد المستخدم: كلمة المرور (مطلوب) واسم المستخدم (اختياري)
- فئة الموصّل:
com.clickhouse.kafka.connect.ClickHouseSinkConnector(مطلوب) topicsأوtopics.regex: مواضيع Kafka التي سيقرأها الموصّل — يجب أن تتطابق أسماء المواضيع مع أسماء الجداول (مطلوب)- محوّلات المفتاح والقيمة: اضبطها بناءً على نوع البيانات في الموضوع لديك. وهي مطلوبة إذا لم تكن معرّفة مسبقًا في إعدادات العامل.
الجداول المستهدفة
المعالجة المسبقة
أنواع البيانات المدعومة
-
(1) - لا يكون JSON مدعومًا إلا عندما تتضمن ClickHouse settings القيمة
input_format_binary_read_json_as_string=1. ولا يعمل ذلك إلا مع عائلة تنسيقات RowBinary format، كما يؤثر هذا الإعداد في جميع الأعمدة ضمن طلب insert، لذا يجب أن تكون كلها من نوع سلسلة نصية. في هذه الحالة، سيحوّل موصل قيمة STRUCT إلى JSON string. -
(2) - عندما يحتوي struct على unions مثل
oneof، يجب تهيئة converter بحيث لا يضيف prefix/suffix إلى أسماء الحقول. يتوفر الإعدادgenerate.index.for.unions=falseلـProtobufConverter.
وصفات التهيئة
التهيئة الأساسية
localhost:8443 مع تمكين SSL، وأن البيانات بتنسيق JSON بلا مخطط.
يتطلب إعداد الموصل أعلاه تمكين تجاوزات العميل في إعدادات العامل عبر
connector.client.config.override.policy=All. راجع وثائق Kafka Connect لمزيد من المعلومات.تهيئة أساسية مع موضوعات متعددة
تهيئة أساسية مع DLQ
دعم مخططات Avro
تعيين أنواع Avro
io.confluent.connect.avro.AvroConverter، وهو التنفيذ الرسمي لتسلسل/إلغاء تسلسل Avro في Kafka Connect. راجع وثائق Kafka Connect للحصول على معلومات متقدمة حول منطق التحويل.
✅: مدعوم
❌: غير مدعوم
️⚠️: مدعوم جزئيًا
ارجع إلى أنواع البيانات المدعومة للاطلاع على التعيين بين أنواع Kafka Connect وأنواع ClickHouse.
مخططات Avro غير المدعومة
- النوع المنطقي
decimalالمبني علىfixed
- اتحادات تقبل NULL
- حقول اتحاد في السجلات
دعم مخطط Protobuf
تعيين أنواع Protobuf
io.confluent.connect.protobuf.ProtobufConverter، وهو التنفيذ الرسمي لتسلسل/إلغاء تسلسل Protobuf في Kafka Connect. راجع وثائق Kafka Connect للحصول على معلومات متقدمة حول منطق التحويل.
✅: مدعوم
❌: غير مدعوم
️⚠️: مدعوم جزئيًا
ارجع إلى أنواع البيانات المدعومة للاطلاع على التعيين بين أنواع Kafka Connect وأنواع ClickHouse.
ملاحظة حول ترجمة حقول oneof إلى أعمدة ClickHouse
oneof) إلى النوع Variant في ClickHouse. وبدلًا من ذلك، أدرِج حقول oneof كحقول Nullable منفصلة في مخطط جدول ClickHouse لديك.
على سبيل المثال:
مخططات Protobuf غير المدعومة
- بُنى union متعددة الرسائل (قبل الإصدار 26.1 من CH)
allow_experimental_nullable_tuple_type=1 (راجع صفحة التوثيق هذه).
دعم مخطط JSON
دعم String
التخزين المؤقت الداخلي
poll() ثم flush لها إلى ClickHouse على شكل دفعات أكبر. ويمكن أن يحسّن ذلك الإنتاجية في أعباء العمل التي ينتج فيها كل استدعاء poll() العديد من الدفعات الصغيرة لكل partition.
السلوك الأساسي:
- يتحكم
bufferCountفي عدد السجلات التي تُخزَّن مؤقتًا قبل الـ flush. - يحدّد
bufferFlushTimeالحد الأقصى لوقت الانتظار (بالمللي ثانية) قبل عمل flush للسجلات المخزّنة مؤقتًا. - لا يكون
bufferFlushTimeفعّالًا إلا عندما تكونbufferCount > 0. - يُبقي
bufferCount=0وbufferFlushTime=0التخزين المؤقت معطّلًا (السلوك الافتراضي). - لا يكون التخزين المؤقت مدعومًا عندما تكون
exactlyOnce=true.
exactlyOnce=false في config الخاص بالموصل، أو تعطيل التخزين المؤقت باستخدام bufferCount=0.
مثال:
التسجيل
المراقبة
المقاييس الخاصة بـ ClickHouse
مقاييس منتِج/مستهلك Kafka
records-sent-total: إجمالي عدد السجلات المُرسلة إلى الموضوعbytes-sent-total: إجمالي البايتات المُرسلة إلى الموضوعrecord-send-rate: متوسط معدل السجلات المُرسلة في الثانيةbyte-rate: متوسط عدد البايتات المُرسلة في الثانيةcompression-rate: نسبة الضغط المتحققة
records-sent-total: إجمالي السجلات المُرسلة إلى الـ partitionbytes-sent-total: إجمالي البايتات المُرسلة إلى الـ partitionrecords-lag: مقدار التأخر الحالي في الـ partitionrecords-lead: مقدار التقدّم الحالي في الـ partitionreplica-fetch-lag: معلومات التأخر الخاصة بالنسخ المتماثلة
connection-creation-total: إجمالي الاتصالات التي أُنشئت مع عقدة Kafkaconnection-close-total: إجمالي الاتصالات التي أُغلقتrequest-total: إجمالي الطلبات المُرسلة إلى العقدةresponse-total: إجمالي الاستجابات المستلمة من العقدةrequest-rate: متوسط معدل الطلبات في الثانيةresponse-rate: متوسط معدل الاستجابات في الثانية
- معدل النقل: تتبّع معدلات إدخال البيانات
- التأخر: تحديد الاختناقات وتأخيرات المعالجة
- الضغط: قياس كفاءة ضغط البيانات
- سلامة الاتصال: مراقبة اتصال الشبكة واستقراره
مقاييس Kafka Connect Framework
task-count: العدد الإجمالي للمهام في الموصلrunning-task-count: عدد المهام قيد التشغيل حاليًاpaused-task-count: عدد المهام المتوقفة مؤقتًا حاليًاfailed-task-count: عدد المهام التي فشلتdestroyed-task-count: عدد المهام التي أُزيلتunassigned-task-count: عدد المهام غير المسندة
running وpaused وfailed وdestroyed وunassigned
مقاييس الأخطاء:
deadletterqueue-produce-failures: عدد عمليات الكتابة الفاشلة إلى DLQdeadletterqueue-produce-requests: إجمالي محاولات الكتابة إلى DLQlast-error-timestamp: الطابع الزمني لآخر خطأrecords-skip-total: العدد الإجمالي للسجلات التي جرى تخطيها بسبب الأخطاءrecords-retry-total: العدد الإجمالي للسجلات التي أُعيدت محاولتهاerrors-total: العدد الإجمالي للأخطاء التي تم رصدها
offset-commit-failures: عدد حالات فشل تثبيت الإزاحةoffset-commit-avg-time-ms: متوسط وقت تثبيت الإزاحةoffset-commit-max-time-ms: أقصى وقت لتثبيت الإزاحةput-batch-avg-time-ms: متوسط وقت معالجة دفعةput-batch-max-time-ms: أقصى وقت لمعالجة دفعةsource-record-poll-total: إجمالي السجلات التي جرى سحبها
أفضل ممارسات المراقبة
- راقب تأخر المستهلك: تتبّع
records-lagلكل تقسيم لتحديد مواضع اختناق المعالجة - تتبّع معدلات الأخطاء: راقب
errors-totalوrecords-skip-totalلاكتشاف مشكلات جودة البيانات - راقب سلامة المهام: راقب مقاييس حالة المهام للتأكد من أنها تعمل على النحو الصحيح
- قِس معدل الإنتاجية: استخدم
records-send-rateوbyte-rateلتتبّع أداء الاستيعاب - راقب سلامة الاتصال: تحقّق من مقاييس الاتصال على مستوى العقدة لاكتشاف مشكلات الشبكة
- تتبّع كفاءة الضغط: استخدم
compression-rateلتحسين نقل البيانات
القيود
- عمليات الحذف غير مدعومة.
- يُورَّث حجم الدفعة من خصائص مستهلك Kafka.
- عند استخدام KeeperMap لتحقيق ضمان المعالجة مرة واحدة فقط وتغيير الإزاحة أو إرجاعها إلى قيمة سابقة، تحتاج إلى حذف المحتوى من KeeperMap لذلك الـموضوع المحدد. (راجع دليل استكشاف الأخطاء وإصلاحها أدناه لمزيد من التفاصيل)
ضبط الأداء وتحسين معدل النقل
متى تكون هناك حاجة إلى ضبط الأداء؟
- أحمال العمل ذات معدل النقل المرتفع: عند معالجة ملايين الأحداث في الثانية من موضوعات Kafka
- تأخر المستهلك: عندما لا يتمكن الموصّل من مجاراة معدل إنتاج البيانات، مما يؤدي إلى زيادة التأخر
- قيود الموارد: عندما تحتاج إلى تحسين استخدام CPU أو الذاكرة أو الشبكة
- موضوعات متعددة: عند الاستهلاك من عدة موضوعات كبيرة الحجم في الوقت نفسه
- أحجام الرسائل الصغيرة: عند التعامل مع عدد كبير من الرسائل الصغيرة التي ستستفيد من التجميع على جانب الخادم
- تعالج أحجامًا منخفضة إلى متوسطة (< 10,000 رسالة/ثانية)
- يكون تأخر المستهلك مستقرًا ومقبولًا بالنسبة إلى حالة الاستخدام لديك
- تكون إعدادات الموصّل الافتراضية تلبي بالفعل متطلبات معدل النقل لديك
- يمكن لعنقود ClickHouse لديك التعامل بسهولة مع الحمل الوارد
فهم تدفق البيانات
- يقوم Kafka Connect Framework بجلب الرسائل من موضوعات Kafka في الخلفية
- يستطلع الموصّل الرسائل من المخزن المؤقت الداخلي للإطار
- يجمّع الموصّل الرسائل استنادًا إلى حجم الاستطلاع
- يتلقى ClickHouse عملية الإدراج المجمّعة عبر HTTP/S
- يعالج ClickHouse عملية الإدراج (بشكل متزامن أو غير متزامن)
ضبط حجم الدُفعات في Kafka Connect
إعدادات الجلب
fetch.min.bytes: الحد الأدنى لكمية البيانات قبل أن يمرّر الإطار القيم إلى الموصل (الافتراضي: 1 بايت)fetch.max.bytes: الحد الأقصى لكمية البيانات التي يمكن جلبها في طلب واحد (الافتراضي: 52428800 / 50 ميغابايت)fetch.max.wait.ms: الحد الأقصى لمدة الانتظار قبل إعادة البيانات إذا لم يتم استيفاءfetch.min.bytes(الافتراضي: 500 مللي ثانية)
في Confluent Cloud، يتطلب تعديل هذه الإعدادات فتح تذكرة دعم عبر Confluent Cloud.
إعدادات الاستطلاع
max.poll.records: الحد الأقصى لعدد السجلات المُعادة في عملية استطلاع واحدة (الافتراضي: 500)max.partition.fetch.bytes: الحد الأقصى لكمية البيانات لكل تقسيم (الافتراضي: 1048576 / 1 MB)
في Confluent Cloud، يتطلّب تعديل هذه الإعدادات فتح تذكرة دعم عبر Confluent Cloud.
الإعدادات الموصى بها لمعدل النقل العالي
تتطلب الخصائص المذكورة أعلاه تمكين تجاوزات العميل في إعداد العامل عبر
connector.client.config.override.policy=All. راجع وثائق Kafka Connect لمزيد من المعلومات.- دفعات أكبر = أداء أفضل لإدخال البيانات إلى ClickHouse، وأجزاء أقل، وعبء إضافي أقل
- دفعات أكبر = استخدام أعلى للذاكرة، واحتمال زيادة زمن الانتقال من البداية إلى النهاية
- دفعات كبيرة جدًا = خطر حدوث timeout، أو أخطاء OutOfMemory، أو تجاوز
max.poll.interval.ms
عمليات الإدراج غير المتزامنة
متى تستخدم عمليات الإدراج غير المتزامنة
- العديد من الدُفعات الصغيرة: يرسل الموصّل دُفعات صغيرة ومتكررة (< 1000 صف لكل دفعة)
- تزامن مرتفع: تكتب مهام موصّل متعددة إلى الجدول نفسه
- نشر موزّع: تشغيل العديد من مثيلات الموصّل عبر مضيفين مختلفين
- عبء إضافي ناتج عن إنشاء الأجزاء: تواجه أخطاء “عدد كبير جدًا من الأجزاء”
- عبء عمل مختلط: الجمع بين استيعاب البيانات في الوقت الفعلي وأعباء عمل الاستعلامات
- كنت ترسل بالفعل دُفعات كبيرة (> 10,000 صف لكل دفعة) بوتيرة مضبوطة
- كنت تحتاج إلى ظهور البيانات فورًا (يجب أن ترى الاستعلامات البيانات على الفور)
- كانت دلالات ضمان المعالجة مرة واحدة فقط مع
wait_for_async_insert=0تتعارض مع متطلباتك - كان سيناريو الاستخدام لديك سيستفيد بدلًا من ذلك من تحسينات التجميع على جهة العميل
كيف تعمل عمليات الإدراج غير المتزامنة
- يستقبل استعلام الإدراج من الموصّل
- يكتب البيانات إلى مخزن مؤقت في الذاكرة (بدلًا من كتابتها إلى القرص فورًا)
- يعيد نجاح العملية إلى الموصّل (إذا كانت
wait_for_async_insert=0) - يفرّغ المخزن المؤقت إلى القرص عند تحقق أحد الشروط التالية:
- وصول المخزن المؤقت إلى
async_insert_max_data_size(القيمة الافتراضية: 100 MB) - انقضاء
async_insert_busy_timeout_msملّي ثانية منذ أول عملية إدراج (القيمة الافتراضية: 1000 ms) - بلوغ الحد الأقصى لعدد الاستعلامات المتراكمة (
async_insert_max_query_number، القيمة الافتراضية: 100)
- وصول المخزن المؤقت إلى
تمكين async inserts
clickhouseSettings:
async_insert=1: تمكين الإدراجات غير المتزامنةwait_for_async_insert=1(موصى به): ينتظر الموصل حتى تُفرَّغ البيانات إلى تخزين ClickHouse قبل إرسال الإقرار. يوفّر ضمانات للتسليم.wait_for_async_insert=0: يرسل الموصل الإقرار فورًا بعد التخزين المؤقت. يوفّر أداءً أفضل، لكن قد تُفقد البيانات إذا تعطّل الخادم قبل تفريغها.
ضبط سلوك async insert
flush في async insert بدقة:
async_insert_max_data_size(الافتراضي: 104857600 / 100 MB): الحد الأقصى لحجم المخزن المؤقت قبل التفريغasync_insert_busy_timeout_ms(الافتراضي: 1000): الحد الأقصى للوقت (مللي ثانية) قبل التفريغasync_insert_stale_timeout_ms(الافتراضي: 0): الوقت (مللي ثانية) منذ آخر عملية إدراج قبل التفريغasync_insert_max_query_number(الافتراضي: 100): الحد الأقصى لعدد الاستعلامات قبل التفريغ
- الفوائد: أجزاء بيانات أقل، وأداء دمج أفضل، وعبء أقل على CPU، وتحسّن في معدل النقل عند ارتفاع التزامن
- اعتبارات: لا تصبح البيانات قابلة للاستعلام فورًا، مع زيادة طفيفة في زمن الوصول من البداية إلى النهاية
- المخاطر: فقدان البيانات عند تعطل الخادم إذا كانت قيمة
wait_for_async_insert=0، واحتمال زيادة الضغط على الذاكرة مع المخازن المؤقتة الكبيرة
الإدراجات غير المتزامنة مع ضمان المعالجة مرة واحدة فقط
exactlyOnce=true مع الإدراجات غير المتزامنة:
wait_for_async_insert=1 مع exactly-once لضمان عدم تنفيذ عمليات commit للإزاحة إلا بعد حفظ البيانات بشكل دائم.
لمزيد من المعلومات حول async inserts، راجع وثائق ClickHouse الخاصة بـ async inserts.
توازي الموصّل
المهام لكل موصل
- الحد الأقصى الفعّال لعدد المهام = عدد أقسام موضوع
- تحتفظ كل مهمة باتصالها الخاص بـ ClickHouse
- المزيد من المهام = عبء إضافي أكبر واحتمال أعلى لحدوث تنازع على الموارد
tasks.max ليعادل عدد أقسام موضوع، ثم اضبطه بناءً على مقاييس CPU ومعدل النقل.
تجاهل الأقسام عند التجميع على دفعات
exactlyOnce=false. يمكن أن يحسّن هذا الإعداد معدل النقل من خلال إنشاء دفعات أكبر، لكنه يفقد ضمانات الترتيب داخل كل قسم.
عدة موضوعات عالية الإنتاجية
topic2TableMap لربط الـ موضوعات بالجداول، وكنت تواجه اختناقًا عند الإدراج يؤدي إلى تأخر المستهلك، ففكّر في إنشاء موصل مستقل لكل موضوع بدلًا من ذلك.
يرجع السبب الرئيسي في ذلك إلى أن الدُفعات تُدرَج حاليًا في كل جدول بشكل تسلسلي.
التوصية: عند التعامل مع عدة موضوعات كبيرة الحجم، قم بنشر instance واحدة من موصل لكل موضوع لتحقيق أقصى معدل نقل متوازٍ لعمليات الإدراج.
اعتبارات محرّك جدول ClickHouse
MergeTree: الأفضل لمعظم حالات الاستخدام، إذ يوازن بين أداء الاستعلام والإدراجReplicatedMergeTree: مطلوب لتحقيق التوفّر العالي، ويضيف عبئًا إضافيًا بسبب النسخ المتماثل*MergeTreeمعORDER BYمضبوط على نحو صحيح: حسّنه بما يلائم أنماط الاستعلام لديك
تجميع الاتصالات والمهل الزمنية
socket_timeout(الافتراضي: 30000 مللي ثانية): الحد الأقصى لمدة عمليات القراءةconnection_timeout(الافتراضي: 10000 مللي ثانية): الحد الأقصى للوقت اللازم لإنشاء الاتصال
مراقبة الأداء واستكشاف المشكلات
- Consumer lag: استخدم أدوات مراقبة Kafka لتتبّع التأخر في كل تقسيم
- مقاييس الموصل: راقب
receivedRecordsوrecordProcessingTimeوtaskProcessingTimeعبر JMX (راجع Monitoring) - مقاييس ClickHouse:
system.asynchronous_inserts: راقب استخدام المخزن المؤقت لعملية الإدراج غير المتزامنةsystem.parts: راقب عدد الأجزاء لاكتشاف مشكلات الدمجsystem.merges: راقب عمليات الدمج النشطةsystem.events: تتبّعInsertedRowsوInsertedBytesوFailedInsertQuery
ملخص أفضل الممارسات
- ابدأ بالإعدادات الافتراضية، ثم قِس واضبط استنادًا إلى الأداء الفعلي
- فضّل الدُفعات الأكبر: استهدف 10,000-100,000 صف لكل insert متى أمكن
- استخدم عمليات الإدراج غير المتزامنة عند إرسال الكثير من الدُفعات الصغيرة أو عند ارتفاع التزامن
- استخدم دائمًا
wait_for_async_insert=1مع ضمان المعالجة مرة واحدة فقط - وسّع أفقيًا: زِد
tasks.maxحتى يصل إلى عدد التقسيمات - موصل واحد لكل topic مرتفع الحجم لتحقيق أقصى إنتاجية
- راقب باستمرار: تتبّع تأخر المستهلك، وعدد الأجزاء، ونشاط الدمج
- اختبر جيدًا: اختبر دائمًا تغييرات التكوين تحت حمل واقعي قبل النشر في بيئة الإنتاج
مثال: إعداد لمعدل نقل عالٍ
تتطلب إعدادات الموصل أعلاه تمكين client overrides في إعدادات العامل عبر
connector.client.config.override.policy=All. راجع وثائق Kafka Connect لمزيد من المعلومات.- يعالج ما يصل إلى 10,000 سجل في كل عملية poll
- ينشئ batches عبر الأقسام للحصول على عمليات insert أكبر
- يستخدم عملية الإدراج غير المتزامنة مع buffer بسعة 16 ميغابايت
- يشغّل 8 tasks متوازية (طابقها مع عدد الأقسام لديك)
- مُحسَّن لتحقيق أعلى معدل النقل بدلًا من الالتزام الصارم بالترتيب
استكشاف الأخطاء وإصلاحها
”عدم تطابق الحالة للموضوع [someTopic] والتقسيم [0]”
قد يؤثر هذا التعديل في ضمان المعالجة مرة واحدة فقط.
”ما الأخطاء التي سيُعيد الموصل المحاولة معها؟”
ClickHouseException- هذا استثناء عام يمكن أن يطرحه ClickHouse. ويُطرح عادةً عندما يكون الخادم مثقلًا، وتُعد رموز الخطأ التالية عابرة بشكل خاص:- 3 - UNEXPECTED_END_OF_FILE
- 107 - FILE_DOESNT_EXIST
- 159 - TIMEOUT_EXCEEDED
- 164 - READONLY
- 202 - TOO_MANY_SIMULTANEOUS_QUERIES
- 203 - NO_FREE_CONNECTION
- 209 - SOCKET_TIMEOUT
- 210 - NETWORK_ERROR
- 241 - MEMORY_LIMIT_EXCEEDED
- 242 - TABLE_IS_READ_ONLY
- 252 - TOO_MANY_PARTS
- 285 - TOO_FEW_LIVE_REPLICAS
- 319 - UNKNOWN_STATUS_OF_INSERT
- 425 - SYSTEM_ERROR
- 999 - KEEPER_EXCEPTION
SocketTimeoutException- يُطرح هذا عندما تنتهي مهلة المقبس.UnknownHostException- يُطرح هذا عندما يتعذر تحديد المضيف.IOException- يُطرح هذا عندما تكون هناك مشكلة في الشبكة.
”كل بياناتي فارغة/أصفار”
_ كفاصل). وستتبع الحقول في الجدول بعد ذلك التنسيق “field1_field2_field3” (أي “before_id” و”after_id” وما إلى ذلك).
”أريد استخدام مفاتيح Kafka الخاصة بي في ClickHouse”
KeyToValue لنقل المفتاح إلى حقل القيمة (ضمن حقل جديد باسم _key):