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

> محرك الجدول يُخزّن سلاسل زمنية، أي مجموعة من القيم المرتبطة بالطوابع الزمنية والوسوم (أو التسميات).

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

export const PrivatePreviewBadge = () => {
  return <div className="privatePreviewBadge">
            <div className="privatePreviewIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M5.33301 6.66667V4.66667V4.66667C5.33301 3.194 6.52701 2 7.99967 2V2C9.47234 2 10.6663 3.194 10.6663 4.66667V4.66667V6.66667" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path d="M8.00033 9.33337V11.3334" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path fillRule="evenodd" clipRule="evenodd" d="M11.333 14H4.66634C3.92967 14 3.33301 13.4033 3.33301 12.6666V7.99996C3.33301 7.26329 3.92967 6.66663 4.66634 6.66663H11.333C12.0697 6.66663 12.6663 7.26329 12.6663 7.99996V12.6666C12.6663 13.4033 12.0697 14 11.333 14Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            {'معاينة خاصة'}
        </div>;
};

<PrivatePreviewBadge />

محرك الجدول يخزّن سلسلة زمنية، أي مجموعة من القيم المرتبطة بطوابع زمنية ووسوم (أو تسميات):

```sql theme={null}
metric_name1[tag1=value1, tag2=value2, ...] = {timestamp1: value1, timestamp2: value2, ...}
metric_name2[...] = ...
```

<Info>
  هذه ميزة في private preview، وقد تتغير مستقبلًا على نحو غير متوافق مع الإصدارات السابقة.
  فعِّل استخدام محرك الجدول TimeSeries
  باستخدام الإعداد `enable_time_series_table`.
  أدخِل الأمر `set enable_time_series_table = 1`.
</Info>

<Note>
  محرك الجدول `TimeSeries` متاح في ClickHouse Cloud كميزة في private preview.
  الخدمات المشارِكة في private preview لديها بالفعل الإعداد
  `enable_time_series_table` مهيَّأً. أما خدمات ClickHouse Cloud الأخرى
  فلا تتوفر لديها هذه التهيئة، ولا يمكنك تفعيل المحرك بنفسك على
  مثل هذه الخدمة.
</Note>

## الصياغة

```sql theme={null}
CREATE TABLE name [(columns)] ENGINE=TimeSeries
[SETTINGS var1=value1, ...]
[SAMPLES db.samples_table_name | [SAMPLES INNER COLUMNS (...)] [SAMPLES INNER ENGINE engine(arguments)]]
[RECENT SAMPLES db.recent_samples_table_name | [RECENT SAMPLES INNER COLUMNS (...)] [RECENT SAMPLES INNER ENGINE engine(arguments)]]
[TAGS db.tags_table_name | [TAGS INNER COLUMNS (...)] [TAGS INNER ENGINE engine(arguments)]]
[METRIC FAMILIES db.metric_families_table_name | [METRIC FAMILIES INNER COLUMNS (...)] [METRIC FAMILIES INNER ENGINE engine(arguments)]]
```

<Note>
  للكلمة المفتاحية `SAMPLES` اسم مستعار هو `DATA`، وللكلمة المفتاحية `METRIC FAMILIES` اسم مستعار هو `METRICS`، وقد أُبقي على كليهما للحفاظ على التوافق مع الإصدارات السابقة.
  يُكتب تعريف الجدول الخاص بأي [version](#schema-versioning) أقدم من 4 باستخدام `METRICS`، حتى يتمكن خادم أقدم من قراءته.
</Note>

## الاستخدام

من الأسهل البدء بالإعدادات الافتراضية لكل شيء (يُسمح بإنشاء جدول `TimeSeries` من دون تحديد قائمة بالأعمدة):

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
```

بعد ذلك، يمكن استخدام هذا الجدول مع البروتوكولات التالية (يجب تعيين منفذ في تهيئة الخادم):

* [prometheus remote-write](/ar/concepts/features/interfaces/prometheus#remote-write)
* [prometheus remote-read](/ar/concepts/features/interfaces/prometheus#remote-read)

### الأعمدة الخارجية

تُنشأ أعمدة جدول TimeSeries تلقائيًا. وهذه هي الأعمدة الخارجية؛ فهي لا تخزّن أي بيانات، وإنما توفّر فقط واجهة لـ SELECT/INSERT. وتُخزَّن البيانات الفعلية في [الجداول الهدف](#target-tables). وفيما يلي قائمة الأعمدة الخارجية:

| Name | Type | Description |
| - | - | - |
| `metric_name` | `String` | اسم المقياس |
| `tags` | `Map(String, String)` | خريطة الوسوم (التسميات) للسلسلة الزمنية |
| `samples` | `Array(Tuple(DateTime64(3), Float64))` افتراضيًا | مصفوفة من أزواج (timestamp، value) لسلسلة زمنية. ويمكن اشتقاق نوعَي عنصر timestamp والعنصر scalar في Tuple من تعريف `INNER COLUMNS` الخاص بـ samples (راجع [تحديد الأعمدة الخارجية](#specifying-outer-columns)). ويُسمّى العمود `time_series` في الجداول ذات [الإصدار](#schema-versioning) 2 والإصدارات الأقدم |
| `metric_family` | `String` | اسم عائلة المقياس (للبيانات الوصفية للمقاييس) |
| `type` | `String` | نوع المقياس (مثل "counter" و"gauge") |
| `unit` | `String` | وحدة المقياس |
| `help` | `String` | وصف المقياس |

مثال:

```sql theme={null}
INSERT INTO my_table (metric_name, tags, samples) VALUES
    ('cpu_usage', {'job': 'node_exporter', 'instance': 'host1:9100'},
     [(toDateTime64('2024-01-01 00:00:00', 3), 0.5), (toDateTime64('2024-01-01 00:01:00', 3), 0.7)])
```

يُسمح بأن تكون القيمة `metric_name` فارغة عند الإدخال، ما يعني أن اسم المقياس يُحدَّد في `tags` ضمن `__name__`، على سبيل المثال:

```sql theme={null}
INSERT INTO my_table (tags, samples) VALUES
    ({'__name__': 'cpu_usage', 'job': 'test'},
     [(toDateTime64('2024-01-01 00:00:00', 3), 0.5)])
```

لإدراج البيانات الوصفية للمقاييس، أدرِجها في الأعمدة `metric_family` و`type` و`unit` و`help`:

```sql theme={null}
INSERT INTO my_table (metric_name, tags, samples, metric_family, type, unit, help) VALUES
    ('http_requests_total', {'method': 'GET'}, [(now64(), 100.0)],
     'http_requests_total', 'counter', 'requests', 'Total HTTP requests')
```

### تحديد الأعمدة الخارجية

يمكن إدراج العمود الخارجي `samples` صراحةً في عبارة `CREATE TABLE` لاستبدال نوعه الافتراضي `Array(Tuple(DateTime64(3), Float64))` (كما يُقبل اسمه القديم `time_series` أيضاً). يستخرج ClickHouse نوعَي الطابع الزمني والقيمة scalar من الـ tuple ويُمرّرهما إلى جدول العينات الداخلي:

```sql theme={null}
CREATE TABLE my_table (samples Array(Tuple(UInt32, Float32))) ENGINE=TimeSeries
```

وهذا يعادل التصريح مباشرةً بأنواع أعمدة الطابع الزمني والقيمة في عبارة `INNER COLUMNS` الخاصة بجدول samples:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp UInt32 CODEC(Delta, T64, ZSTD(3)), value Float32 CODEC(ALP, ZSTD(3)))
```

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

## الجداول الهدف

لا يحتوي جدول `TimeSeries` على بيانات خاصة به، إذ يُخزَّن كل شيء في جداوله الهدف.
وهذا يشبه طريقة عمل [العرض المادي](/ar/reference/statements/create/view#materialized-view)،
مع فارق أن العرض المادي له جدول هدف واحد،
بينما يحتوي جدول `TimeSeries` على ثلاثة جداول هدف إلزامية باسم [samples](#samples-table) و[tags](#tags-table) و[عائلة المقياس](#metric-families-table)،
وجدول هدف اختياري لـ [العينات الحديثة](#recent-samples-table) يكون مُمكّنًا افتراضيًا
(انظر الإعداد [recent\_samples\_ttl\_seconds](#settings)).

يمكن تحديد الجداول الهدف صراحةً في استعلام `CREATE TABLE`
أو يمكن لمحرك الجدول `TimeSeries` إنشاء الجداول الهدف الداخلية تلقائيًا.

تُحوَّل الصفوف المُدرجة في جدول `TimeSeries`، وتُقسَّم إلى كتل، ثم تُدرج في هذه الجداول الهدف.

الجداول الهدف هي كما يلي:

### جدول العينات

يحتوي جدول *samples* على سلاسل زمنية مرتبطة بمعرّف معيّن.

يجب أن يحتوي جدول *samples* على الأعمدة التالية:

| الاسم | إلزامي؟ | النوع الافتراضي | الأنواع الممكنة | الوصف |
| - | - | - | - | - |
| `id` | \[x] | `Tuple(UInt64, LowCardinality(UUID))` | أيّ نوع | يحدّد مجموعة من أسماء المقاييس والوسوم |
| `timestamp` | \[x] | `DateTime64(3)` | `DateTime64(X)` | نقطة زمنية |
| `value` | \[x] | `Float64` | `Float32` أو `Float64` | قيمة مرتبطة بـ `timestamp` |

تستخدم الأعمدة التي ينشئها المحرك تلقائيًا برامج ترميز ضغط للسلاسل الزمنية:
`timestamp CODEC(Delta, T64, ZSTD(3))` و`value CODEC(ALP, ZSTD(3))`. بالكاد
تُضغط الطوابع الزمنية شبه الرتيبة باستخدام برامج الترميز العامة، وقد تستحوذ لولا ذلك على معظم حجم جدول العينات على القرص.
يفعّل المحرك `ALP` لجداول العينات الداخلية وجداول العينات الحديثة الخاصة به دون الحاجة إلى ضبط `enable_alp_codec`.
انظر أيضًا [ضبط أنواع الأعمدة](#adjusting-column-types).

### جدول العينات الحديثة

جدول *العينات الحديثة* اختياري ومُفعّل افتراضيًا (راجع إعداد [recent\_samples\_ttl\_seconds](#settings)؛
إذ يؤدي ضبطه على صفر إلى تعطيل الجدول). يحتوي على نسخة من العينات الأحدث من قيمة TTL التي يحددها هذا الإعداد،
ويجب أن يتضمن الأعمدة نفسها الموجودة في جدول [العينات](#samples-table).
يستخدم العمود المُولَّد `timestamp` الترميز `CODEC(Delta, T64, ZSTD(3))`،
ويستخدم العمود المُولَّد `value` الترميز `CODEC(ALP, ZSTD(3))`.

تُكتب كل عينة مُدرجة في كلٍّ من جدول العينات وجدول العينات الحديثة.
تقرأ الاستعلامات التي يقع نطاقها الزمني ضمن نافذة TTL من جدول العينات الحديثة بدلًا من جدول العينات الرئيسي
لأنه أصغر بكثير (يمكن تعطيل ذلك باستخدام إعداد على مستوى الاستعلام `time_series_prefer_recent_samples_table`).

تُشتق قيمة TTL لجدول العينات الحديثة الداخلي دائمًا من إعداد [recent\_samples\_ttl\_seconds](#settings).

### جدول الوسوم

يحتوي جدول *tags* على المعرّفات المحسوبة لكل توليفة من اسم مقياس والوسوم.

يجب أن يحتوي جدول *tags* على الأعمدة التالية:

| Name | Mandatory? | Default type | Possible types | Description |
| - | - | - | - | - |
| `id` | \[x] | `Tuple(UInt64, LowCardinality(UUID))` | any (must match the type of `id` in the [samples](#samples-table) table) | يعرّف `id` توليفة من اسم مقياس والوسوم. ويحدّد تعبير DEFAULT كيفية حساب هذا المعرّف |
| `metric_name` | \[x] | `LowCardinality(String)` | `String` or `LowCardinality(String)` | اسم المقياس |
| `<tag_value_column>` | \[ ] | `String` | `String` or `LowCardinality(String)` or `LowCardinality(Nullable(String))` | قيمة وسم معيّن، ويُحدَّد اسم الوسم واسم العمود المقابل له في الإعداد [tags\_to\_columns](#settings) |
| `tags` | \[x] | `Map(LowCardinality(String), String)` | `Map(String, String)` or `Map(LowCardinality(String), String)` or `Map(LowCardinality(String), LowCardinality(String))` | خريطة لجميع الوسوم، بما فيها الوسم `__name__` الذي يحتوي على اسم المقياس، والوسوم التي أُدرجت أسماؤها في الإعداد [tags\_to\_columns](#settings). كانت الجداول التي أنشأتها الإصدارات الأقدم من ClickHouse تخزّن في هذا العمود الوسوم التي لا تحتوي على أعمدة مخصصة فقط ودون اسم المقياس؛ وتدعم القراءة كلتا الحالتين |
| `min_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` or `Nullable(DateTime64(X))` | أدنى طابع زمني للسلسلة الزمنية ذات `id` هذا. يُنشأ العمود إذا كانت قيمة [store\_min\_time\_and\_max\_time](#settings) هي `true` |
| `max_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` or `Nullable(DateTime64(X))` | أقصى طابع زمني للسلسلة الزمنية ذات `id` هذا. يُنشأ العمود إذا كانت قيمة [store\_min\_time\_and\_max\_time](#settings) هي `true` |

تحتوي جداول الوسوم الداخلية الجديدة من [version](#schema-versioning) 5 فما بعد، والتي تستخدم محركًا من عائلة `MergeTree`، على فهرس نصي معكوس على `tags`:
`INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs')`. وهو يسرّع المطابقات التامة للوسوم مثل
`{job="api"}` في PromQL عبر البحث عن المفتاح والقيمة معًا. أما المقارنات مع سلسلة فارغة فتطابق أيضًا الوسوم المفقودة ولا تستفيد من هذا الفهرس.

تحلّ الفهارس الصريحة المعلَنة في `TAGS INNER COLUMNS` محل الفهرس الافتراضي. أما الجداول الموجودة وجداول الوسوم الخارجية فتحتفظ بفهارسها؛ ولتفعيله عليها، أضف الفهرس وجسّده على جدول الهدف الخاص بوسومها.

### جدول عائلات المقاييس

يحتوي جدول *metric families* على بعض المعلومات حول عائلات المقاييس التي تُجمع، وأنواع تلك العائلات وأوصافها.
عائلة المقياس هي مجموعة من المقاييس التي تحمل الاسم نفسه (الوسم `__name__`) والنوع نفسه، فعلى سبيل المثال المُدرَّج التكراري هو عائلة مقياس تتكون من عدة مقاييس.

يجب أن يحتوي جدول *metric families* على الأعمدة التالية:

| الاسم | إلزامي؟ | النوع الافتراضي | الأنواع الممكنة | الوصف |
| - | - | - | - | - |
| `metric_family_name` | \[x] | `String` | `String` أو `LowCardinality(String)` | اسم عائلة المقياس |
| `type` | \[x] | `LowCardinality(String)` | `String` أو `LowCardinality(String)` | نوع عائلة المقياس، ويكون إحدى القيم التالية: "counter" أو "gauge" أو "summary" أو "stateset" أو "histogram" أو "gaugehistogram" |
| `unit` | \[x] | `LowCardinality(String)` | `String` أو `LowCardinality(String)` | الوحدة المستخدمة في المقياس |
| `help` | \[x] | `String` | `String` أو `LowCardinality(String)` | وصف المقياس |

## الإنشاء

توجد عدة طرق لإنشاء جدول باستخدام محرك الجدول `TimeSeries`.
أبسط عبارة

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
```

سينشئ فعليًا الجدول التالي (يمكنك التحقق من ذلك بتنفيذ `SHOW CREATE TABLE my_table`):

```sql theme={null}
CREATE TABLE my_table
(
    `metric_name` String,
    `tags` Map(String, String),
    `samples` Array(Tuple(DateTime64(3), Float64)),
    `metric_family` String,
    `type` String,
    `unit` String,
    `help` String
)
ENGINE = TimeSeries
SETTINGS version = 5, recent_samples_ttl_seconds = 345600
SAMPLES INNER COLUMNS
(
    `id` Tuple(UInt64, LowCardinality(UUID)),
    `timestamp` DateTime64(3) CODEC(Delta, T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
SAMPLES INNER ENGINE = MergeTree ORDER BY (id, timestamp) SETTINGS index_granularity = 32768
RECENT SAMPLES INNER COLUMNS
(
    `id` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(Delta, T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
RECENT SAMPLES INNER ENGINE = MergeTree PARTITION BY toStartOfInterval(toDateTime(timestamp), toIntervalHour(5)) ORDER BY (id, timestamp) TTL toDateTime(timestamp) + toIntervalSecond(345600) SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
TAGS INNER COLUMNS
(
    `id` Tuple(UInt64, LowCardinality(UUID)) DEFAULT tuple(sipHash64(metric_name), toLowCardinality(reinterpretAsUUID(sipHash128(tags)))),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
    `max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3))),
    INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs') GRANULARITY 100000000
)
TAGS INNER ENGINE = AggregatingMergeTree PRIMARY KEY metric_name ORDER BY (metric_name, id) SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
METRIC FAMILIES INNER COLUMNS
(
    `metric_family_name` String,
    `type` LowCardinality(String),
    `unit` LowCardinality(String),
    `help` String
)
METRIC FAMILIES INNER ENGINE = ReplacingMergeTree ORDER BY metric_family_name
```

لذلك، جرى إنشاء الأعمدة تلقائيًا، وهناك أيضًا أربعة جداول هدف داخلية، لكل منها تعريفات أعمدة خاصة
مخزنة في عبارات `INNER COLUMNS`. وكُتب الإعداد `recent_samples_ttl_seconds` في عبارة `SETTINGS`
بقيمته الافتراضية: يحدد الإعداد TTL لجدول العينات الحديثة، لذا تُثبَّت قيمته الفعلية عند الإنشاء.
كما جرى تثبيت أحدث إصدار من المخطط في الإعداد `version` (انظر [إصدارات المخطط](#schema-versioning)).

تحمل الجداول الهدف الداخلية أسماء مثل `.inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`،
و`.inner_id.recentsamples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`، و`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`،
و`.inner_id.metricfamilies.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
ولكل جدول هدف مجموعته الخاصة من الأعمدة:

```sql theme={null}
CREATE TABLE default.`.inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, LowCardinality(UUID)),
    `timestamp` DateTime64(3) CODEC(Delta(8), T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
ENGINE = MergeTree
ORDER BY (id, timestamp)
SETTINGS index_granularity = 32768
```

```sql theme={null}
CREATE TABLE default.`.inner_id.recentsamples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(Delta(8), T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
ENGINE = MergeTree
PARTITION BY toStartOfInterval(toDateTime(timestamp), toIntervalHour(5))
ORDER BY (id, timestamp)
TTL toDateTime(timestamp) + toIntervalSecond(345600)
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
```

```sql theme={null}
CREATE TABLE default.`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, LowCardinality(UUID)) DEFAULT tuple(sipHash64(metric_name), toLowCardinality(reinterpretAsUUID(sipHash128(tags)))),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
    `max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3))),
    INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs') GRANULARITY 100000000
)
ENGINE = AggregatingMergeTree
PRIMARY KEY metric_name
ORDER BY (metric_name, id)
SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
```

```sql theme={null}
CREATE TABLE default.`.inner_id.metricfamilies.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `metric_family_name` String,
    `type` LowCardinality(String),
    `unit` LowCardinality(String),
    `help` String
)
ENGINE = ReplacingMergeTree
ORDER BY metric_family_name
SETTINGS index_granularity = 8192
```

## إنشاء جدول AS جدول موجود

تنشئ العبارة `CREATE TABLE new_table AS existing_table` جدول `TimeSeries` مهيأً على غرار `existing_table`،
الذي يجب أن يكون بدوره جدول `TimeSeries`. لا تُنسخ الأهداف الخارجية لـ `existing_table`؛ إذ يجب أن تعرّفها العبارة
بنفسها.

تنسخ العبارة من `existing_table`:

* عبارة `SETTINGS`، باستثناء `version`: يحصل الجدول الجديد دائمًا على أحدث إصدار. تُدمج الإعدادات المكتوبة في العبارة
  نفسها مع الإعدادات المنسوخة بحسب الاسم، لذا يتقدم الإعداد المكتوب على الإعداد المنسوخ، ويؤدي `name = DEFAULT`
  إلى إعادة ضبط إعداد منسوخ إلى قيمته الافتراضية؛
* عبارتا `INNER COLUMNS` و`INNER ENGINE` لكل جدول داخلي. يُحتفظ بالأعمدة المخصصة (مثل الأعمدة الإضافية والأعمدة
  التي تحتوي على برنامج ترميز الضغط أو تعبير DEFAULT) وأجزاء المحرك المخصصة (مثل محرك ذي arguments أو sorting key مخصص
  أو إعداد للمحرك)، بينما تُضبط الأعمدة وأجزاء المحرك الأخرى وفقًا لإعدادات الجدول الجديد، بحيث
  تسري، على سبيل المثال، قيم `tags_to_columns` أو `aggregate_min_time_and_max_time` أو `tags_index_granularity` المكتوبة في العبارة.

تُؤخذ أيضًا أنواع أعمدة `id` والطابع الزمني والقيمة، ونوع النسخ المتماثل للمحركات الداخلية (`MergeTree`،
`ReplicatedMergeTree` أو `SharedMergeTree`) من `existing_table`، ما لم تعرّفها العبارة بنفسها.
تُعاد إنشاء قائمة الأعمدة الخارجية ولا تُنسخ.

يمكن استخدام جدول أنشأه إصدار أقدم من ClickHouse بصفته `existing_table`: يحصل الجدول الجديد على
البنية الحالية، مثل نوع `id` الحالي وتعبير المعرّف الافتراضي.

## ضبط أنواع الأعمدة

يمكنك ضبط أنواع الأعمدة في الجداول الهدف الداخلية باستخدام عبارة `INNER COLUMNS`. على سبيل المثال، لتخزين الطوابع الزمنية بالميكروثانية والقيم كـ `Float32`، استخدم:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6) CODEC(Delta, T64, ZSTD(3)), value Float32 CODEC(ALP, ZSTD(3)))
```

يعني تحديد الأعمدة الداخلية دون برامج ترميز الضغط استخدام برنامج ترميز الضغط الافتراضي لها:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6), value Float32)
```

## العمود `id`

يحتوي العمود `id` على معرّفات، ويُحتسب كل معرّف استنادًا إلى تركيبة من اسم المقياس والوسوم.
يمكن تخصيص النوع وتعبير `DEFAULT` المستخدم لتوليد المعرّفات عبر العبارة `TAGS INNER COLUMNS`:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
TAGS INNER COLUMNS (id UInt64 DEFAULT sipHash64(tags))
```

يمكن أن يكون العمود `id` من أي نوع غير `Nullable` قابل للمقارنة. يجب أن تتطابق أنواع `id` المُعلنة في الجدولين الداخليين `samples` و`tags`.

إذا لم يتم تحديد التعبير `DEFAULT` للعمود `id` ولم يكن الإعداد `id_generator` مُعيَّنًا، فسيختار ClickHouse التعبير `DEFAULT` تلقائيًا بناءً على نوع `id`، ولكن فقط إذا كان نوع `id` أحد الأنواع `UUID` أو `UInt64` أو `UInt128` أو `FixedString(16)`، أو الأنواع نفسها المغلّفة بـ`LowCardinality`، أو زوجًا من اثنين من هذه الأنواع. بالنسبة إلى هذا الزوج، يحسب التعبير المختار تلقائيًا تجزئةً لاسم المقياس في المكوّن الأول وتجزئةً لجميع الوسوم في المكوّن الثاني.

يُبقي نوع المعرّف `LowCardinality`، مثل `Tuple(UInt64, LowCardinality(UUID))`، المعرّفات مُرمَّزة بالقاموس: إذ يخزّن جدول samples قواميس صغيرة لكل كتلة مع فهارس القاموس بدلًا من تكرار المعرّف الكامل في كل صف، مما يقلل كمية البيانات التي تقرؤها الاستعلامات.

يوفّر الإعداد `id_generator` مستوى التخصيص نفسه من دون استخدام العبارة `INNER COLUMNS`:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_generator = 'sipHash64(tags)'
```

إذا كان هذا الإعداد مُعيَّنًا، فسيُستخدم لتوليد `id` حتى إذا كانت قيمة `DEFAULT` الخاصة بالعمود تحتوي على تعبير مختلف.

يمكن أيضًا تحديد نوع العمود `id` في الإعداد `id_type` بدلًا من العبارة `INNER COLUMNS`:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_type = 'UInt64', id_generator = 'sipHash64(tags)'
```

عندما يكون الإعداد `id_generator` مُعيَّنًا، يُسجَّل الإعداد `id_type` تلقائيًا عند `CREATE`،
بحيث يحتفظ التعريف بالنوع الذي كُتب التعبير من أجله.

## العمود `tags`

يحتوي العمود `tags` على جميع وسوم السلسلة الزمنية، بما في ذلك الوسم `__name__` الذي يحتوي على اسم المقياس.

يتيح الإعداد `tags_to_columns` تحديد وسم معيّن لتخزينه أيضًا في عمود منفصل
بالإضافة إلى الخريطة داخل العمود `tags`:

```sql theme={null}
CREATE TABLE my_table
ENGINE = TimeSeries
SETTINGS tags_to_columns = {'instance': 'instance', 'job': 'job'}
```

ستضيف هذه العبارة العمودين `instance` و`job` إلى جدول [الوسوم](#tags-table) الهدف الداخلي.
ستُخزَّن قيم الوسمين `instance` و`job` في العمودين المذكورين وفي العمود `tags`.

<Note>
  في الجداول التي أنشأتها إصدارات أقدم من ClickHouse، يحتوي العمود `tags` على الوسوم التي لا توجد لها
  أعمدة مخصصة فقط، ولا يتضمن اسم المقياس، بينما يكون العمود `all_tags` عمودًا مؤقتًا جرى ملؤه عند الإدراج
  بجميع الوسوم باستثناء اسم المقياس.
</Note>

## محركات الجداول الخاصة بالجداول الهدف الداخلية

تستخدم الجداول الهدف الداخلية، افتراضيًا، محركات الجداول التالية:

* يستخدم جدول [العينات](#samples-table) محرك [MergeTree](/ar/reference/engines/table-engines/mergetree-family/mergetree);
* يستخدم جدول [العينات الحديثة](#recent-samples-table) محرك [MergeTree](/ar/reference/engines/table-engines/mergetree-family/mergetree) مقسمًا إلى حاويات زمنية مدتها 5 ساعات (راجع إعداد [recent\_samples\_partition\_by](#settings)) مع قيمة `TTL` مشتقة من
  إعداد [recent\_samples\_ttl\_seconds](#settings) ومع تمكين `ttl_only_drop_parts`، بحيث تُحذف الأجزاء المنتهية الصلاحية كاملةً؛
* يستخدم جدول [الوسوم](#tags-table) محرك [AggregatingMergeTree](/ar/reference/engines/table-engines/mergetree-family/aggregatingmergetree) لأن البيانات نفسها تُدرج في هذا الجدول غالبًا عدة مرات، لذا نحتاج إلى طريقة
  لإزالة التكرارات، وكذلك لأن التجميع مطلوب للعمودين `min_time` و `max_time`;
* يستخدم جدول [عائلات المقاييس](#metric-families-table) محرك [ReplacingMergeTree](/ar/reference/engines/table-engines/mergetree-family/replacingmergetree) لأن البيانات نفسها تُدرج في هذا الجدول غالبًا عدة مرات، لذا نحتاج إلى طريقة
  لإزالة التكرارات.

تتبع عائلة محركات الجداول الداخلية المُنشأة إعداد مستوى الاستعلام `default_table_engine`:
فعند استخدام `default_table_engine = ReplicatedMergeTree` أو `SharedMergeTree`، تستخدم الجداول الداخلية محركات
`Replicated` أو `Shared` المقابلة. ومع `default_table_engine = None` (أو أي قيمة أخرى)، يجب
تحديد محركات الجداول الداخلية صراحةً.

يجب أن تكون جميع الجداول الداخلية من نفس نوع النسخ المتماثل: فإذا كان أحدها متماثلًا (أو مشتركًا)، يجب أن تكون الجداول الداخلية
الأخرى متماثلة (أو مشتركة) أيضًا، وإلا فستتباين محتوياتها بين النسخ المتماثلة. على سبيل المثال،
يتطلب تعريف `SAMPLES INNER ENGINE = ReplicatedMergeTree(...)` أن تكون المحركات الداخلية الأخرى متماثلة أيضًا -
إما بتعريفها صراحةً أو بإنشائها باستخدام `default_table_engine = ReplicatedMergeTree`.

كما يمكن استخدام محركات جداول أخرى للجداول الهدف الداخلية إذا تم تحديد ذلك:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES ENGINE=ReplicatedMergeTree
RECENT SAMPLES ENGINE=ReplicatedMergeTree
TAGS ENGINE=ReplicatedAggregatingMergeTree
METRIC FAMILIES ENGINE=ReplicatedReplacingMergeTree
```

يُبقي جدول [الوسوم](#tags-table) أعمدة الوسوم (والـ Map `tags`) خارج مفتاح الفرز الخاص به،
وهو ما يرفضه `AggregatingMergeTree` افتراضيًا (راجع [`allow_dimensions_outside_sorting_key`](/ar/reference/engines/table-engines/mergetree-family/aggregatingmergetree)).
وهذا آمن هنا لأن تلك الأعمدة تعتمد وظيفيًا على `id`، وهو جزء من مفتاح الفرز، لذا فإن جميع
الصفوف التي تدمجها عملية دمج في الخلفية معًا تتشارك القيم نفسها. وعندما يُنشأ جدول الوسوم الداخلي أو يُحدَّد محركه inline كما هو موضح أعلاه، يضبط `TimeSeries` القيمة `allow_dimensions_outside_sorting_key = 1` عليه تلقائيًا؛
أما بالنسبة إلى جدول الوسوم التجميعي [الخارجي](#external-target-tables) الذي يُنشأ يدويًا، فيجب عليك تعيين هذا الإعداد بنفسك.

## الجداول الهدف الخارجية

يمكن إعداد جدول `TimeSeries` لاستخدام جدول أُنشئ يدويًا:

```sql theme={null}
CREATE TABLE samples_for_my_table
(
    `id` UUID,
    `timestamp` DateTime64(3),
    `value` Float64
)
ENGINE = MergeTree
ORDER BY (id, timestamp);

CREATE TABLE tags_for_my_table ...

CREATE TABLE metric_families_for_my_table ...

CREATE TABLE my_table ENGINE=TimeSeries SAMPLES samples_for_my_table TAGS tags_for_my_table METRIC FAMILIES metric_families_for_my_table;
```

يمكن أيضًا استخدام جدول خارجي كهدف [للعينات الحديثة](#recent-samples-table) (العبارة `RECENT SAMPLES my_recent_samples_table`).
يجب أن يحتوي هذا الجدول على الأعمدة نفسها الموجودة في جدول عينات خارجي، وأن يحتفظ ببيانات لمدة لا تقل عن
[recent\_samples\_ttl\_seconds](#settings) ثانية، وتقع مسؤولية ذلك على عاتق المستخدم.

يجب أن تتطابق أنواع أعمدة الجداول الخارجية (`id` و`timestamp` و`value` وأعمدة `<tag_value_column>` المدرجة في [`tags_to_columns`](#settings)) مع ما كان جدول `TimeSeries` سيُنشئه داخليًا في الحالة العادية (راجع [جدول العينات](#samples-table) و[جدول الوسوم](#tags-table) و[جدول عائلات المقاييس](#metric-families-table) للاطلاع على قيود الأنواع). ويُبلَّغ عن أي عدم تطابق في الأنواع عند تنفيذ `CREATE`.

يُسجَّل نوع عمود `id` في جدول الوسوم الخارجي والتعبير المولِّد للمعرّفات في الإعدادين [`id_type`](#settings) و[`id_generator`](#settings) عند تنفيذ `CREATE` (بدءًا من [الإصدار](#schema-versioning) 2)، بحيث يحتفظ بهما تعريف جدول `TimeSeries`: على سبيل المثال، يقرأ `CREATE TABLE ... AS my_table` نوع `id` من تعريف `my_table` دون قراءة جداوله الهدف الخارجية. وإذا لم يُحدَّد الإعداد `id_generator`، فيُعيَّن إلى `DEFAULT` المعرَّف في عمود `id` للجدول الخارجي (إن وجد)، وإلا فإلى المولِّد القياسي المشتق من نوع `id`. ويُستخدَم التعبير المسجَّل لتوليد `id` حتى إذا تغيّرت قيمة `DEFAULT` في الجدول الخارجي لاحقًا — راجع [عمود `id`](#id-column) للتفاصيل.

## تعديل الإعدادات

يمكن تغيير إعدادَين بعد `CREATE`:

* `id_generator`
* `filter_by_min_time_and_max_time`

```sql theme={null}
ALTER TABLE my_table MODIFY SETTING id_generator = 'sipHash64(tags)';
ALTER TABLE my_table MODIFY SETTING filter_by_min_time_and_max_time = 0;
ALTER TABLE my_table RESET SETTING filter_by_min_time_and_max_time;
```

لاحظ أن تغيير `id_generator` بعد وجود بيانات بالفعل في جدول الوسوم قد يؤدي إلى إنشاء معرّفات مختلفة لنفس تركيبة metric+tag — إذ تحتفظ الصفوف القديمة بمعرّفاتها القديمة، بينما تستخدم الصفوف الجديدة المولِّد الجديد.

ولا يمكن تغيير الإعدادات الأخرى باستخدام `ALTER ... MODIFY SETTING`: فمعظمها يكون مدمجًا في مخطط الجداول الداخلية عند `CREATE`،
كما أن الإعداد `version` يُثبَّت تلقائيًا عند `CREATE` ويُعرِّف المخطط نفسه (انظر [إصدارات المخطط](#schema-versioning)).

## الإعدادات

فيما يلي قائمة بالإعدادات التي يمكن تحديدها عند تعريف جدول `TimeSeries`:

| الاسم | النوع | الافتراضي | الوصف |
| - | - | - | - |
| `id_type` | نوع البيانات | يعتمد على العمود `id` | نوع العمود `id` في جداول الهدف. عادةً يُعلَن النوع في عبارات `INNER COLUMNS` للجداول الداخلية أو في جدول وسوم [خارجي](#external-target-tables)؛ ويُسجّل الإعداد تلقائيًا وقت `CREATE` إذا لم يكن النوع محفوظًا في التعريف بطريقة أخرى: أي إذا كان هدف الوسوم جدولًا خارجيًا، أو إذا كان الإعداد `id_generator` معيّنًا. كما يمكن تحديد الإعداد صراحةً بدلًا من `TAGS INNER COLUMNS (id <type>)`. يتطلب أن تكون `version` 2 على الأقل |
| `id_generator` | Expression | يعتمد على نوع `id` | تعبير يحسب معرّف (بصمة) السلسلة الزمنية من وسومها. إذا لم يتم تعيينه، فسيُستخدم التعبير الافتراضي للعمود `id`. وإذا كان التعبير الافتراضي للعمود `id` غير معيّن أيضًا، فسيُختار التعبير تلقائيًا. بالنسبة لجدول وسوم خارجي، يُسجَّل الإعداد تلقائيًا وقت `CREATE` إذا كانت `version` 2 على الأقل (راجع [جداول الهدف الخارجية](#external-target-tables)) |
| `tags_to_columns` | خريطة | {} | قيمة خريطة تحدد الوسوم التي يجب وضعها في أعمدة منفصلة في [جدول الوسوم](#tags-table). الصياغة: `{'tag1': 'column1', 'tag2' : column2, ...}` |
| `use_all_tags_column_to_generate_id` | Bool | false | إعداد متقادم، لا يفعل شيئًا |
| `store_min_time_and_max_time` | Bool | true | إذا تم تعيينه إلى true، فسيخزّن الجدول `min_time` و`max_time` لكل سلسلة زمنية |
| `aggregate_min_time_and_max_time` | Bool | true | عند إنشاء جدول `tags` الداخلي الهدف، يتيح هذا الخيار استخدام `SimpleAggregateFunction(min, Nullable(DateTime64(3)))` بدلًا من `Nullable(DateTime64(3))` فقط كنوع للعمود `min_time`، وينطبق الأمر نفسه على العمود `max_time` |
| `filter_by_min_time_and_max_time` | Bool | true | إذا تم تعيينه إلى true، فسيستخدم الجدول العمودين `min_time` و`max_time` لتصفية السلاسل الزمنية |
| `samples_index_granularity` | UInt64 | 32768 | يضبط `index_granularity` لجدول [العينات](#samples-table) الداخلي. عند تعيينه صراحةً، فإنه يتجاوز `index_granularity` من تعريف المحرك. يُتجاهل لجدول العينات خارجي ولمحرك غير MergeTree |
| `recent_samples_ttl_seconds` | UInt64 | 345600 | مدة الاحتفاظ بجدول الهدف الإضافي `recent samples`، الذي تُكتب إليه أيضًا كل عينة مُدرجة. يحصل جدول العينات الحديثة الداخلي دائمًا على `TTL toDateTime(timestamp) + toIntervalSecond(recent_samples_ttl_seconds)` مشتق من هذا الإعداد (متجاوزًا أي TTL من تعريف المحرك)؛ ويجب أن يحتفظ جدول العينات الحديثة الخارجي ببيانات لهذه المدة من الثواني على الأقل. تفضّل الاستعلامات التي يقع نطاقها الزمني ضمن نافذة TTL جدول العينات الحديثة على جدول العينات الرئيسي (راجع الإعداد على مستوى الاستعلام `time_series_prefer_recent_samples_table`). القيمة الافتراضية هي 4 أيام؛ وتُثبّت القيمة الفعلية في تعريف الجدول وقت CREATE. عيّنه إلى 0 لتعطيل جدول العينات الحديثة |
| `recent_samples_partition_by` | Expression | `toStartOfInterval(toDateTime(timestamp), toIntervalHour(5))` | مفتاح التقسيم لجدول `recent samples` الداخلي، مثلًا `toStartOfHour(timestamp)`. عند تعيينه صراحةً، فإنه يتجاوز مفتاح التقسيم من تعريف المحرك؛ وإذا لم يُعيّن أي منهما، فسيُستخدم قسم واحد لكل 5 ساعات. يُتجاهل لجدول العينات الحديثة خارجي. يتطلب أن تكون `recent_samples_ttl_seconds` غير صفرية |
| `recent_samples_index_granularity` | UInt64 | 8192 | يضبط `index_granularity` لجدول `recent samples` الداخلي. عند تعيينه صراحةً، فإنه يتجاوز `index_granularity` من تعريف المحرك. يُتجاهل لجدول العينات الحديثة خارجي ولمحرك غير MergeTree. يتطلب أن تكون `recent_samples_ttl_seconds` غير صفرية |
| `tags_index_granularity` | UInt64 | 8192 | يضبط `index_granularity` لجدول [الوسوم](#tags-table) الداخلي. عند تعيينه صراحةً، فإنه يتجاوز `index_granularity` من تعريف المحرك. يُتجاهل لجدول الوسوم خارجي ولمحرك غير MergeTree |
| `version` | UInt64 | 5 | إصدار الجدول: يحدد مجموعة جداول الهدف وبنيتها. يُثبّت الإصدار تلقائيًا عند إنشاء الجدول ولا يمكن تغييره بعد ذلك، وعادةً ينبغي حذفه من استعلام `CREATE TABLE` (راجع [إصدارات المخطط](#schema-versioning)) |

## إصدارات المخطط

لا يزال محرك الجدول `TimeSeries` وطبقة تنفيذ PromQL قيد التطوير النشط:
فمجموعة الجداول الهدف وبنيتها قد تتغيّر بين إصدارات ClickHouse.
ولجعل مثل هذه التغييرات قابلة للاكتشاف، يخزّن كل جدول `TimeSeries` إصداره في الإعداد [version](#settings).
ويُثبَّت الإصدار تلقائيًا في استعلام `CREATE` عند إنشاء الجدول - وقيمته هي أحدث إصدار معروف للخادم (حاليًا 5) -
ويبقى محفوظًا في بيانات الجدول الوصفية، ولا يمكن تغييره باستخدام `ALTER`. أما الجداول التي أُنشئت قبل أن يُضاف هذا الإعداد فتُعدّ من الإصدار 0.
وفي الأحوال العادية يُستحسن إغفال هذا الإعداد في استعلام `CREATE TABLE`، فيحصل الجدول عندئذٍ على أحدث إصدار.
ويُقبل تحديد `version` صراحةً إذا كان الخادم يدعم ذلك الإصدار؛ عندئذٍ يُعرَّف الجدول بالطريقة التي يعتمدها ذلك الإصدار (انظر [سجل الإصدارات](#version-history)).
ولا ينسخ `CREATE TABLE ... AS other_table` إصدار الجدول الآخر، انظر [إنشاء جدول AS جدول موجود](#create-as).

يدعم الخادم نطاقًا من الإصدارات، وقد يختلف الحد الأدنى للإصدار بين القراءة عبر `SELECT`، والكتابة عبر `INSERT`
أو بروتوكول remote-write الخاص بـ Prometheus، وتقييم PromQL (دوال الجداول [prometheusQuery](/ar/reference/functions/table-functions/prometheusQuery)
و[prometheusQueryRange](/ar/reference/functions/table-functions/prometheusQueryRange)
و[timeSeriesSelector](/ar/reference/functions/table-functions/timeSeriesSelector)،
ولهجة `promql`، وواجهة برمجة تطبيقات الاستعلام عبر HTTP الخاصة بـ Prometheus):

* إذا كان إصدار جدول `TimeSeries` أقدم مما يدعمه PromQL، تُرفض استعلامات PromQL التي تجري عليه. ويقترح الاستثناء إعادة إنشاء الجدول:
  أنشئ جدول `TimeSeries` جديدًا، وانسخ البيانات باستعلام `INSERT ... SELECT`، ثم استبدل الجدول القديم بالجديد.
* إذا كان الإصدار أقدم من أن يُكتب فيه، تُرفض استعلامات `INSERT` وبروتوكول remote-write الخاص بـ Prometheus، بينما تظل استعلامات `SELECT` تعمل.
* وإذا كان الإصدار أقدم من أن يدعمه الخادم أصلًا، يُرفض كل استعلام على الجدول (باستثناء `SHOW CREATE TABLE` و`DETACH` و`DROP`).

### سجل الإصدارات

| الإصدار | التغييرات |
| - | - |
| 0 | الجداول التي أُنشئت قبل إضافة الإعداد `version`، بما فيها جداول "prealpha" (التي كانت تُعلن أعمدة الجداول الهدف كـ[أعمدة خارجية](#outer-columns)) والجداول التي لا تحتوي على جدول [العينات الحديثة](#recent-samples-table) |
| 1 | أُضيف الإعداد `version` |
| 2 | أُضيف الإعداد [`id_type`](#settings): الجدول الذي له جدول الوسوم الخارجي يسجّل نوع العمود `id` في `id_type`، والتعبير المولِّد للمعرّفات في [`id_generator`](#settings)، بحيث لا يعتمد تعريفه على الجدول الخارجي. ويُسجَّل `id_type` أيضًا عند ضبط `id_generator` (انظر [العمود `id`](#id-column)) |
| 3 | أُعيدت تسمية العمود الخارجي `time_series` إلى `samples` (انظر [الأعمدة الخارجية](#outer-columns)). تحتفظ جداول الإصدارات الأقدم بالاسم القديم للعمود، وتُعيد دالتا الجداول [prometheusQuery](/ar/reference/functions/table-functions/prometheusQuery) و[prometheusQueryRange](/ar/reference/functions/table-functions/prometheusQueryRange) العمود بالاسم الذي يستخدمه الجدول. أما البيانات المخزَّنة فلم تتغيّر |
| 4 | أُعيدت تسمية جدول الهدف `metrics` إلى `عائلة المقياس`: يُسمّى الجدول الداخلي `.inner_id.metricfamilies.<uuid>` بدلًا من `.inner_id.metrics.<uuid>`، ويُكتب التعريف بالكلمة المفتاحية `METRIC FAMILIES` بدلًا من `METRICS`. أما البيانات المخزَّنة فلم تتغيّر |
| 5 | جداول الوسوم الداخلية الجديدة التي تستخدم محركًا من عائلة `MergeTree` تحصل افتراضيًا على فهرس نصي `keyValuePairs` على الخريطة `tags` (انظر [جدول الوسوم](#tags-table)) |

# الدوال

فيما يلي قائمة بالدوال التي تقبل جدول `TimeSeries` كوسيطة:

* [timeSeriesSamples](/ar/reference/functions/table-functions/timeSeriesSamples)
* [timeSeriesTags](/ar/reference/functions/table-functions/timeSeriesTags)
* [timeSeriesMetricFamilies](/ar/reference/functions/table-functions/timeSeriesMetricFamilies)
