> ## 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.

> يوفّر هذا المحرك تكاملًا للقراءة فقط مع جداول Apache Iceberg الحالية في Amazon S3 وAzure وHDFS والجداول المخزّنة محليًا.

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

<Warning>
  نوصي باستخدام [دالة جدول Iceberg](/ar/reference/functions/table-functions/iceberg) للعمل مع بيانات Iceberg في ClickHouse. يوفّر دالة جدول Iceberg حاليًا إمكانات كافية، مع تقديم واجهة جزئية للقراءة فقط لجداول Iceberg.

  يتوفر Iceberg محرك الجدول، لكنه قد يواجه بعض القيود. لم يُصمَّم ClickHouse في الأصل لدعم الجداول ذات المخططات التي تتغير خارجيًا، ما قد يؤثر في وظائف Iceberg محرك الجدول. ونتيجة لذلك، قد لا تتوفر بعض الميزات التي تعمل مع الجداول العادية، أو قد لا تعمل على نحو صحيح، خاصة عند استخدام المُحلِّل القديم.

  للحصول على أفضل توافق، نقترح استخدام دالة جدول Iceberg بينما نواصل تحسين دعم Iceberg محرك الجدول.
</Warning>

يوفّر هذا المحرك تكاملًا للقراءة فقط مع جداول Apache [Iceberg](https://iceberg.apache.org/) الحالية في Amazon S3 وAzure وHDFS والجداول المخزّنة محليًا.

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

لاحظ أن جدول Iceberg يجب أن يكون موجودًا بالفعل في التخزين، فهذا الأمر لا يأخذ معاملات DDL لإنشاء جدول جديد.

```sql theme={null}
CREATE TABLE iceberg_table_s3
    ENGINE = IcebergS3(url,  [, NOSIGN | access_key_id, secret_access_key, [session_token]], format, [,compression], [,extra_credentials])

CREATE TABLE iceberg_table_azure
    ENGINE = IcebergAzure(connection_string|storage_account_url, container_name, blobpath, [account_name, account_key, format, compression])

CREATE TABLE iceberg_table_hdfs
    ENGINE = IcebergHDFS(path_to_table, [,format] [,compression_method])

CREATE TABLE iceberg_table_local
    ENGINE = IcebergLocal(path_to_table, [,format] [,compression_method])
```

<div id="engine-arguments">
  ## وسيطات المحرك
</div>

وصف هذه الوسيطات مطابق لوصف الوسيطات في المحرّكات `S3` و`AzureBlobStorage` و`HDFS` و`File`، على الترتيب.
يشير `format` إلى تنسيق ملفات البيانات في جدول Iceberg.

بالنسبة إلى `IcebergS3`، يمكن استخدام المعامل الاختياري `extra_credentials` لتمرير `role_arn` من أجل الوصول المستند إلى الأدوار في ClickHouse Cloud. راجع [تأمين S3](/ar/products/cloud/guides/data-sources/accessing-s3-data-securely) للاطلاع على خطوات الإعداد.

يمكن تحديد معاملات المحرك باستخدام [المجموعات المُسمّاة](/ar/concepts/features/configuration/server-config/named-collections)

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

```sql theme={null}
CREATE TABLE iceberg_table ENGINE=IcebergS3('http://test.s3.amazonaws.com/clickhouse-bucket/test_table', 'test', 'test')
```

باستخدام المجموعات المُسمّاة:

```xml theme={null}
<clickhouse>
    <named_collections>
        <iceberg_conf>
            <url>http://test.s3.amazonaws.com/clickhouse-bucket/</url>
            <access_key_id>test</access_key_id>
            <secret_access_key>test</secret_access_key>
        </iceberg_conf>
    </named_collections>
</clickhouse>
```

```sql theme={null}
CREATE TABLE iceberg_table ENGINE=IcebergS3(iceberg_conf, filename = 'test_table')

```

<div id="aliases">
  ## الأسماء البديلة
</div>

يكتشف محرك الجدول `Iceberg` خلفية التخزين تلقائيًا من إعداد `disk`، ثم يوجّه إلى `IcebergS3` أو `IcebergAzure` أو `IcebergLocal` وفقًا لذلك. وعند عدم تحديد `disk`، يستخدم تنفيذ `IcebergS3` افتراضيًا.

<div id="data-types">
  ## أنواع البيانات
</div>

يوضح الجدول التالي كيفية مطابقة أنواع بيانات Iceberg مع أنواع بيانات ClickHouse أثناء استنتاج المخطط (لأغراض القراءة).

<div id="primitive-types">
  ### الأنواع الأولية
</div>

| نوع Iceberg        | نوع ClickHouse         | ملاحظات                                                 |
| ------------------ | ---------------------- | ------------------------------------------------------- |
| `boolean`          | `Bool`                 |                                                         |
| `int`              | `Int32`                |                                                         |
| `long`, `bigint`   | `Int64`                |                                                         |
| `float`            | `Float32`              |                                                         |
| `double`           | `Float64`              |                                                         |
| `date`             | `Date32`               |                                                         |
| `time`             | `Int64`                | ميكروثانية منذ منتصف الليل                              |
| `timestamp`        | `DateTime64(6)`        | ميكروثانية، من دون منطقة زمنية                          |
| `timestamptz`      | `DateTime64(6, 'UTC')` | ميكروثانية، بتوقيت UTC                                  |
| `timestamp_ns`     | `DateTime64(9)`        | نانوثانية، من دون منطقة زمنية (بدءًا من Iceberg v3 فقط) |
| `timestamptz_ns`   | `DateTime64(9, 'UTC')` | نانوثانية، بتوقيت UTC (بدءًا من Iceberg v3 فقط)         |
| `string`, `binary` | `String`               |                                                         |
| `uuid`             | `UUID`                 |                                                         |
| `fixed(N)`         | `FixedString(N)`       |                                                         |
| `decimal(P, S)`    | `Decimal(P, S)`        |                                                         |

<div id="complex-types">
  ### الأنواع المركبة
</div>

| نوع Iceberg | نوع ClickHouse |
| ----------- | -------------- |
| `list`      | `Array`        |
| `map`       | `Map`          |
| `struct`    | `Tuple`        |

<div id="schema-evolution">
  ## تطور المخطط
</div>

يدعم ClickHouse قراءة جداول Iceberg التي تطور مخططها بمرور الوقت. ويشمل ذلك الجداول التي أُضيفت إليها أعمدة أو أُزيلت منها أو أُعيد ترتيبها، وكذلك الأعمدة التي تغيّرت من required إلى Nullable. بالإضافة إلى ذلك، تكون تحويلات الأنواع التالية مدعومة:

* int -> long
* float -> double
* decimal(P, S) -> decimal(P', S) where P' > P.

حاليًا، لا يمكن تغيير البُنى المتداخلة أو أنواع العناصر داخل Array وMap.

لقراءة جدول تغيّر مخططه بعد إنشائه باستخدام الاستدلال الديناميكي على المخطط، اضبط allow\_dynamic\_metadata\_for\_data\_lakes = true عند إنشاء الجدول.

<div id="partition-pruning">
  ## تشذيب الأقسام
</div>

يدعم ClickHouse تشذيب الأقسام أثناء استعلامات SELECT على جداول Iceberg، مما يساعد على تحسين أداء الاستعلام من خلال تخطي ملفات البيانات غير ذات الصلة. لتمكين تشذيب الأقسام، اضبط `use_iceberg_partition_pruning = 1`. لمزيد من المعلومات حول تشذيب أقسام Iceberg، راجع [https://iceberg.apache.org/spec/#partitioning](https://iceberg.apache.org/spec/#partitioning)

<div id="time-travel">
  ## السفر عبر الزمن
</div>

يدعم ClickHouse ميزة السفر عبر الزمن في جداول Iceberg، ما يتيح لك الاستعلام عن البيانات التاريخية باستخدام طابع زمني محدد أو معرّف لقطة.

<div id="deleted-rows">
  ## معالجة الجداول ذات الصفوف المحذوفة
</div>

يدعم ClickHouse قراءة جداول Iceberg التي تستخدم طرق الحذف التالية:

* [الحذف بحسب الموضع](https://iceberg.apache.org/spec/#position-delete-files)
* [الحذف بحسب المساواة](https://iceberg.apache.org/spec/#equality-delete-files) (مدعوم بدءًا من الإصدار 25.8+)

طريقة الحذف التالية **غير مدعومة**:

* [متجهات الحذف](https://iceberg.apache.org/spec/#deletion-vectors) (طُرحت في v3)

<div id="basic-usage">
  ### الاستخدام الأساسي
</div>

```sql theme={null}
 SELECT * FROM example_table ORDER BY 1 
 SETTINGS iceberg_timestamp_ms = 1714636800000
```

```sql theme={null}
 SELECT * FROM example_table ORDER BY 1 
 SETTINGS iceberg_snapshot_id = 3547395809148285433
```

ملاحظة: لا يمكنك تحديد كلٍ من `iceberg_timestamp_ms` و`iceberg_snapshot_id` كمعاملَين في الاستعلام نفسه.

<div id="important-considerations">
  ### اعتبارات مهمة
</div>

* **تُنشأ اللقطات** عادةً في الحالات التالية:
  * عند كتابة بيانات جديدة إلى الجدول
  * عند إجراء نوع من دمج البيانات

* **لا تؤدي تغييرات المخطط عادةً إلى إنشاء لقطات** - وهذا يترتب عليه سلوكيات مهمة عند استخدام السفر عبر الزمن مع الجداول التي خضعت لتطور المخطط.

<div id="example-scenarios">
  ### سيناريوهات نموذجية
</div>

جميع هذه السيناريوهات مكتوبة باستخدام Spark لأن CH لا يدعم الكتابة إلى جداول Iceberg حتى الآن.

<div id="scenario-1">
  #### السيناريو 1: تغييرات المخطط دون لقطات جديدة
</div>

ضع في اعتبارك تسلسل العمليات التالي:

```sql theme={null}
 -- Create a table with two columns
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2')

-- Insert data into the table
  INSERT INTO spark_catalog.db.time_travel_example VALUES 
    (1, 'Mars')

  ts1 = now() // A piece of pseudo code

-- Alter table to add a new column
  ALTER TABLE spark_catalog.db.time_travel_example ADD COLUMN (price double)
 
  ts2 = now()

-- Insert data into the table
  INSERT INTO spark_catalog.db.time_travel_example VALUES (2, 'Venus', 100)

   ts3 = now()

-- Query the table at each timestamp
  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts1;

+------------+------------+
|order_number|product_code|
+------------+------------+
|           1|        Mars|
+------------+------------+
  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts2;

+------------+------------+
|order_number|product_code|
+------------+------------+
|           1|        Mars|
+------------+------------+

  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts3;

+------------+------------+-----+
|order_number|product_code|price|
+------------+------------+-----+
|           1|        Mars| NULL|
|           2|       Venus|100.0|
+------------+------------+-----+
```

نتائج الاستعلام عند طوابع زمنية مختلفة:

* عند ts1 وts2: لا يظهر سوى العمودين الأصليين
* عند ts3: تظهر الأعمدة الثلاثة كلها، وتكون قيمة السعر في الصف الأول NULL

<div id="scenario-2">
  #### السيناريو 2: الاختلافات بين المخطط التاريخي والمخطط الحالي
</div>

قد يُظهر استعلام السفر عبر الزمن في اللحظة الحالية مخططًا يختلف عن مخطط الجدول الحالي:

```sql theme={null}
-- Create a table
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example_2 (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2')

-- Insert initial data into the table
  INSERT INTO spark_catalog.db.time_travel_example_2 VALUES (2, 'Venus');

-- Alter table to add a new column
  ALTER TABLE spark_catalog.db.time_travel_example_2 ADD COLUMN (price double);

  ts = now();

-- Query the table at a current moment but using timestamp syntax

  SELECT * FROM spark_catalog.db.time_travel_example_2 TIMESTAMP AS OF ts;

    +------------+------------+
    |order_number|product_code|
    +------------+------------+
    |           2|       Venus|
    +------------+------------+

-- Query the table at a current moment
  SELECT * FROM spark_catalog.db.time_travel_example_2;
    +------------+------------+-----+
    |order_number|product_code|price|
    +------------+------------+-----+
    |           2|       Venus| NULL|
    +------------+------------+-----+
```

يحدث هذا لأن `ALTER TABLE` لا يُنشئ لقطة جديدة، لكن بالنسبة إلى الجدول الحالي، يأخذ Spark قيمة `schema_id` من أحدث ملف metadata، وليس من لقطة.

<div id="scenario-3">
  #### السيناريو 3: اختلافات المخطط التاريخي مقارنةً بالحالي
</div>

أما الحالة الثانية فهي أنه عند استخدام السفر عبر الزمن، لا يمكنك الوصول إلى حالة الجدول قبل كتابة أي بيانات فيه:

```sql theme={null}
-- Create a table
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example_3 (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2');

  ts = now();

-- Query the table at a specific timestamp
  SELECT * FROM spark_catalog.db.time_travel_example_3 TIMESTAMP AS OF ts; -- Finises with error: Cannot find a snapshot older than ts.
```

في ClickHouse، يكون السلوك متوافقًا مع Spark. يمكنك ببساطة اعتبار استعلامات Select في Spark بمثابة استعلامات Select في ClickHouse، وسيعمل الأمر بالطريقة نفسها.

<div id="metadata-file-resolution">
  ## تحديد موقع ملف metadata
</div>

عند استخدام محرك الجدول `Iceberg` في ClickHouse، يحتاج النظام إلى تحديد موقع ملف metadata.json الصحيح الذي يصف بنية جدول Iceberg. وتعمل عملية التحديد هذه على النحو التالي:

<div id="candidate-search">
  ### البحث عن الملفات المرشحة
</div>

1. **تحديد المسار مباشرةً**:

* إذا قمت بتعيين `iceberg_metadata_file_path`، فسيستخدم النظام هذا المسار كما هو بدمجه مع مسار دليل جدول Iceberg.
* عند توفير هذا الإعداد، يتم تجاهل جميع إعدادات الاستدلال الأخرى.

2. **مطابقة UUID الجدول**:

* إذا تم تحديد `iceberg_metadata_table_uuid`، فسيقوم النظام بما يلي:
  * النظر فقط في ملفات `.metadata.json` داخل دليل `metadata`
  * تصفية الملفات التي تحتوي على حقل `table-uuid` يطابق UUID الذي حددته (غير حساس لحالة الأحرف)

3. **البحث الافتراضي**:

* إذا لم يتم توفير أيٍّ من الإعدادين أعلاه، فستصبح جميع ملفات `.metadata.json` داخل دليل `metadata` ملفات مرشحة

<div id="most-recent-file">
  ### اختيار أحدث ملف
</div>

بعد تحديد الملفات المرشحة وفقًا للقواعد المذكورة أعلاه، يحدّد النظام الملف الأحدث بينها:

* إذا كان `iceberg_recent_metadata_file_by_last_updated_ms_field` مفعّلًا:
  * يُختار الملف الذي يحمل أكبر قيمة لـ `last-updated-ms`

* بخلاف ذلك:
  * يُختار الملف ذو أعلى رقم إصدار
  * (يظهر الإصدار على شكل `V` في أسماء الملفات المنسّقة بالشكل `V.metadata.json` أو `V-uuid.metadata.json`)

**ملاحظة**: جميع الإعدادات المذكورة (ما لم يُنصّ صراحةً على خلاف ذلك) هي إعدادات على مستوى المحرّك، ويجب تحديدها أثناء إنشاء الجدول كما هو موضّح أدناه:

```sql theme={null}
CREATE TABLE example_table ENGINE = Iceberg(
    's3://bucket/path/to/iceberg_table'
) SETTINGS iceberg_metadata_table_uuid = '6f6f6407-c6a5-465f-a808-ea8900e35a38';
```

**ملاحظة**: بينما تتولى كتالوجات Iceberg عادةً تحديد البيانات الوصفية، فإن محرك الجداول `Iceberg` في ClickHouse يفسّر مباشرةً الملفات المخزّنة في S3 باعتبارها جداول Iceberg، لذلك من المهم فهم قواعد التحديد هذه.

<div id="data-cache">
  ## ذاكرة التخزين المؤقت للبيانات
</div>

يدعم محرك الجدول `Iceberg` ودالة الجدول التخزين المؤقت للبيانات، تمامًا مثل أنظمة التخزين `S3` و`AzureBlobStorage` و`HDFS`. راجع [هنا](/ar/reference/engines/table-engines/integrations/s3#data-cache).

<div id="metadata-cache">
  ## ذاكرة التخزين المؤقت للبيانات الوصفية
</div>

يدعم كلٌّ من محرك الجدول ودالة الجدول `Iceberg` ذاكرةً مؤقتة للبيانات الوصفية تخزّن معلومات ملفات البيان وقائمة البيان وملف JSON للبيانات الوصفية. تُخزَّن هذه الذاكرة المؤقتة في الذاكرة. ويجري التحكّم في هذه الميزة عبر الإعداد `use_iceberg_metadata_files_cache`، وهو مفعّل افتراضيًا.

<div id="async-metadata-prefetch">
  ## الجلب المسبق غير المتزامن للبيانات الوصفية
</div>

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

إذا كانت هذه الميزة مُمكّنة، فسيشغّل الخادم عملية دورية في الخلفية لعرض الكتالوج البعيد واكتشاف إصدار جديد من البيانات الوصفية. ثم سيُحلّلها ويجتاز اللقطة بشكل تكراري، جالبًا ملفات manifest list النشطة وملفات manifest.
أما الملفات المتوفرة بالفعل في ذاكرة التخزين المؤقت للبيانات الوصفية، فلن يُعاد تنزيلها. وفي نهاية كل دورة جلب مسبق، تصبح أحدث لقطة للبيانات الوصفية متاحة في ذاكرة التخزين المؤقت للبيانات الوصفية.

```sql theme={null}
CREATE TABLE example_table ENGINE = Iceberg(
    's3://bucket/path/to/iceberg_table'
) SETTINGS
    iceberg_metadata_async_prefetch_period_ms = 60000;
```

للاستفادة إلى أقصى حد من الجلب المسبق غير المتزامن للبيانات الوصفية في عمليات القراءة، يجب تحديد المعلمة `iceberg_metadata_staleness_ms` كمعلمة على مستوى الاستعلام أو الجلسة. افتراضيًا (0 - غير محددة)، وفي سياق كل استعلام، سيجلب الخادم أحدث البيانات الوصفية من الكتالوج البعيد.
ومن خلال تحديد مقدار التحمّل لتقادم البيانات الوصفية، يُسمح للخادم باستخدام النسخة المخزنة مؤقتًا من لقطة البيانات الوصفية من دون استدعاء الكتالوج البعيد. إذا توفرت نسخة من البيانات الوصفية في الذاكرة المؤقتة، وكانت قد نُزِّلت ضمن نافذة التقادم المحددة، فستُستخدم لمعالجة الاستعلام.
وإلا فسيتم جلب أحدث نسخة من الكتالوج البعيد.

```sql theme={null}
SELECT count() FROM icebench_table WHERE ...
SETTINGS iceberg_metadata_staleness_ms=120000
```

**ملاحظة**: يعمل الجلب المسبق غير المتزامن للبيانات الوصفية ضمن `ICEBERG_SCEDULE_POOL`، وهي مجموعة مؤشرات ترابط على مستوى الخادم لعمليات الخلفية على جداول `Iceberg` النشطة. ويُتحكَّم في حجم مجموعة مؤشرات الترابط هذه بواسطة معلمة إعداد الخادم `iceberg_background_schedule_pool_size` (القيمة الافتراضية هي 10).

**ملاحظة**: التوقع الحالي هو أن يكون حجم ذاكرة التخزين المؤقت للبيانات الوصفية كافيًا للاحتفاظ بالكامل بأحدث لقطة للبيانات الوصفية لجميع الجداول النشطة، إذا كان الجلب المسبق غير المتزامن مُمكّنًا.

<div id="see-also">
  ## انظر أيضًا
</div>

* [دالة جدول Iceberg](/ar/reference/functions/table-functions/iceberg)
