نظرة عامة على الإسقاطات
تخزّن الإسقاطات البيانات بصيغة تُحسّن تنفيذ الاستعلامات، وتكون هذه الميزة مفيدة في الحالات التالية:- تشغيل استعلامات على عمود ليس جزءًا من المفتاح الأساسي
- إجراء تجميع مسبق للأعمدة، مما يقلل كلاً من العمليات الحسابية وIO
استخدام القرصتُنشئ الإسقاطات داخليًا جدولًا مخفيًا جديدًا، ما يعني الحاجة إلى مزيد من 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 بقيمته عبر عمليات الدمج والتعديلات، مما يجعله مفيدًا للفهرسة الثانوية. ويمكننا الاستفادة من ذلك في الاستعلامات:
مثال على إسقاط مع عبارة WHERE
يمكن أن تتضمن الـ إسقاطات عبارة WHERE لتخزين مجموعة فرعية فقط من الصفوف. ويكون ذلك مفيدًا عندما تُصفّي الاستعلامات كثيرًا باستخدام شرط معروف، إذ لا تُخزِّن الـ إسقاط إلا الصفوف المطابقة، مما يقلل التخزين ويحسّن أداء الاستعلامات.
إنشاء جدول وإضافة إسقاط مُرشَّحة:
WHERE الخاصة بالاستعلام عبارة WHERE الخاصة بالإسقاط (أي إن كل شرط في عامل تصفية الإسقاط موجود أيضًا في عامل تصفية الاستعلام)، يمكن للمُحسِّن استخدام الإسقاط تلقائيًا إذا حدّد أن ذلك مفيد:
إدارة الإسقاطات
تتوفّر العمليات التالية على الإسقاطات:ADD PROJECTION
استخدم تعليمة SQL التالية لإضافة وصف لإسقاط إلى البيانات الوصفية لجدول:عندما يحدِّد الإسقاط عبارة
WHERE، لا تُجسَّد إلا الصفوف التي تطابق الشرط. ويمكن للمُحسِّن استخدام هذا الإسقاط عندما يستلزم WHERE الخاص بالاستعلام منطقيًا WHERE الخاص بالإسقاط، وكان الإسقاط مفيدًا لخطة الاستعلام. وينطبق ذلك على كلٍّ من الإسقاطات العادية والإسقاطات التجميعية.عبارة WITH SETTINGS
تُعرِّف WITH SETTINGS إعدادات على مستوى الإسقاط، والتي تُخصِّص كيفية تخزين البيانات في الإسقاط (على سبيل المثال، index_granularity أو index_granularity_bytes).
وتقابل هذه الإعدادات مباشرةً إعدادات جدول MergeTree، لكنها تنطبق على هذا الإسقاط فقط.
مثال:
MODIFY PROJECTION
استخدم العبارة التالية لتعديل عبارةWITH SETTINGS في إسقاط موجود دون إعادة بناء بياناته:
INDEX بدلًا من استعلام SELECT:
WITH SETTINGS فقط.
يجب أن يظل استعلام الإسقاط نفسه (أو، بالنسبة إلى فهرس الإسقاط، تعبير الفهرس ونوعه) دون تغيير، لأن أجزاء الإسقاط الحالية تخزّن بيانات مُنشأة منه؛ ولتغييره، استخدم DROP PROJECTION ثم ADD PROJECTION.
لا تغيّر التعليمة سوى البيانات الوصفية للجدول ولا تعيد كتابة أي بيانات: تحتفظ أجزاء الإسقاط الحالية بالإعدادات التي كُتبت بها، بينما تستخدم أجزاء الإسقاط التي تُنشئها عمليات الإدراج والدمج المستقبلية الإعدادات الجديدة.
ولا تطبّق MATERIALIZE PROJECTION أيضًا الإعدادات الجديدة على الأجزاء الحالية، إذ تقتصر على بناء الإسقاط في الأجزاء التي يكون فيها مفقودًا أو تالفًا، وتترك أجزاء الإسقاط الموجودة مسبقًا كما هي.
لإعادة بناء الأجزاء الحالية بالإعدادات الجديدة، شغّل CLEAR PROJECTION ثم MATERIALIZE PROJECTION، أو ادمج الأجزاء، على سبيل المثال باستخدام OPTIMIZE TABLE ... FINAL.
مثال:
DROP PROJECTION
استخدم التعليمة التالية لإزالة وصف الإسقاط من البيانات الوصفية للجداول وحذف ملفات الإسقاط من القرص. يُنفَّذ هذا على شكل mutation.MATERIALIZE PROJECTION
استخدم العبارة أدناه لبناء الإسقاطname في أجزاء البيانات التي يكون فيها مفقودًا أو تالفًا، مع إمكانية قصر ذلك على القسم partition_name فقط.
تبقى أجزاء البيانات التي تحتوي على الإسقاط مسبقًا دون تغيير، حتى لو عُدِّلت إعدادات الإسقاط باستخدام MODIFY PROJECTION بعد كتابتها؛ ولإعادة بنائها، نفِّذ CLEAR PROJECTION أولًا.
يُنفَّذ ذلك على هيئة تعديل.
CLEAR PROJECTION
استخدم التعليمة أدناه لحذف ملفات الإسقاط من القرص من دون إزالة التعريف. يُنفَّذ ذلك على شكل mutation.ADD وMODIFY و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 أو ضمِّن التعبير مباشرةً: