لا يُنصح بإرسال عدد كبير من الدفعات الصغيرة في الوضع المتزامن، لأن ذلك يؤدي إلى إنشاء عدد كبير من الأجزاء. وينتج عن ذلك ضعف في أداء الاستعلامات وظهور أخطاء “عدد كبير جدًا من الأجزاء”.
async_insert.

async_insert = 1)، تُخزَّن عمليات الإدراج مؤقتًا ولا تُكتب إلى القرص إلا عند تحقق أحد شروط التفريغ التالية:
- يصل المخزن المؤقت إلى حجم بيانات محدد (
async_insert_max_data_size، والقيمة الافتراضية 100 MiB). - انقضاء حد زمني (
async_insert_busy_timeout_ms، والقيمة الافتراضية 200 ms أو 1000 ms على Cloud). - تراكم عدد أقصى من استعلامات الإدراج (
async_insert_max_query_number، والقيمة الافتراضية 450).
اختيار وضع الإرجاع
يمكن ضبط سلوك عمليات الإدراج غير المتزامنة بمزيد من الدقة باستخدام الإعدادwait_for_async_insert.
عند ضبطه على 1 (وهو الإعداد الافتراضي)، لا يؤكد ClickHouse عملية insert إلا بعد تفريغ البيانات إلى قرص بنجاح. ويضمن ذلك مستوىً قويًا من استمرارية البيانات، كما يجعل التعامل مع error مباشرًا: فإذا حدث خطأ أثناء الـ تفريغ، يُعاد هذا error إلى client. ويُنصح بهذا الوضع في معظم سيناريوهات production، خاصةً عندما يكون من الضروري تتبّع حالات فشل insert بشكل موثوق.
تُظهر المقارنات المعيارية أنه يتوسع جيدًا مع Concurrency، سواء كنت تشغّل 200 أو 500 client، وذلك بفضل inserts التكيفية والسلوك المستقر في إنشاء جزء.
يؤدي ضبط wait_for_async_insert = 0 إلى تفعيل وضع “fire-and-forget”. في هذا الوضع، يؤكد server عملية insert بمجرد تخزين البيانات في مخزن مؤقت، من دون انتظار وصولها إلى Storage.
يوفّر ذلك عمليات insert بزمن latency منخفض جدًا وأقصى throughput، ما يجعله مثاليًا للبيانات عالية التدفق ومنخفضة الأهمية. لكن لهذا الوضع مفاضلاته: فلا يوجد ضمان لاستمرار حفظ البيانات، ولا تظهر الأخطاء إلا أثناء تفريغ، كما لا توجد dead-letter queue لعمليات inserts الفاشلة — ولذلك يتطلب تتبّع حالات الفشل فحص سجلات الخادم وsystem tables بعد حدوثها. استخدم هذا الوضع فقط إذا كان workload لديك يمكنه تحمّل فقدان البيانات.
وتُظهر المقارنات المعيارية أيضًا انخفاضًا كبيرًا في عدد الأجزاء وتراجعًا في CPU usage عندما تكون عمليات تفريغ للـ مخزن مؤقت غير متكررة (مثلًا كل 30 Seconds)، لكن خطر الفشل الصامت يظل قائمًا.
نوصي بشدة باستخدام async_insert=1,wait_for_async_insert=1 عند استخدام عمليات الإدراج غير المتزامنة. فاستخدام wait_for_async_insert=0 ينطوي على مخاطر كبيرة جدًا، لأن INSERT client قد لا يكتشف وجود أخطاء، وقد يؤدي أيضًا إلى حمل زائد محتمل إذا واصل client الكتابة بسرعة في موقف يحتاج فيه ClickHouse server إلى إبطاء عمليات الكتابة وفرض بعض الضغط العكسي لضمان موثوقية service.
عمليات الإدراج غير المتزامنة التكيفية
اعتبارًا من الإصدار 24.2، يستخدم ClickHouse افتراضيًا مهلات تفريغ تكيفية (async_insert_use_adaptive_busy_timeout). فبدلًا من فاصل زمني ثابت للتفريغ، تُضبط المهلة ديناميكيًا بين حد أدنى (async_insert_busy_timeout_min_ms، والقيمة الافتراضية 50 مللي ثانية) وحد أقصى (async_insert_busy_timeout_max_ms، والقيمة الافتراضية 200 مللي ثانية أو 1000 مللي ثانية على Cloud) استنادًا إلى معدل البيانات الواردة.
عندما تصل البيانات بوتيرة متكررة، تبقى المهلة أقرب إلى الحد الأدنى لتفريغ البيانات بشكل أسرع وتقليل زمن الانتقال من الطرف إلى الطرف. وعندما تكون البيانات متناثرة، ترتفع المهلة باتجاه الحد الأقصى لتجميع دفعات أكبر. ويكون ذلك مفيدًا بشكل خاص في الوضع الافتراضي (wait_for_async_insert=1)، إذ إن المهلة الثابتة المرتفعة ستجبر العميل على الانتظار طوال الفاصل الزمني الكامل حتى عندما تكون البيانات جاهزة للتفريغ.
معالجة الأخطاء
يحدث التحقق من المخطط وتحليل البيانات أثناء تفريغ المخزن المؤقت، وليس عند استلام عملية insert. إذا احتوى أي صف في استعلام insert على خطأ في التحليل أو في النوع، فلن يُفرَّغ أيٌّ من بيانات ذلك الاستعلام — بل تُرفَض حمولة الاستعلام بالكامل. في الوضع الافتراضي (wait_for_async_insert=1)، يُعاد الخطأ إلى العميل. أما في وضع fire-and-forget، فتُسجَّل الأخطاء في سجلات الخادم وفي جدول system.asynchronous_inserts.
تُعاد أيضًا عملية البحث عن الوجهة والتحقق من الأذونات عند التفريغ، وفقًا لحالة الكتالوج والتحكم في الوصول في ذلك الوقت، لا لحالتهما عند استلام عملية insert. لذا، فإن إرفاق عرض مُجسَّد بالوجهة أو إلغاء أحد الأذونات بين استلام عملية insert وتفريغ مخزنها المؤقت يؤثر في عملية التفريغ.
ينشئ كل تفريغ جزءًا واحدًا على الأقل لكل قيمة مميزة لمفتاح partition في المخزن المؤقت. وحتى في الجداول التي لا تحتوي على مفتاح partition، يمكن لعملية تفريغ واحدة أن تُنتج عدة أجزاء إذا تجاوزت البيانات المخزنة مؤقتًا max_insert_block_size (الافتراضي نحو مليون صف).
على الرغم من استخدام عملية الإدراج غير المتزامنة، فقد تظل تواجه أخطاء “too many parts” إذا كان مفتاح partitioning ذا كاردينالية عالية.
إزالة التكرار والموثوقية
بدءًا من الإصدار 26.2، يُجري ClickHouse إزالة التكرار تلقائيًا لعمليات الإدراج غير المتزامنة والمتزامنة، مما يجعل إعادة المحاولة آمنة في الجداول التي تحتفظ بسجل لإزالة التكرار. تحتفظ محركات*ReplicatedMergeTree بهذا السجل افتراضيًا؛ أما جدول MergeTree العادي، فيتطلب ضبط non_replicated_deduplication_window على قيمة موجبة. يتحكم الإعداد deduplicate_insert في كلا نوعَي عمليات الإدراج، وقيمته الافتراضية هي enable. كما تُدعَم طرق العرض المجسّدة التابعة.
عمليًا، إذا أُعيدت محاولة عملية الإدراج نفسها — بسبب مهلة أو انقطاع في الشبكة، مثلًا — يمكن لـ ClickHouse تجاهل العملية المكررة بأمان. يساعد ذلك على ضمان عدم التكرار وتجنب كتابة البيانات مرتين. بالنسبة إلى عمليات الإدراج غير المتزامنة، تعمل إزالة التكرار على مستوى استعلام المستخدم، لا على مستوى كل دفعة تم تفريغها؛ لذلك، لا يؤدي الاستعلام المكرر إلى تجاهل الاستعلامات الأخرى المجمّعة معه.
للتفاصيل، وللاطلاع على القيد الوحيد الذي ينطبق على طرق العرض المجسّدة مع عمليات الإدراج غير المتزامنة، راجع إزالة تكرار عمليات الإدراج عند إعادة المحاولة.
تمكين عمليات الإدراج غير المتزامنة
يمكن تمكين عمليات الإدراج غير المتزامنة لمستخدم معيّن أو لاستعلام محدد:-
تمكين عمليات الإدراج غير المتزامنة على مستوى المستخدم. يستخدم هذا المثال المستخدم
default، فإذا أنشأت مستخدمًا آخر، فاستبدل اسم المستخدم بهذا الاسم: -
يمكنك تحديد إعدادات الإدراج غير المتزامن باستخدام عبارة SETTINGS في استعلامات
INSERT: -
يمكنك أيضًا تحديد إعدادات الإدراج غير المتزامن كمعلمات اتصال عند استخدام عميل ClickHouse لإحدى لغات البرمجة.
على سبيل المثال، إليك كيفية تنفيذ ذلك ضمن سلسلة اتصال JDBC عند استخدام برنامج تشغيل ClickHouse Java JDBC للاتصال بـ ClickHouse Cloud:
يمكن أيضًا توجيه
INSERT ... SELECT عبر قائمة انتظار الإدراج غير المتزامن عندما يكون async_insert = 1 وتكون النتيجة بأكملها كتلة واحدة لا يتجاوز حجمها async_insert_max_data_size؛ وإلا فسيُنفَّذ بشكل متزامن. ويخضع هذا المسار لقواعد أهلية خاصة به، وله سلوكه الخاص في احتساب عمليات الكتابة وإلغائها. راجع عمليات INSERT ... SELECT غير المتزامنة للاطلاع على التفاصيل.تفريغ المخازن المؤقتة عند إيقاف التشغيل
async insert المؤقتة قيد الانتظار — على سبيل المثال، أثناء إيقاف تشغيلٍ منظّم أو قبل إجراء الصيانة — شغّل:
مقارنة مع جداول Buffer
- لا حاجة إلى أي تغييرات في DDL. تعمل عمليات الإدراج غير المتزامنة بشفافية — إذ تفعّل إعدادًا، ولا تنشئ جداول إضافية.
- التخزين المؤقت لكل بنية. تحتفظ عمليات الإدراج غير المتزامنة بمخازن مؤقتة منفصلة لكل بنية query فريدة ولكل مجموعة إعدادات، مما يتيح سياسات تفريغ دقيقة. أما جداول Buffer فتستخدم مخزنًا مؤقتًا واحدًا لكل table مستهدفة.
- الاستمرارية. في الوضع الافتراضي (
wait_for_async_insert=1)، يتم تأكيد البيانات على القرص قبل أن يتلقى العميل الإقرار. أما جداول Buffer فتعمل بأسلوب fire-and-forget — وتُفقد البيانات المخزنة مؤقتًا عند حدوث crash. - سلوك cluster. في clusters، تُدار مخازن عمليات الإدراج غير المتزامنة المؤقتة على مستوى كل node. وتتطلب جداول Buffer إنشاءها صراحةً على كل node.