ما هي دمج الأجزاء في ClickHouse؟
يتميّز ClickHouse بالسرعة ليس فقط في الاستعلامات، بل أيضًا في عمليات الإدراج، وذلك بفضل طبقة التخزين التي تعمل بأسلوب مشابه لـ LSM trees: ① تؤدي عمليات الإدراج (في الجداول من عائلة محرك MergeTree) إلى إنشاء أجزاء بيانات مرتبة وغير قابلة للتغيير. ② تُنقَل كل معالجة البيانات إلى دمج الأجزاء في الخلفية. وهذا يجعل عمليات كتابة البيانات خفيفة وعالية الكفاءة. وللتحكم في عدد الأجزاء لكل جدول وتنفيذ ② أعلاه، يدمج ClickHouse باستمرار الأجزاء الأصغر في أجزاء أكبر في الخلفية (ضمن كل partition) إلى أن تصل إلى حجم مضغوط يقارب ~150 GB. يوضح المخطط التالي بإيجاز عملية الدمج في الخلفية:
تزداد قيمة
merge level للجزء بمقدار واحد مع كل عملية دمج إضافية. ويعني المستوى 0 أن الجزء جديد ولم يُدمج بعد. أما الأجزاء التي دُمجت في أجزاء أكبر فتُعلَّم على أنها غير نشطة ثم تُحذف نهائيًا بعد مدة قابلة للتهيئة (8 دقائق افتراضيًا). ومع مرور الوقت، يؤدي ذلك إلى تكوين شجرة من الأجزاء المدمجة. ومن هنا جاءت تسمية جدول MergeTree.
مراقبة عمليات الدمج
/merges، ويمكن استخدامها لتصوير جميع دمج الأجزاء لجدولنا التجريبي:
تُظهر لوحة المعلومات المسجَّلة أعلاه العملية كاملة، بدءًا من عمليات إدراج البيانات الأولية وصولًا إلى الدمج النهائي في جزء واحد: ① عدد الأجزاء النشطة. ② دمج الأجزاء، ممثَّلة بصريًا بمربعات (يعكس الحجم حجم الجزء). ③ تضخيم الكتابة.
عمليات دمج متزامنة
ينفّذ كل خيط دمج حلقةً على النحو التالي:
1
تحميل الأجزاء إلى الذاكرة
يحدّد الأجزاء التي ستُدمج بعد ذلك، ويحمّلها إلى الذاكرة.
2
دمج الأجزاء
يدمج الأجزاء الموجودة في الذاكرة في جزء أكبر.
3
الكتابة إلى القرص
يكتب الجزء المدمج إلى القرص، ثم يعود إلى الخطوة 1.
عمليات الدمج الموفّرة للذاكرة
آليات الدمج
تُنفَّذ عملية دمج الأجزاء على عدة خطوات:
1
فك الضغط والتحميل
تُفك ضغط ملفات الأعمدة الثنائية المضغوطة الخاصة بالأجزاء المراد دمجها وتُحمَّل إلى الذاكرة.
2
الدمج
تُدمَج البيانات في ملفات أعمدة أكبر.
3
الفهرسة
يُنشأ فهرس أساسي متناثر جديد لملفات الأعمدة المدمجة.
عمليات الدمج القياسية
تنشئ عبارة DDL في المخطط أعلاه جدول
MergeTree بمفتاح فرز (town, street)، ما يعني أن البيانات على القرص تُرتَّب وفقًا لهذه الأعمدة، ويُنشأ تبعًا لذلك فهرس أساسي متناثر.
تُدمَج ② أعمدة الجدول ① المفكوكة الضغط والمرتبة مسبقًا مع الحفاظ على الترتيب العام للفرز في الجدول كما يحدده مفتاح الفرز، ويُنشأ ③ فهرس أساسي متناثر جديد، ثم تُضغط ④ ملفات الأعمدة المدمجة والفهرس وتُخزَّن كجزء بيانات جديد على القرص.
عمليات دمج ReplacingMergeTree
تنشئ عبارة DDL في المخطط أعلاه جدول
ReplacingMergeTree بمفتاح فرز (town, street, id)، ما يعني أن البيانات على القرص تُرتَّب بحسب هذه الأعمدة، ويُنشأ تبعًا لذلك فهرس أساسي متناثر.
وتعمل عملية الدمج ② بطريقة مشابهة لما يحدث في جدول MergeTree قياسي، إذ تجمع الأعمدة المفكوك ضغطها والمفروزة مسبقًا مع الحفاظ على ترتيب الفرز العام.
ومع ذلك، يزيل ReplacingMergeTree الصفوف المكررة التي لها مفتاح الفرز نفسه، ولا يُبقي إلا على أحدث صف استنادًا إلى الطابع الزمني لإنشاء الجزء الذي يحتويه.
عمليات الدمج بالتجميع
تُعرِّف عبارة DDL في المخطط أعلاه جدول
SummingMergeTree بحيث يكون town مفتاح الفرز، ما يعني أن البيانات على القرص تُرتَّب وفقًا لهذا العمود، ويُنشأ تبعًا لذلك فهرس أساسي متناثر.
في خطوة الدمج ②، يستبدل ClickHouse جميع الصفوف التي لها مفتاح الفرز نفسه بصف واحد، مع جمع قيم الأعمدة الرقمية.
عمليات الدمج التجميعية
SummingMergeTree الوارد أعلاه صيغة متخصصة من جدول AggregatingMergeTree، ويتيح التحويل التلقائي التزايدي للبيانات من خلال تطبيق أيٍ من دوال التجميع البالغ عددها [90+] أثناء دمج الأجزاء:
تُنشئ عبارة DDL في المخطط أعلاه جدول
AggregatingMergeTree مع town بوصفه مفتاح الفرز، مما يضمن ترتيب البيانات حسب هذا العمود على القرص وإنشاء فهرس أساسي متناظر مطابق.
أثناء ② الدمج، يستبدل ClickHouse جميع الصفوف التي لها مفتاح الفرز نفسه بصف واحد يخزّن حالات التجميع الجزئية (مثل sum وcount من أجل avg()). وتضمن هذه الحالات نتائج دقيقة من خلال عمليات الدمج التزايدية في الخلفية.