ما هي أقسام الجدول في ClickHouse؟
تُجمِّع أقسام الجدول أجزاء البيانات الخاصة بجدول ضمن عائلة محركات MergeTree في وحدات منطقية منظَّمة، وهي طريقة لتنظيم البيانات بما يجعلها ذات دلالة مفاهيمية ومتوافقة مع معايير محددة، مثل النطاقات الزمنية أو الفئات أو السمات الرئيسية الأخرى. وتُسهِّل هذه الوحدات المنطقية إدارة البيانات والاستعلام عنها وتحسينها.
PARTITION BY
PARTITION BY toStartOfMonth(date)، التي تنظّم أجزاء بيانات الجدول بحسب أشهر مبيعات العقارات:
البنية على القرص
يقوم ClickHouse server أولًا بتقسيم الصفوف في مثال الإدراج، الذي يتضمن 4 صفوف كما هو موضح في المخطط أعلاه، وفقًا لقيمة مفتاح القسم
toStartOfMonth(date).
ثم تُعالَج الصفوف، لكل قسم تم تحديده، كالمعتاد من خلال تنفيذ عدة خطوات متسلسلة (① الفرز، ② التقسيم إلى أعمدة، ③ الضغط، ④ الكتابة إلى القرص).
لاحظ أنه عند تمكين التقسيم، ينشئ ClickHouse تلقائيًا فهارس MinMax لكل جزء بيانات. وهي ببساطة ملفات لكل عمود في الجدول مستخدم في تعبير مفتاح القسم، وتحتوي على القيمتين الصغرى والكبرى لذلك العمود داخل جزء البيانات.
عمليات الدمج داخل كل قسم
كما يوضّح المخطط أعلاه، لا تُدمَج الأجزاء التابعة لأقسام مختلفة مطلقًا. وإذا اخترت مفتاح تقسيم ذي عددية مرتفعة، فستتوزع الأجزاء على آلاف الأقسام، ولن تصبح مرشحة للدمج أبدًا، ما يؤدي إلى تجاوز الحدود المضبوطة مسبقًا والتسبب في ظهور الخطأ المزعج
Too many parts. وحل هذه المشكلة بسيط: اختر مفتاح تقسيم مناسبًا ذي عددية أقل من 1000..10000.
مراقبة الأقسام
_partition_value:
بدلاً من ذلك، يتتبع ClickHouse جميع الأجزاء والأقسام لكل الجداول في جدول النظام system.parts، ويُرجع الاستعلام التالي لجدول المثال أعلاه قائمةً بجميع الأقسام، بالإضافة إلى العدد الحالي من الأجزاء النشطة وإجمالي الصفوف في هذه الأجزاء لكل قسم:
فيما تُستخدم أقسام الجدول؟
إدارة البيانات
toStartOfMonth(date)، فستُحذف الأقسام كاملةً (وهي مجموعات من أجزاء الجدول) التي تستوفي شرط TTL، مما يجعل عملية التنظيف أكثر كفاءة، من دون الحاجة إلى إعادة كتابة الأجزاء.
وبالمثل، بدلًا من حذف البيانات القديمة، يمكن نقلها تلقائيًا وبكفاءة إلى فئة تخزين أقل تكلفة:
تحسين الاستعلام
date) المُستخدَم في مفتاح تقسيم الجدول وعمود (town) المُستخدَم في المفتاح الأساسي للجدول (مع العلم أن date ليس جزءًا من المفتاح الأساسي).
يعالج ClickHouse هذا الاستعلام من خلال تطبيق سلسلة من تقنيات تقليم البيانات لتجنّب فحص البيانات غير ذات الصلة:
① تقليم الأقسام: تُستخدَم فهارس MinMax لتجاهل أقسام كاملة (مجموعات من الأجزاء) لا يمكن منطقيًا أن تطابق عامل التصفية في الاستعلام على الأعمدة المستخدمة في مفتاح تقسيم الجدول. ② تقليم الحبيبات: بالنسبة إلى أجزاء البيانات المتبقية بعد الخطوة ①، يُستخدَم الفهرس الأساسي لتجاهل جميع الحبيبات (كتل من الصفوف) التي لا يمكن منطقيًا أن تطابق عامل التصفية في الاستعلام على الأعمدة المستخدمة في المفتاح الأساسي للجدول. يمكننا ملاحظة خطوات تقليم البيانات هذه من خلال فحص خطة تنفيذ الاستعلام الفعلية لاستعلام المثال المذكور أعلاه باستخدام عبارة EXPLAIN:
date لتحديد 11 من أصل 3257 حبيبة (كتل من الصفوف) مخزَّنة في جزء بيانات نشط واحد من أصل 436 جزء بيانات نشط موجود، وتحتوي على صفوف تطابق عامل التصفية date الخاص بالاستعلام.
② تقليم الحبيبة: تشير الأسطر من 19 إلى 24 من ناتج EXPLAIN أعلاه إلى أن ClickHouse يستخدم بعد ذلك الفهرس الأساسي (الذي أُنشئ على الحقل town) لجزء البيانات الذي جرى تحديده في الخطوة ①، لتقليل عدد الحبيبات أكثر (التي تحتوي على صفوف قد تطابق أيضًا عامل التصفية town الخاص بالاستعلام) من 11 إلى 1. وينعكس ذلك أيضًا في ناتج ClickHouse-client الذي طبعناه أعلاه للاستعلام المُنفَّذ:
يُعد التقسيم في المقام الأول ميزة لإدارة البيانات
uk_price_paid_simple_partitioned على أكثر من 600 قسم، وبالتالي على 600 306 من أجزاء البيانات النشطة. أما جدولنا غير المُقسَّم uk_price_paid_simple، فقد أمكن دمج جميع أجزاء البيانات الأولية فيه في جزء نشط واحد عبر عمليات الدمج في الخلفية.
عندما نتحقق من خطة التنفيذ الفعلية للاستعلام باستخدام عبارة EXPLAIN لاستعلام المثال أعلاه، من دون مُرشِّح للقسم، عند تشغيله على الجدول المُقسَّم، يمكننا أن نرى في الصفين 19 و20 من المخرجات أدناه أن ClickHouse حدّد 671 من أصل 3257 حبيبة موجودة (كتل من الصفوف)، موزعة على 431 من أصل 436 جزء بيانات نشط موجود، قد تحتوي على صفوف تطابق مُرشِّح الاستعلام، ولذلك سيجري محرك الاستعلام مسحها ومعالجتها: