الانتقال إلى المحتوى الرئيسي
تتناول هذه الصفحة ماهية الإسقاطات، وكيفية استخدامها، والخيارات المختلفة لإدارتها.

نظرة عامة على الإسقاطات

تخزّن الإسقاطات البيانات بصيغة تُحسّن تنفيذ الاستعلامات، وتكون هذه الميزة مفيدة في الحالات التالية:
  • تشغيل استعلامات على عمود ليس جزءًا من المفتاح الأساسي
  • إجراء تجميع مسبق للأعمدة، مما يقلل كلاً من العمليات الحسابية وIO
يمكنك تعريف إسقاط واحد أو أكثر لجدول، وأثناء تحليل الاستعلام سيختار ClickHouse الإسقاط الذي يتطلب مسح أقل قدر من البيانات، وذلك من دون تعديل الاستعلام الذي قدّمه المستخدم.
استخدام القرصتُنشئ الإسقاطات داخليًا جدولًا مخفيًا جديدًا، ما يعني الحاجة إلى مزيد من IO ومساحة أكبر على القرص. على سبيل المثال، إذا كان الإسقاط يعرّف مفتاحًا أساسيًا مختلفًا، فستُنسخ جميع البيانات من الجدول الأصلي.
يمكنك الاطلاع على مزيد من التفاصيل التقنية حول كيفية عمل الإسقاطات داخليًا في هذه الصفحة.

استخدام الإسقاطات

مثال على التصفية دون استخدام المفاتيح الأساسية

إنشاء الجدول:
باستخدام ALTER TABLE، يمكننا إضافة الإسقاط إلى جدولٍ موجود:
إدخال البيانات:
سيتيح لنا الإسقاط إجراء تصفية حسب user_name بسرعة، حتى لو لم يكن user_name مُعرَّفًا في الجدول الأصلي بوصفه PRIMARY_KEY. أثناء تنفيذ الاستعلام، يحدّد ClickHouse أن مقدارًا أقل من البيانات سيُعالَج إذا استُخدم الإسقاط، لأن البيانات مرتبة حسب user_name.
للتحقق من أن استعلامًا يستخدم الإسقاط، يمكننا مراجعة جدول system.query_log. في الحقل projections يظهر اسم الإسقاط المستخدم، أو يكون الحقل فارغًا إذا لم يُستخدم أي إسقاط:

مثال على استعلام التجميع المسبق

أنشئ الجدول باستخدام الإسقاط projection_visits_by_user:
أدرِج البيانات:
نفّذ أول استعلام باستخدام GROUP BY مع الحقل user_agent. لن يستخدم هذا الاستعلام الـ إسقاط المعرّف لأن التجميع المسبق لا يتطابق.
لاستخدام الإسقاط، يمكنك تنفيذ استعلامات تحدد بعض حقول التجميع المسبق وGROUP BY أو جميعها:
كما ذُكر سابقًا، يمكنك مراجعة جدول system.query_log لمعرفة ما إذا كان قد استُخدم أي إسقاط. ويعرض الحقل projections اسم الـ إسقاط المستخدم. وسيكون فارغًا إذا لم يُستخدم أي إسقاط:

إنشاء فهارس الإسقاط واستخدامها

إنشاء فهرس إسقاط:
إدراج بعض البيانات النموذجية:
يحتفظ الحقل _part_offset بقيمته عبر عمليات الدمج والتعديلات، مما يجعله مفيدًا للفهرسة الثانوية. ويمكننا الاستفادة من ذلك في الاستعلامات:

إدارة الإسقاطات

تتوفّر العمليات التالية على الإسقاطات:

ADD PROJECTION

استخدم العبارة أدناه لإضافة وصف إسقاط إلى البيانات الوصفية للجدول:

عبارة WITH SETTINGS

تُعرِّف WITH SETTINGS إعدادات على مستوى الإسقاط، والتي تُخصِّص كيفية تخزين البيانات في الإسقاط (على سبيل المثال، index_granularity أو index_granularity_bytes). وتقابل هذه الإعدادات مباشرةً إعدادات جدول MergeTree، لكنها تنطبق على هذا الإسقاط فقط. مثال:
تحلّ إعدادات الإسقاط محل إعدادات الجدول المطبَّقة فعليًا على الإسقاط، مع مراعاة قواعد التحقق (على سبيل المثال، سيُرفض أي تجاوز غير صالح أو غير متوافق).

DROP PROJECTION

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

MATERIALIZE PROJECTION

استخدم التعليمة أدناه لإعادة بناء الإسقاط name في القسم partition_name. يُنفَّذ ذلك على هيئة mutation.

CLEAR PROJECTION

استخدم التعليمة أدناه لحذف ملفات الإسقاط من القرص من دون إزالة التعريف. يُنفَّذ ذلك على شكل mutation.
تُعد الأوامر ADD وDROP وCLEAR خفيفة الوزن، بمعنى أنها لا تغيّر سوى البيانات الوصفية أو تزيل الملفات. بالإضافة إلى ذلك، فهي تدعم النسخ المتماثل وتُزامِن البيانات الوصفية للإسقاط عبر ClickHouse Keeper أو ZooKeeper.
لا يُدعَم التعامل مع الإسقاطات إلا في الجداول التي تستخدم محرك *MergeTree (بما في ذلك المتغيرات ذات النسخ المتماثل).

التحكم في سلوك دمج الإسقاطات

عند تنفيذ استعلام، يختار ClickHouse بين القراءة من الجدول الأصلي أو من أحد الإسقاطات التابعة له. ويُتخذ قرار القراءة من الجدول الأصلي أو من أحد إسقاطاته بشكل منفصل لكل جزء بيانات. يهدف ClickHouse عمومًا إلى قراءة أقل قدر ممكن من البيانات، ويستخدم عدة أساليب لتحديد أفضل جزء للقراءة منه، مثل أخذ عيّنة من المفتاح الأساسي للجزء. وفي بعض الحالات، لا تكون لأجزاء الجدول المصدر أجزاء إسقاط مقابلة. وقد يحدث هذا، على سبيل المثال، لأن إنشاء إسقاط لجدول في SQL يكون “lazy” افتراضيًا، أي إنه يؤثر فقط في البيانات المُدرجة حديثًا ويُبقي الأجزاء الموجودة كما هي. وبما أن أحد الإسقاطات يحتوي بالفعل على قيم مجمّعة ومحسوبة مسبقًا، يحاول ClickHouse القراءة من أجزاء الإسقاط المقابلة لتجنّب تنفيذ التجميع مرة أخرى أثناء تشغيل الاستعلام. وإذا كان جزء معيّن يفتقر إلى جزء الإسقاط المقابل، فسيعود تنفيذ الاستعلام إلى الجزء الأصلي. لكن ماذا يحدث إذا تغيّرت الصفوف في الجدول الأصلي بطريقة غير بسيطة نتيجة عمليات الدمج غير البسيطة في الخلفية لأجزاء البيانات؟ على سبيل المثال، افترض أن الجدول مخزّن باستخدام محرك الجدول ReplacingMergeTree. إذا جرى اكتشاف الصف نفسه في عدة أجزاء إدخال أثناء الدمج، فلن يُحتفَظ إلا بأحدث إصدار من الصف (من الجزء المُدرَج أخيرًا)، بينما ستُهمَل جميع الإصدارات الأقدم. وبالمثل، إذا كان الجدول مخزّنًا باستخدام محرك الجدول AggregatingMergeTree، فقد تؤدي عملية الدمج إلى طيّ الصفوف المتطابقة في أجزاء الإدخال (استنادًا إلى قيم المفتاح الأساسي) في صف واحد لتحديث حالات التجميع الجزئية. قبل ClickHouse v24.8، كانت أجزاء الإسقاط إما تفقد التزامن مع البيانات الأساسية بصمت، أو أن بعض العمليات مثل التحديثات وعمليات الحذف لم يكن ممكنًا تشغيلها مطلقًا لأن قاعدة البيانات كانت تطرح استثناءً تلقائيًا إذا كان للجدول إسقاطات. اعتبارًا من v24.8، يتحكم إعداد جديد على مستوى الجدول deduplicate_merge_projection_mode في السلوك عند حدوث عمليات الدمج غير البسيطة المذكورة أعلاه في أجزاء الجدول الأصلي. تُعد Delete mutations مثالًا آخر على عمليات دمج الأجزاء التي تُسقط صفوفًا من أجزاء الجدول الأصلي. واعتبارًا من v24.7، يتوفر أيضًا إعداد للتحكم في السلوك فيما يتعلق بـ delete mutations التي تُفعَّل بواسطة lightweight deletes: lightweight_mutation_projection_mode. فيما يلي القيم الممكنة لكل من deduplicate_merge_projection_mode وlightweight_mutation_projection_mode:
  • throw (الافتراضي): يُطرَح استثناء، مما يمنع أجزاء الإسقاط من فقدان التزامن.
  • drop: تُسقَط أجزاء جدول الإسقاط المتأثرة. وستعود الاستعلامات إلى جزء الجدول الأصلي بالنسبة إلى أجزاء الإسقاط المتأثرة.
  • rebuild: يُعاد بناء جزء الإسقاط المتأثر ليظل متسقًا مع البيانات الموجودة في جزء الجدول الأصلي.

القيود

لا يمكن استخدام عمود ALIAS ضمن عبارة ORDER BY الخاصة بالإسقاط. على سبيل المثال:
أعمدة ALIAS لا تُخزَّن فعليًا، بل تُحتسَب أثناء تنفيذ الاستعلام، لذا لا تكون متاحة ضمن مسار كتابة جزء الإسقاط عند تقييم تعبير الترتيب. بدلًا من ذلك، استخدم أعمدة MATERIALIZED أو ضمِّن التعبير مباشرةً:

انظر أيضًا

آخر تعديل في ٢ يوليو ٢٠٢٦