> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> تمثل السجلات المُدرجة في جدول `QueryRunner` الاستعلامات التي ينفذها المحرك، سواءً محليًا أو على عنقود بعيد، في وضع "fire and forget".

# محرك الجدول QueryRunner

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

<div id="creating-a-table">
  ## إنشاء جدول
</div>

```sql theme={null}
CREATE TABLE runner
(
    query String,
    database String,
    settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
    cluster = 'cluster_name',
    shard = '1',
    mode = 'asynchronous',
    threads = 4,
    max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];
```

يجب إنشاء الجدول باستخدام مجموعة فرعية من الأعمدة المسموح بها: `query`، و`database`، و`settings`.
العمود `query` إلزامي، أما الأعمدة الأخرى فاختيارية.

| العمود     | النوع                 | المعنى                                                                                           |
| ---------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| `query`    | `String`              | الاستعلام المطلوب تنفيذه.                                                                        |
| `database` | `String`              | قاعدة البيانات الافتراضية للاستعلام. إذا كانت فارغة، فستُستخدم قاعدة البيانات الافتراضية للخادم. |
| `settings` | `Map(String, String)` | الإعدادات المُطبَّقة على الاستعلام.                                                              |

<div id="engine-settings">
  ## إعدادات المحرّك
</div>

| الإعداد          | القيمة الافتراضية | المعنى                                                                                                                                                                             |
| ---------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cluster`        | `''`              | اسم العنقود الذي تُرسَل إليه الاستعلامات. وإذا كان فارغًا، تُنفَّذ الاستعلامات محليًا.                                                                                             |
| `shard`          | `'1'`             | مؤشر يبدأ من 1 لجزء العنقود الذي تُرسَل إليه الاستعلامات، أو `'random'` لاختيار جزء عشوائي لكل استعلام، أو `'all'` لتشغيل كل استعلام على جميع الأجزاء. ويتطلب ذلك إعداد `cluster`. |
| `mode`           | `'asynchronous'`  | في وضع `synchronous`، تعود عملية INSERT بعد اكتمال جميع استعلامات الدفعة المُدرَجة. وفي وضع `asynchronous`، تعود عملية INSERT بمجرد إدراج الاستعلامات في قائمة الانتظار.           |
| `threads`        | `4`               | عدد الخيوط الخلفية التي تنفّذ الاستعلامات.                                                                                                                                         |
| `max_queue_size` | `1000`            | الحد الأقصى لعدد الاستعلامات في قائمة الانتظار. وعندما تمتلئ القائمة، تُهمَل الاستعلامات المُدرَجة حديثًا ويُسجَّل خطأ.                                                            |

<div id="details">
  ## التفاصيل
</div>

لا يسمح الجدول إلا باستعلامات `INSERT`.
تُنفَّذ الاستعلامات بأسلوب "fire and forget": ففي حال حدوث استثناء، لا تُجرى أي محاولات إعادة،
كما تُهمَل نتائج استعلامات `SELECT` (والطريقة الوحيدة للاحتفاظ بالنتائج هي `INSERT SELECT`).
ويمكن التحقق من نجاح كل استعلام في جدول `system.query_log`، حيث تُوسَم الاستعلامات التي يبدأها
هذا المحرك بالقيمة `is_internal = 1` على الخادم المُبادِر.

تُحفَظ الاستعلامات الموضوعة في قائمة الانتظار في الذاكرة، ولا تستمر بعد إعادة تشغيل الخادم. وعند إيقاف تشغيل الخادم
(أو تنفيذ `DROP`/`DETACH` للجدول)، تُهمَل الاستعلامات التي لم تبدأ بعد. أما من بين
الاستعلامات الجاري تنفيذها بالفعل، فتُلغى تلك المُرسَلة إلى عنقود، بينما يُنتظَر اكتمال تلك التي تعمل
محليًا حتى تنتهي.

عندما يكون الاستعلام المراد تشغيله هو نفسه `INSERT`، يجب أن تكون بياناته مضمّنة مباشرة — `INSERT ... VALUES (...)`،
أو `INSERT ... SELECT ...`، أو `INSERT ... FORMAT ...` مع وجود البيانات في نص الاستعلام. أما `INSERT` الذي
يتوقع بياناته من دفق منفصل فهو غير مدعوم.

<div id="local-mode-and-sql-security">
  ## الوضع المحلي وSQL SECURITY
</div>

من دون إعداد `cluster`، تُنفَّذ الاستعلامات على الخادم المحلي.
ويُحدَّد المستخدم الذي تُنفَّذ باسمه هذه الاستعلامات بواسطة بند `SQL SECURITY`:

* `INVOKER` (الافتراضي): تُنفَّذ الاستعلامات نيابةً عن المستخدم الذي نفّذ `INSERT`.
* `DEFINER`: تُنفَّذ الاستعلامات نيابةً عن مستخدم `DEFINER` المحدَّد. ونظرًا لأن الاستعلامات المُدرَجة قد تكون اعتباطية، فإن منح `INSERT` على جدول من هذا النوع يفوِّض جميع امتيازات هذا المستخدم.
* `NONE`: تُنفَّذ الاستعلامات بصلاحية وصول كاملة، من دون مستخدم. ويتطلب ذلك امتياز `ALLOW_SQL_SECURITY_NONE` عند إنشاء الجدول.

<div id="cluster-mode">
  ## وضع العنقود
</div>

عند تحديد إعداد `cluster`، تُرسَل الاستعلامات إلى العنقود المحدد.

يُحدَّد الجزء المستهدف بواسطة `shard`: إمّا فهرس ثابت يبدأ من 1 (`'1'` افتراضيًا)، أو `'random'` لاختيار
جزء عشوائي لكل استعلام، أو `'all'` لتشغيل كل استعلام على كل جزء في العنقود. وتُختار نسخة متماثلة داخل
الجزء وفقًا لإعداد `load_balancing` الخاص بالخادم.

يضبط العمود `database` قاعدة البيانات الافتراضية للاتصال بالخادم البعيد. وبما أن
قاعدة البيانات الافتراضية تُضبط مرة واحدة لكل اتصال، فإن كل قيمة `database` مختلفة تستخدم
مجموعة اتصالات خاصة بها، تُنشأ عند أول استخدام ويُعاد استخدامها طوال عمر الجدول.

لا يكون لـ `DEFINER` و `SQL SECURITY` تأثير إلا في الوضع المحلي، ويُعد الجمع بينهما وبين
إعداد `cluster` خطأً. وعلى الخوادم البعيدة، تُوثَّق الاستعلامات باستخدام
بيانات الاعتماد من إعدادات العنقود، وتُشغَّل كاستعلامات أولية عادية: وتُسجَّل في
`system.query_log` مع `is_initial_query = 1` ومعرّف `query_id` خاص بها (من دون ربطها بعملية INSERT التي
أنتجتها). وعلى الخادم البادئ، تُسجَّل الاستعلامات الموجَّهة في `system.query_log`
مع `is_internal = 1`.

ولأن المحرك يتجاهل نتائج الاستعلام، فإنه يشغّل دائمًا الاستعلامات الموجَّهة باستخدام
`discard_query_data = 1`، لذا لا تُنقَل بيانات نتائج استعلامات SELECT عبر الشبكة
(وهذا يتجاوز أي قيمة `discard_query_data` مُعيَّنة في العمود `settings`).

<div id="waiting-for-queries-to-finish">
  ## انتظار اكتمال الاستعلامات
</div>

في الوضع غير المتزامن، يمكن استخدام الاستعلام التالي للانتظار إلى أن يكتمل كل استعلام أُرسل إلى الجدول حتى الآن:

```sql theme={null}
SYSTEM WAIT QUERY RUNNER runner;
```

<div id="example">
  ## مثال
</div>

إعادة تنفيذ أحدث استعلامات `SELECT` من سجل الاستعلامات:

```sql theme={null}
INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
  AND event_time > now() - INTERVAL 1 HOUR;
```
