> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# النسخ المتماثلة المتوازية

> في هذا الدليل، سنناقش أولاً كيف يوزّع ClickHouse الاستعلام عبر عدة شظايا باستخدام الجداول الموزّعة، ثم كيف يمكن للاستعلام الاستفادة من عدة نُسخ متماثلة عند تنفيذه.

export const Image = ({img, alt, size}) => {
  return <Frame>
      <img src={img} alt={alt} />
    </Frame>;
};

<div id="introduction">
  ## المقدمة
</div>

يعالج ClickHouse الاستعلامات بسرعة فائقة، لكن كيف تُوزَّع هذه الاستعلامات
ويُنفَّذ تنفيذها بالتوازي عبر عدة خوادم؟

> في هذا الدليل، سنناقش أولًا كيف يوزّع ClickHouse الاستعلام عبر
> عدة شظايا من خلال الجداول الموزعة، ثم كيف يمكن للاستعلام أن يستفيد من
> عدة نُسخ متماثلة أثناء تنفيذه.

<div id="sharded-architecture">
  ## البنية المُجزّأة
</div>

في بنية shared-nothing، تُقسَّم العناقيد عادةً إلى
عدة شظايا، بحيث تحتوي كل شظية على مجموعة فرعية من إجمالي البيانات. ويعلو
هذه الشظايا جدول موزّع، يوفّر عرضًا موحّدًا
لكامل البيانات.

يمكن إرسال عمليات القراءة إلى الجدول المحلي. وفي هذه الحالة، لن يُنفَّذ الاستعلام إلا
على الشظية المحددة. أو يمكن إرساله إلى الجدول الموزّع، وعندها
ستنفّذ كل شظية الاستعلامات المطلوبة. وسيقوم الخادم الذي تم الاستعلام من خلاله عن
الجدول الموزّع بتجميع البيانات وإرجاع الرد إلى العميل:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-1.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=0eab55f5c61ab1fb82cf4c68d98de9b9" size="md" alt="البنية المُجزّأة" width="2914" height="1242" data-path="images/deployment-guides/parallel-replicas-1.png" />

يوضح الشكل أعلاه ما يحدث عندما يرسل عميل استعلامًا إلى جدول موزّع:

<ol className="docs-ordered-list">
  <li>
    يُرسل استعلام SELECT إلى جدول موزّع على إحدى العقد بشكل عشوائي
    (باستخدام استراتيجية التناوب أو بعد توجيهه إلى خادم محدد
    بواسطة موازن تحميل). وستعمل هذه العقدة الآن كمنسّق.
  </li>

  <li>
    ستحدّد العقدة كل شظية تحتاج إلى تنفيذ الاستعلام
    استنادًا إلى المعلومات التي يحددها الجدول الموزّع، ثم يُرسل الاستعلام
    إلى كل شظية.
  </li>

  <li>
    تقرأ كل شظية البيانات وتُرشّحها وتُجمّعها محليًا، ثم
    ترسل حالة قابلة للدمج إلى المنسّق.
  </li>

  <li>
    تدمج العقدة المنسِّقة البيانات ثم ترسل الاستجابة
    إلى العميل.
  </li>
</ol>

عند إضافة النسخ المتماثلة إلى هذا المزيج، تبقى العملية متشابهة إلى حد كبير، ويكمن
الفرق الوحيد في أن نسخة متماثلة واحدة فقط من كل شظية ستنفّذ الاستعلام.
وهذا يعني أنه يمكن بعد ذلك معالجة المزيد من الاستعلامات بالتوازي.

<div id="non-sharded-architecture">
  ## بنية غير مُشظّاة
</div>

تتمتع ClickHouse Cloud ببنية تختلف كثيرًا عن تلك المعروضة أعلاه.
(راجع ["بنية ClickHouse Cloud"](/ar/products/cloud/reference/architecture)
لمزيد من التفاصيل). ومع فصل المعالجة عن التخزين، ومع توفر مساحة تخزين
تكاد تكون غير محدودة، تصبح الحاجة إلى الشظايا أقل أهمية.

يوضح الشكل أدناه بنية ClickHouse Cloud:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-2.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=f7d4250c531013325e768d7077bbab11" size="md" alt="بنية غير مُشظّاة" width="2914" height="1241" data-path="images/deployment-guides/parallel-replicas-2.png" />

تتيح لنا هذه البنية إضافة النسخ المتماثلة وإزالتها بشكل شبه
فوري، مما يضمن قابلية توسع عالية جدًا للعنقود. ويضمن عنقود ClickHouse
Keeper (الموضح على اليمين) وجود مرجع وحيد موثوق
للبيانات الوصفية. ويمكن للنسخ المتماثلة جلب البيانات الوصفية من عنقود ClickHouse Keeper
مع احتفاظها جميعًا بالبيانات نفسها. أما البيانات نفسها فتُخزَّن في
التخزين الكائني، وتتيح لنا ذاكرة التخزين المؤقت على SSD تسريع الاستعلامات.

لكن كيف يمكننا الآن توزيع تنفيذ الاستعلامات عبر عدة خوادم؟ في بنية
مُشظّاة، كان ذلك واضحًا إلى حد ما لأن كل شظية كان يستطيع بالفعل
تنفيذ استعلام على مجموعة فرعية من البيانات. فكيف يعمل ذلك عندما لا توجد شظايا؟

<div id="introducing-parallel-replicas">
  ## تقديم النسخ المتماثلة المتوازية
</div>

لموازاة تنفيذ الاستعلام عبر عدة خوادم، نحتاج أولًا إلى
القدرة على تعيين أحد خوادمنا بصفته منسّقًا. والمنسّق هو
العقدة التي تنشئ قائمة المهام التي يجب تنفيذها، وتضمن تنفيذها جميعًا،
وتجميع نتائجها وإرجاعها إلى العميل. وكما هو الحال
في معظم الأنظمة الموزعة، يكون هذا دور العقدة التي تستقبل
الاستعلام الأولي. ونحتاج أيضًا إلى تحديد وحدة العمل. في
بنية تعتمد على الشظايا، تكون وحدة العمل هي الـشظية، أي مجموعة فرعية من البيانات. ومع النسخ المتماثلة المتوازية
سنستخدم جزءًا صغيرًا من الجدول، يُسمى [الحبيبات](/ar/guides/clickhouse/data-modelling/sparse-primary-indexes#data-is-organized-into-granules-for-parallel-data-processing)،
بوصفه وحدة العمل.

والآن، لنرَ كيف يعمل ذلك عمليًا بمساعدة الشكل أدناه:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-3.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=96c38584a90648885b08f58c565fc4b6" size="md" alt="النسخ المتماثلة المتوازية" width="2915" height="1169" data-path="images/deployment-guides/parallel-replicas-3.png" />

مع النسخ المتماثلة المتوازية:

<ol className="docs-ordered-list">
  <li>
    يُرسَل الاستعلام من العميل إلى عقدة واحدة بعد مروره عبر
    موازن تحميل. وتصبح هذه العقدة المنسّق لهذا الاستعلام.
  </li>

  <li>
    تحلّل العقدة فهرس كل جزء، وتحدّد الأجزاء
    والحبيبات المناسبة للمعالجة.
  </li>

  <li>
    يقسّم المنسّق عبء العمل إلى مجموعة من الحبيبات التي يمكن
    إسنادها إلى نسخ متماثلة مختلفة.
  </li>

  <li>
    تُعالَج كل مجموعة من الحبيبات بواسطة النسخ المتماثلة المقابلة لها، وتُرسَل
    حالة قابلة للدمج إلى المنسّق عند الانتهاء.
  </li>

  <li>
    أخيرًا، يدمج المنسّق جميع نتائج النسخ المتماثلة
    ثم يعيد النتيجة إلى العميل.
  </li>
</ol>

توضّح الخطوات أعلاه كيفية عمل النسخ المتماثلة المتوازية من الناحية النظرية.
ومع ذلك، عمليًا، هناك كثير من العوامل التي قد تمنع هذه الآلية
من العمل على نحو مثالي:

<ol className="docs-ordered-list">
  <li>
    قد تكون بعض النسخ المتماثلة غير متاحة.
  </li>

  <li>
    تكون آلية النسخ المتماثل في ClickHouse غير متزامنة، وقد لا
    تحتوي بعض النسخ المتماثلة على الأجزاء نفسها في لحظة معينة.
  </li>

  <li>
    يجب التعامل مع كمون الذيل بين النسخ المتماثلة.
  </li>

  <li>
    تختلف ذاكرة التخزين المؤقت لنظام الملفات من نسخة متماثلة إلى أخرى بحسب
    النشاط على كل نسخة متماثلة، ما يعني أن إسناد المهام عشوائيًا قد
    يؤدي إلى أداء أقل كفاءة نظرًا إلى محلية ذاكرة التخزين المؤقت.
  </li>
</ol>

نستعرض في الأقسام التالية كيفية تجاوز هذه العوامل.

<div id="announcements">
  ### الإعلانات
</div>

لمعالجة (1) و(2) من القائمة أعلاه، قدّمنا مفهوم
الإعلان. لنتصوّر كيف يعمل ذلك باستخدام الشكل أدناه:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-4.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=0f798358f4bf78039a88c8eb1f58c32e" size="md" alt="الإعلانات" width="2916" height="1248" data-path="images/deployment-guides/parallel-replicas-4.png" />

<ol className="docs-ordered-list">
  <li>
    يُرسَل الاستعلام من العميل إلى إحدى العُقد بعد مروره عبر
    موازن التحميل. وتصبح هذه العقدة المنسّق لهذا الاستعلام.
  </li>

  <li>
    ترسل العقدة المنسِّقة طلبًا للحصول على إعلانات من
    جميع النسخ المتماثلة في العنقود. وقد تكون لدى النسخ المتماثلة
    تصوّرات مختلفة قليلًا عن المجموعة الحالية من الأجزاء في جدولٍ ما. لذلك نحتاج إلى
    جمع هذه المعلومات لتجنّب اتخاذ قرارات جدولة غير صحيحة.
  </li>

  <li>
    تستخدم العقدة المنسِّقة بعد ذلك الإعلانات لتحديد مجموعة من
    الحبيبات التي يمكن إسنادها إلى النسخ المتماثلة المختلفة. هنا، على سبيل المثال،
    نرى أنه لم تُسنَد أي حبيبات من الجزء 3 إلى النسخة المتماثلة 2
    لأن هذه النسخة المتماثلة لم تُدرِج هذا الجزء في إعلانها.
    ولاحظ أيضًا أنه لم تُسنَد أي مهام إلى النسخة المتماثلة 3 لأن
    هذه النسخة لم تقدّم إعلانًا.
  </li>

  <li>
    بعد أن تعالج كل نسخة متماثلة الاستعلام على مجموعتها الفرعية من الحبيبات
    وتُرسَل الحالة القابلة للدمج مرة أخرى إلى المنسّق،
    يدمج المنسّق النتائج ثم يُرسَل الرد إلى العميل.
  </li>
</ol>

<div id="dynamic-coordination">
  ### التنسيق الديناميكي
</div>

لمعالجة مشكلة كمون الذيل، أضفنا التنسيق الديناميكي. ويعني ذلك
أن الحبيبات لا تُرسَل كلها إلى نسخة متماثلة ضمن طلب واحد، بل تتمكن كل نسخة متماثلة
من طلب مهمة جديدة (أي مجموعة من الحبيبات المطلوب معالجتها) من
المنسّق. ويزوّد المنسّق النسخة المتماثلة بمجموعة الحبيبات بناءً على
الإعلان الذي تلقّاه.

لنفترض أننا وصلنا إلى مرحلة من العملية تكون فيها جميع النسخ المتماثلة قد أرسلت
إعلانًا يتضمن جميع الأجزاء.

يوضّح الشكل أدناه كيفية عمل التنسيق الديناميكي:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-5.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=ab440e051552836e9f49d806758f5003" size="md" alt="التنسيق الديناميكي - الجزء 1" width="2915" height="1060" data-path="images/deployment-guides/parallel-replicas-5.png" />

<ol className="docs-ordered-list">
  <li>
    تُبلغ النسخ المتماثلة عقدة المنسّق بأنها قادرة على معالجة
    المهام، ويمكنها أيضًا تحديد مقدار العمل الذي تستطيع معالجته.
  </li>

  <li>
    يوزّع المنسّق المهام على النسخ المتماثلة.
  </li>
</ol>

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-6.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=000b9c024c8e1f339e2d4f1f1af812b7" size="md" alt="التنسيق الديناميكي - الجزء 2" width="2915" height="1125" data-path="images/deployment-guides/parallel-replicas-6.png" />

<ol className="docs-ordered-list">
  <li>
    تتمكن النسختان المتماثلتان 1 و2 من إنهاء مهمتهما بسرعة كبيرة، لذا
    تطلبان مهمة أخرى من عقدة المنسّق.
  </li>

  <li>
    يوزّع المنسّق مهامًا جديدة على النسختين المتماثلتين 1 و2.
  </li>
</ol>

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-7.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=975447109d7acb0b1fbbe03dc7f10675" size="md" alt="التنسيق الديناميكي - الجزء 3" width="2916" height="1248" data-path="images/deployment-guides/parallel-replicas-7.png" />

<ol className="docs-ordered-list">
  <li>
    تكون جميع النسخ المتماثلة قد انتهت الآن من معالجة مهامها.
    وتطلب المزيد من المهام.
  </li>

  <li>
    يتحقق المنسّق، باستخدام الإعلانات، من المهام التي لا تزال
    بحاجة إلى معالجة، لكنه لا يجد أي مهام متبقية.
  </li>

  <li>
    يُبلغ المنسّق النسخ المتماثلة بأن كل شيء قد تمت معالجته.
    وسيقوم الآن بدمج جميع الحالات القابلة للدمج والرد على الاستعلام.
  </li>
</ol>

<div id="managing-cache-locality">
  ### إدارة محلية ذاكرة التخزين المؤقت
</div>

آخر مشكلة محتملة متبقية هي كيفية التعامل مع محلية ذاكرة التخزين المؤقت. إذا نُفِّذ الاستعلام
عدة مرات، فكيف نضمن توجيه المهمة نفسها إلى
النسخة المتماثلة نفسها؟ في المثال السابق، كانت المهام موزعة على النحو التالي:

<table>
  <thead>
    <tr>
      <th />

      <th>النسخة المتماثلة 1</th>
      <th>النسخة المتماثلة 2</th>
      <th>النسخة المتماثلة 3</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>الجزء 1</td>
      <td>g1, g6, g7</td>
      <td>g2, g4, g5</td>
      <td>g3</td>
    </tr>

    <tr>
      <td>الجزء 2</td>
      <td>g1</td>
      <td>g2, g4, g5</td>
      <td>g3</td>
    </tr>

    <tr>
      <td>الجزء 3</td>
      <td>g1, g6</td>
      <td>g2, g4, g5</td>
      <td>g3</td>
    </tr>
  </tbody>
</table>

ولضمان إسناد المهام نفسها إلى النسخ المتماثلة نفسها بحيث
تستفيد من ذاكرة التخزين المؤقت، يحدث أمران. أولًا، تُحتسب قيمة hash للجزء + مجموعة
الحبيبات (أي المهمة). ثانيًا، يُطبَّق باقي قسمة عدد النسخ المتماثلة
لتحديد إسناد المهمة.

نظريًا يبدو هذا جيدًا، لكن عمليًا قد يتسبب حمل مفاجئ على إحدى النسخ المتماثلة، أو
تدهور في الشبكة، في زيادة زمن الاستجابة عند الذيل إذا استُخدمت النسخة المتماثلة نفسها
باستمرار لتنفيذ مهام معينة. إذا كانت قيمة `max_parallel_replicas` أقل
من عدد النسخ المتماثلة، فستُختار نسخ متماثلة عشوائية لتنفيذ الاستعلام.

<div id="task-stealing">
  ### استيلاء المهام
</div>

إذا كانت إحدى النسخ المتماثلة تعالج المهام أبطأ من غيرها، فستحاول النسخ الأخرى
'الاستيلاء' على المهام التي تكون مخصّصةً مبدئيًا لتلك النسخة المتماثلة وفقًا لـ hash، وذلك لتقليل
كمون الذيل.

<div id="limitations">
  ### القيود
</div>

لهذه الميزة قيود معروفة، وقد وُثِّقت أهمها في
هذا القسم.

<Note>
  إذا صادفت مشكلة لا تندرج ضمن القيود المذكورة أدناه،
  وتشتبه في أن النسخة المتماثلة المتوازية هي السبب، يُرجى فتح issue على GitHub باستخدام
  الوسم `comp-parallel-replicas`.
</Note>

| القيد                                                  | الوصف                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| الاستعلامات المعقدة                                    | تعمل النسخ المتماثلة المتوازية حاليًا بشكل جيد إلى حدٍّ ما مع الاستعلامات البسيطة. ويمكن أن تؤثر عناصر التعقيد مثل CTEs و`subqueries` وJOINs والاستعلامات غير المسطّحة وغيرها سلبًا في أداء الاستعلام.                                                                                                                                                                                                            |
| الاستعلامات الصغيرة                                    | إذا كنت تنفّذ استعلامًا لا يعالج عددًا كبيرًا من الصفوف، فقد لا يؤدي تشغيله على عدة نُسخ متماثلة إلى تحسين زمن التنفيذ، لأن زمن الشبكة اللازم للتنسيق بين النُسخ المتماثلة قد يضيف دورات إضافية إلى تنفيذ الاستعلام. يمكنك الحد من هذه المشكلات باستخدام الإعداد: [`parallel_replicas_min_number_of_rows_per_replica`](/ar/reference/settings/session-settings#parallel_replicas_min_number_of_rows_per_replica). |
| تُعطَّل النسخ المتماثلة المتوازية مع FINAL             |                                                                                                                                                                                                                                                                                                                                                                                                                   |
| لا تُستخدم الإسقاطات مع النسخ المتماثلة المتوازية معًا |                                                                                                                                                                                                                                                                                                                                                                                                                   |
| البيانات عالية التفرّد والتجميع المعقّد                | قد يؤدي التجميع عالي التفرّد الذي يتطلب إرسال كمية كبيرة من البيانات إلى إبطاء استعلاماتك بشكل ملحوظ.                                                                                                                                                                                                                                                                                                             |
| التوافق مع المحلّل الجديد                              | قد يؤدي المحلّل الجديد إلى إبطاء تنفيذ الاستعلام أو تسريعه بشكل ملحوظ في سيناريوهات محددة.                                                                                                                                                                                                                                                                                                                        |

<div id="settings-related-to-parallel-replicas">
  ## الإعدادات المتعلقة بالنسخ المتماثلة المتوازية
</div>

| Setting                                            | Description                                                                                                                                                                                                                               |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enable_parallel_replicas`                         | `0`: معطّل<br /> `1`: مفعّل <br />`2`: فرض استخدام النسخة المتماثلة المتوازية، وسيُطلق استثناء إذا لم تُستخدم.                                                                                                                            |
| `cluster_for_parallel_replicas`                    | اسم العنقود المُستخدَم للنسخ المتماثل المتوازي؛ وإذا كنت تستخدم ClickHouse Cloud، فاستخدم `default`.                                                                                                                                      |
| `max_parallel_replicas`                            | الحد الأقصى لعدد النسخ المتماثلة المستخدمة في تنفيذ الاستعلام عبر عدة نسخ متماثلة. وإذا تم تحديد عدد أقل من عدد النسخ المتماثلة في العنقود، فسيتم اختيار العُقد عشوائيًا. ويمكن أيضًا الإفراط في تخصيص هذه القيمة لمراعاة التوسّع الأفقي. |
| `parallel_replicas_min_number_of_rows_per_replica` | يساعد في تقييد عدد النسخ المتماثلة المستخدمة بناءً على عدد الصفوف المطلوب معالجتها. ويُحدَّد عدد النسخ المتماثلة المستخدمة وفقًا لما يلي: <br /> `estimated rows to read` / `min_number_of_rows_per_replica`.                             |
| `enable_analyzer`                                  | لا يُدعَم تنفيذ الاستعلام باستخدام النسخ المتماثلة المتوازية إلا عند تفعيل المُحلِّل                                                                                                                                                      |

<div id="investigating-issues-with-parallel-replicas">
  ## استقصاء المشكلات المتعلقة بالنسخ المتماثلة المتوازية
</div>

يمكنك التحقق من الإعدادات المستخدمة لكل query في
جدول [`system.query_log`](/ar/reference/system-tables/query_log). ويمكنك
أيضًا الاطلاع على جدول [`system.events`](/ar/reference/system-tables/events)
لرؤية جميع الأحداث التي حدثت على الخادم، كما يمكنك استخدام
table function [`clusterAllReplicas`](/ar/reference/functions/table-functions/cluster) لرؤية الجداول على جميع النسخ المتماثلة
(إذا كنت من مستخدمي Cloud، فاستخدم `default`).

```sql title="Query" theme={null}
SELECT
   hostname(),
   *
FROM clusterAllReplicas('default', system.events)
WHERE event ILIKE '%ParallelReplicas%'
```

<Accordion title="الاستجابة">
  ```response title="Response" theme={null}
  ┌─hostname()───────────────────────┬─event──────────────────────────────────────────┬─value─┬─description──────────────────────────────────────────────────────────────────────────────────────────┐
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasHandleRequestMicroseconds      │   438 │ Time spent processing requests for marks from replicas                                               │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasHandleAnnouncementMicroseconds │   558 │ Time spent processing replicas announcements                                                         │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasReadUnassignedMarks            │   240 │ Sum across all replicas of how many unassigned marks were scheduled                                  │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasReadAssignedForStealingMarks   │     4 │ Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasStealingByHashMicroseconds     │     5 │ Time spent collecting segments meant for stealing by hash                                            │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasProcessingPartsMicroseconds    │     5 │ Time spent processing data parts                                                                     │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasStealingLeftoversMicroseconds  │     3 │ Time spent collecting orphaned segments                                                              │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasUsedCount                      │     2 │ Number of replicas used to execute a query with task-based parallel replicas                         │
  │ c-crimson-vd-86-server-rdhnsx3-0 │ ParallelReplicasAvailableCount                 │     6 │ Number of replicas available to execute a query with task-based parallel replicas                    │
  └──────────────────────────────────┴────────────────────────────────────────────────┴───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘
  ┌─hostname()───────────────────────┬─event──────────────────────────────────────────┬─value─┬─description──────────────────────────────────────────────────────────────────────────────────────────┐
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasHandleRequestMicroseconds      │   698 │ Time spent processing requests for marks from replicas                                               │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasHandleAnnouncementMicroseconds │   644 │ Time spent processing replicas announcements                                                         │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasReadUnassignedMarks            │   190 │ Sum across all replicas of how many unassigned marks were scheduled                                  │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasReadAssignedForStealingMarks   │    54 │ Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasStealingByHashMicroseconds     │     8 │ Time spent collecting segments meant for stealing by hash                                            │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasProcessingPartsMicroseconds    │     4 │ Time spent processing data parts                                                                     │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasStealingLeftoversMicroseconds  │     2 │ Time spent collecting orphaned segments                                                              │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasUsedCount                      │     2 │ Number of replicas used to execute a query with task-based parallel replicas                         │
  │ c-crimson-vd-86-server-e9kp5f0-0 │ ParallelReplicasAvailableCount                 │     6 │ Number of replicas available to execute a query with task-based parallel replicas                    │
  └──────────────────────────────────┴────────────────────────────────────────────────┴───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘
  ┌─hostname()───────────────────────┬─event──────────────────────────────────────────┬─value─┬─description──────────────────────────────────────────────────────────────────────────────────────────┐
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasHandleRequestMicroseconds      │   620 │ Time spent processing requests for marks from replicas                                               │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasHandleAnnouncementMicroseconds │   656 │ Time spent processing replicas announcements                                                         │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasReadUnassignedMarks            │     1 │ Sum across all replicas of how many unassigned marks were scheduled                                  │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasReadAssignedForStealingMarks   │     1 │ Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasStealingByHashMicroseconds     │     4 │ Time spent collecting segments meant for stealing by hash                                            │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasProcessingPartsMicroseconds    │     3 │ Time spent processing data parts                                                                     │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasStealingLeftoversMicroseconds  │     1 │ Time spent collecting orphaned segments                                                              │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasUsedCount                      │     2 │ Number of replicas used to execute a query with task-based parallel replicas                         │
  │ c-crimson-vd-86-server-ybtm18n-0 │ ParallelReplicasAvailableCount                 │    12 │ Number of replicas available to execute a query with task-based parallel replicas                    │
  └──────────────────────────────────┴────────────────────────────────────────────────┴───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘
  ┌─hostname()───────────────────────┬─event──────────────────────────────────────────┬─value─┬─description──────────────────────────────────────────────────────────────────────────────────────────┐
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasHandleRequestMicroseconds      │   696 │ Time spent processing requests for marks from replicas                                               │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasHandleAnnouncementMicroseconds │   717 │ Time spent processing replicas announcements                                                         │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasReadUnassignedMarks            │     2 │ Sum across all replicas of how many unassigned marks were scheduled                                  │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasReadAssignedForStealingMarks   │     2 │ Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasStealingByHashMicroseconds     │    10 │ Time spent collecting segments meant for stealing by hash                                            │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasProcessingPartsMicroseconds    │     6 │ Time spent processing data parts                                                                     │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasStealingLeftoversMicroseconds  │     2 │ Time spent collecting orphaned segments                                                              │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasUsedCount                      │     2 │ Number of replicas used to execute a query with task-based parallel replicas                         │
  │ c-crimson-vd-86-server-16j1ncj-0 │ ParallelReplicasAvailableCount                 │    12 │ Number of replicas available to execute a query with task-based parallel replicas                    │
  └──────────────────────────────────┴────────────────────────────────────────────────┴───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘
  ```
</Accordion>

يتضمن جدول [`system.text_log`](/ar/reference/system-tables/text_log) أيضًا
معلومات عن تنفيذ الاستعلامات باستخدام النسخ المتماثلة المتوازية:

```sql title="Query" theme={null}
SELECT message
FROM clusterAllReplicas('default', system.text_log)
WHERE query_id = 'ad40c712-d25d-45c4-b1a1-a28ba8d4019c'
ORDER BY event_time_microseconds ASC
```

<Accordion title="الاستجابة">
  ```response title="Response" theme={null}
  ┌─message────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ (from 54.218.178.249:59198) SELECT * FROM session_events WHERE type='type2' LIMIT 10 SETTINGS allow_experimental_parallel_reading_from_replicas=2; (stage: Complete)                                                                                       │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') SETTINGS allow_experimental_parallel_reading_from_replicas = 2 to stage Complete │
  │ Access granted: SELECT(clientId, sessionId, pageId, timestamp, type) ON default.session_events                                                                                                                                                             │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') to stage WithMergeableState only analyze │
  │ Access granted: SELECT(clientId, sessionId, pageId, timestamp, type) ON default.session_events                                                                                                                                                             │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') from stage FetchColumns to stage WithMergeableState only analyze │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') SETTINGS allow_experimental_parallel_reading_from_replicas = 2 to stage WithMergeableState only analyze │
  │ Access granted: SELECT(clientId, sessionId, pageId, timestamp, type) ON default.session_events                                                                                                                                                             │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') SETTINGS allow_experimental_parallel_reading_from_replicas = 2 from stage FetchColumns to stage WithMergeableState only analyze │
  │ Query SELECT __table1.clientId AS clientId, __table1.sessionId AS sessionId, __table1.pageId AS pageId, __table1.timestamp AS timestamp, __table1.type AS type FROM default.session_events AS __table1 WHERE __table1.type = 'type2' LIMIT _CAST(10, 'UInt64') SETTINGS allow_experimental_parallel_reading_from_replicas = 2 from stage WithMergeableState to stage Complete │
  │ The number of replicas requested (100) is bigger than the real number available in the cluster (6). Will use the latter number to execute the query.                                                                                                       │
  │ Initial request from replica 4: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 4 replica
                                                                                                     │
  │ Reading state is fully initialized: part all_0_2_1 with ranges [(0, 182)] in replicas [4]; part all_3_3_0 with ranges [(0, 62)] in replicas [4]                                                                                                            │
  │ Sent initial requests: 1 Replicas count: 6                                                                                                                                                                                                                 │
  │ Initial request from replica 2: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 2 replica
                                                                                                     │
  │ Sent initial requests: 2 Replicas count: 6                                                                                                                                                                                                                 │
  │ Handling request from replica 4, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 4 with 1 parts: [part all_0_2_1 with ranges [(128, 182)]]. Finish: false; mine_marks=0, stolen_by_hash=54, stolen_rest=0                                                                                                       │
  │ Initial request from replica 1: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 1 replica
                                                                                                     │
  │ Sent initial requests: 3 Replicas count: 6                                                                                                                                                                                                                 │
  │ Handling request from replica 4, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 4 with 2 parts: [part all_0_2_1 with ranges [(0, 128)], part all_3_3_0 with ranges [(0, 62)]]. Finish: false; mine_marks=0, stolen_by_hash=0, stolen_rest=190                                                                  │
  │ Initial request from replica 0: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 0 replica
                                                                                                     │
  │ Sent initial requests: 4 Replicas count: 6                                                                                                                                                                                                                 │
  │ Initial request from replica 5: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 5 replica
                                                                                                     │
  │ Sent initial requests: 5 Replicas count: 6                                                                                                                                                                                                                 │
  │ Handling request from replica 2, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 2 with 0 parts: []. Finish: true; mine_marks=0, stolen_by_hash=0, stolen_rest=0                                                                                                                                                │
  │ Initial request from replica 3: 2 parts: [part all_0_2_1 with ranges [(0, 182)], part all_3_3_0 with ranges [(0, 62)]]----------
  Received from 3 replica
                                                                                                     │
  │ Sent initial requests: 6 Replicas count: 6                                                                                                                                                                                                                 │
  │ Total rows to read: 2000000                                                                                                                                                                                                                                │
  │ Handling request from replica 5, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 5 with 0 parts: []. Finish: true; mine_marks=0, stolen_by_hash=0, stolen_rest=0                                                                                                                                                │
  │ Handling request from replica 0, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 0 with 0 parts: []. Finish: true; mine_marks=0, stolen_by_hash=0, stolen_rest=0                                                                                                                                                │
  │ Handling request from replica 1, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 1 with 0 parts: []. Finish: true; mine_marks=0, stolen_by_hash=0, stolen_rest=0                                                                                                                                                │
  │ Handling request from replica 3, minimal marks size is 240                                                                                                                                                                                                 │
  │ Going to respond to replica 3 with 0 parts: []. Finish: true; mine_marks=0, stolen_by_hash=0, stolen_rest=0                                                                                                                                                │
  │ (c-crimson-vd-86-server-rdhnsx3-0.c-crimson-vd-86-server-headless.ns-crimson-vd-86.svc.cluster.local:9000) Cancelling query because enough data has been read                                                                                              │
  │ Read 81920 rows, 5.16 MiB in 0.013166 sec., 6222087.194288318 rows/sec., 391.63 MiB/sec.                                                                                                                                                                   │
  │ Coordination done: Statistics: replica 0 - {requests: 2 marks: 0 assigned_to_me: 0 stolen_by_hash: 0 stolen_unassigned: 0}; replica 1 - {requests: 2 marks: 0 assigned_to_me: 0 stolen_by_hash: 0 stolen_unassigned: 0}; replica 2 - {requests: 2 marks: 0 assigned_to_me: 0 stolen_by_hash: 0 stolen_unassigned: 0}; replica 3 - {requests: 2 marks: 0 assigned_to_me: 0 stolen_by_hash: 0 stolen_unassigned: 0}; replica 4 - {requests: 3 marks: 244 assigned_to_me: 0 stolen_by_hash: 54 stolen_unassigned: 190}; replica 5 - {requests: 2 marks: 0 assigned_to_me: 0 stolen_by_hash: 0 stolen_unassigned: 0} │
  │ Peak memory usage (for query): 1.81 MiB.                                                                                                                                                                                                                   │
  │ Processed in 0.024095586 sec.                                                                                                                                                                                                                              │
  └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  ```
</Accordion>

أخيرًا، يمكنك أيضًا استخدام `EXPLAIN PIPELINE`. يوضّح هذا كيف سيُنفِّذ ClickHouse
الاستعلام والموارد التي سيستخدمها في
تنفيذه. لنأخذ الاستعلام التالي مثالًا:

```sql theme={null}
SELECT count(), uniq(pageId) , min(timestamp), max(timestamp) 
FROM session_events 
WHERE type='type3' 
GROUP BY toYear(timestamp) LIMIT 10
```

لنلقِ نظرة على مسار تنفيذ الاستعلام بدون استخدام parallel replica:

```sql title="EXPLAIN PIPELINE (without parallel replica)" theme={null}
EXPLAIN PIPELINE graph = 1, compact = 0 
SELECT count(), uniq(pageId) , min(timestamp), max(timestamp) 
FROM session_events 
WHERE type='type3' 
GROUP BY toYear(timestamp) 
LIMIT 10 
SETTINGS allow_experimental_parallel_reading_from_replicas=0 
FORMAT TSV;
```

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-8.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=d7e5483910e540167274a4575b7559d1" size="lg" alt="EXPLAIN بدون parallel_replica" width="869" height="159" data-path="images/deployment-guides/parallel-replicas-8.png" />

والآن مع النسخ المتماثلة المتوازية:

```sql title="EXPLAIN PIPELINE (with parallel replica)" theme={null}
EXPLAIN PIPELINE graph = 1, compact = 0 
SELECT count(), uniq(pageId) , min(timestamp), max(timestamp) 
FROM session_events 
WHERE type='type3' 
GROUP BY toYear(timestamp) 
LIMIT 10 
SETTINGS allow_experimental_parallel_reading_from_replicas=2 
FORMAT TSV;
```

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-fbfa8bee/qvDh3oxLPI7c74wx/images/deployment-guides/parallel-replicas-9.png?fit=max&auto=format&n=qvDh3oxLPI7c74wx&q=85&s=701d14edbb0cdf63c673385bd08b0fba" size="lg" alt="EXPLAIN باستخدام parallel_replica" width="868" height="219" data-path="images/deployment-guides/parallel-replicas-9.png" />
