Skip to main content
لا يقتصر مسار قائمة انتظار الإدراج غير المتزامن على INSERT ... VALUES العادي، بل يمكن لـ INSERT ... SELECT أيضًا أن يسلكه. توضّح هذه الصفحة متى يحدث ذلك، وكيف يُحتسب جانب الكتابة، وما الذي يحدث عند إلغاء الاستعلام أو انتهاء مهلته.

الأهلية وتوجيه المسار

يسلك INSERT ... SELECT مسار قائمة الانتظار غير المتزامنة فقط عند استيفاء جميع الشروط التالية:
  • async_insert = 1.
  • async_insert_select_as_async_insert = 1 (القيمة الافتراضية). هذا هو مفتاح التحكم الرئيسي: عند تعطيله، يكون INSERT ... SELECT متزامنًا دائمًا بصرف النظر عن async_insert. يؤدي ضبط compatibility على إصدار يسبق 26.10 إلى تغيير قيمته الافتراضية إلى 0؛ ويمكن إعادة تفعيل هذا المسار بضبط async_insert_select_as_async_insert = 1 صراحةً.
  • تكون نتيجة SELECT بأكملها في كتلة واحدة لا يتجاوز حجمها async_insert_max_data_size.
  • تكون الوجهة جدولًا من عائلة MergeTree (ويُتتبَّع الاسم البديل إلى هدفه للتحقق من هذا الشرط).
حتى مع استيفاء جميع الشروط أعلاه، يتحوّل الإدراج إلى المسار المتزامن في أيٍّ من الحالات التالية:
  • تمتد النتيجة عبر أكثر من كتلة، أو يتجاوز حجمها async_insert_max_data_size، أو تكون فارغة.
  • يُستخدم نصاب غير متوازٍ: يكون insert_quorum مضبوطًا وinsert_quorum_parallel = 0.
  • توجد عروض مُجسَّدة تعتمد على الوجهة.
  • تكون الوجهة عرضًا مُجسَّدًا. ينطبق التحقق من MergeTree على العرض لا على جدول الهدف الخاص به، لذا لا يكون مؤهلًا.
  • تكون الوجهة دالة جدول، أو تستخدم محرك جدول بعيدًا مثل Distributed.
  • يقرأ SELECT من جدول الوجهة نفسه (INSERT INTO t SELECT ... FROM t).
  • يتعيّن على insert_null_as_default استبدال قيمة NULL بقيمة افتراضية عند تمرير عمود من النوع Nullable في SELECT إلى عمود هدف من نوع غير Nullable.
  • يكون الإدراج داخليًا (تحديث عرض مُجسَّد قابل للتحديث، أو POPULATE، أو CREATE TABLE ... AS SELECT). وتكون هذه العمليات متزامنة دائمًا، وتتجاهل async_insert_select_as_async_insert وasync_insert.
تختلف المعالجة في حالة المعاملات. فعندما يُنفَّذ الاستعلام داخل معاملة (سواء كانت صريحة أو مع implicit_transaction = 1)، لا يكون المسار غير المتزامن مدعومًا، ويرفع ClickHouse افتراضيًا الاستثناء NOT_IMPLEMENTED بدلًا من التحوّل إلى المسار المتزامن. ولا يتحوّل الاستعلام إلى الإدراج المتزامن إلا عند ضبط throw_on_unsupported_query_inside_transaction = 0. تكون الأولوية للمسار الذي يُحدَّد قبل الوصول إلى بوابة الإدراج غير المتزامن، لذا قد يستبعد جزء SELECT وحده المسار غير المتزامن. عند تفعيل parallel_distributed_insert_select (وهو مفعّل افتراضيًا)، فإن INSERT ... SELECT الذي يقرأ من مصدر على عنقود مثل s3Cluster ويُدرج في جدول متماثل يسلك مسار الإدراج الموزّع، ولا يصل أبدًا إلى قائمة الانتظار غير المتزامنة. وينطبق الأمر نفسه على النسخ المتماثلة المتوازية.

وضع الإرجاع والانتظار

يتصرف wait_for_async_insert كما في أي عملية إدراج غير متزامنة: تنتظر القيمة 1 (الافتراضية) اكتمال التفريغ؛ أما القيمة 0 فتتيح العودة فور إضافة الكتلة إلى قائمة الانتظار. لمساعدة استعلام SELECT على إنتاج الكتلة الواحدة التي يتطلبها المسار غير المتزامن، يحدّ optimize_trivial_insert_select استعلامًا بسيطًا من نمط INSERT INTO dest SELECT ... FROM source بين جدولين مختلفين بما لا يتجاوز max_insert_threads من خيوط القراءة. اضبط max_insert_threads = 1، وعندها ينتج استعلام SELECT عادةً كتلة واحدة.

احتساب عمليات الكتابة وإمكانية المراقبة

تُنسَب عمليات الكتابة إلى استعلام التفريغ، لا إلى استعلام INSERT ... SELECT الأصلي:
  • تُنسَب أحداث الكتابة في ProfileEvents ‏(InsertedRows، InsertedBytes) إلى استعلام التفريغ، ويكون له صف مستقل لعمليات الكتابة في system.query_log. أما صف استعلام INSERT ... SELECT الأصلي، فتظهر فيه القيمة 0 لهذين الحدثين في ProfileEvents. للاطلاع على أرقام الكتابة الخاصة بالتفريغ، راجع صف استعلام التفريغ في system.query_log وsystem.asynchronous_insert_log.
  • عند ضبط wait_for_async_insert = 1 (الإعداد الافتراضي)، تعرض قيمتا written_rows وwritten_bytes الخاصتان بالاستعلام (وكذلك ترويسة HTTP ‏X-ClickHouse-Summary) عدد الصفوف والبايتات المقبولة من SELECT، لا إجمالي ما كتبه استعلام التفريغ. وإذا فشل التفريغ، يُبلَّغ العميل بالخطأ.
  • عند ضبط wait_for_async_insert = 0، لا تُعرض هذه الأرقام، لأن الاستعلام يعيد نتيجته قبل توفّر نتيجة التفريغ.
  • تُحتسَب حصة WRITTEN_BYTES مرة واحدة أثناء التفريغ، ولا يُلغى احتسابها إذا فشل التفريغ.

الإلغاء وانتهاء المهلة

تُضاف الكتلة إلى قائمة الانتظار قبل بدء انتظار تفريغها، لذا فإن إلغاء الاستعلام ينهي انتظار العميل، لكنه لا يمنع تفريغ قائمة الانتظار.
  • يُرجع KILL QUERY، أو بلوغ max_execution_time أثناء الانتظار، رسالة خطأ إلى العميل، لكن قد تُكتب الصفوف رغم ذلك. لا تعتبر إلغاء استعلام أو انتهاء مهلته على هذا المسار دليلًا على عدم كتابة أي صفوف.
  • مع timeout_overflow_mode = 'break'، لا يحدث خطأ ولا ينتهي الاستعلام مبكرًا: يواصل الاستعلام انتظار التفريغ بعد تجاوز max_execution_time، حتى wait_for_async_insert_timeout. فالانتهاء مبكرًا سيُشير إلى نجاح العملية قبل تأكيد الكتابة.

متى تُحسم القرارات

تُحدَّد أهلية استخدام المسار غير المتزامن مرة واحدة عند بدء الاستعلام، قبل وضع الكتلة في قائمة الانتظار. ويتيح التحقق المسبق من أذونات الوصول رفض عمليات الإدراج غير المصرّح بها مبكرًا. أما سلوك INSERT ... SELECT المسار غير المتزامن أصلًا، فيعتمد على بنية الكتلة الناتجة، لا على async_insert وحده. ويُبحث عن الوجهة ويُتحقَّق من الأذونات عند الربط وقت التفريغ، كما يحدث مع أي عملية إدراج غير متزامنة: فإذا أُرفق عرض مُجسَّد بالوجهة أو أُلغيت أذونات بعد وضع العملية في قائمة الانتظار وقبل تفريغها، فإن ذلك يؤثر في عملية التفريغ.
آخر تعديل في ١٤ أكتوبر ٢٠٢٦