تحياتي هابر.
إذا كان هناك شخص ما يقوم بتشغيل النظام
ClickHouse يحل المشاكل الموصوفة جيداً. على سبيل المثال ، بعد سكب 2 تيرابايت من البيانات من الهمس ، فإنها تتناسب مع 300 جيجا بايت. لن أتطرق إلى المقارنة بالتفصيل ، فهناك مقالات كافية حول هذا الموضوع. بالإضافة إلى ذلك ، حتى وقت قريب ، لم يكن كل شيء مثاليًا مع وحدة تخزين ClickHouse الخاصة بنا.
قضايا المساحة المستهلكة
للوهلة الأولى ، كل شيء يجب أن يعمل بشكل جيد. التالي retention
) ، ثم قم بإنشاء جدول وفقًا لتوصية الواجهة الخلفية لشبكة الجرافيت المحددة:
لفهم أيها ، تحتاج إلى معرفة كيفية عمل الإدخالات ومسار الحياة الإضافي للبيانات في جداول محركات العائلة *MergeTree ClickHouse (الرسوم البيانية مأخوذة من
- تم إدراجه
блок
بيانات. في حالتنا ، هذه مقاييس.
- يتم فرز كل كتلة وفقًا للمفتاح قبل كتابتها على القرص.
ORDER BY
المحدد عندما تم إنشاء الجدول. - بعد الفرز ،
кусок
(part
) تتم كتابة البيانات على القرص.
- يراقب الخادم في الخلفية بحيث لا يوجد الكثير من هذه القطع ، ويطلق الخلفية
слияния
(merge
، ثم دمج).
- يتوقف الخادم عن بدء عمليات الدمج من تلقاء نفسه بمجرد توقف تدفق البيانات بشكل نشط
партицию
(partition
) ، ولكن يمكنك بدء العملية يدويًا باستخدام الأمرOPTIMIZE
. - إذا بقيت قطعة واحدة فقط في القسم ، فلن تتمكن من بدء الدمج بالأمر المعتاد ، فيجب عليك استخدام
OPTIMIZE ... FINAL
لذا ، وصلت المقاييس الأولى. ويشغلون بعض المساحة. قد تختلف الأحداث اللاحقة إلى حد ما اعتمادًا على العديد من العوامل:
- يمكن أن يكون مفتاح التقسيم إما صغيرًا جدًا (يوميًا) أو كبيرًا جدًا (عدة أشهر).
- يمكن أن يتلاءم تكوين الاحتفاظ مع العديد من عتبات تجميع البيانات المهمة داخل القسم النشط (حيث تتم كتابة المقاييس) ، أو ربما لا.
- إذا كان هناك الكثير من البيانات ، فلن يتم دمج الأجزاء الأولى ، والتي قد تكون ضخمة بالفعل بسبب دمج الخلفية (عند اختيار مفتاح تقسيم غير مثالي) ، مع قطع صغيرة جديدة.
ودائما ينتهي الأمر نفسه. لا ينمو المكان الذي تشغله المقاييس في ClickHouse إلا إذا:
- لا تنطبق
OPTIMIZE ... FINAL
يدويا أو - لا تقم بإدراج البيانات في كافة الأقسام بشكل مستمر لبدء دمج الخلفية عاجلاً أم آجلاً
يبدو أن الطريقة الثانية هي الأسهل في التنفيذ ، وبالتالي فهي خاطئة وتم اختبارها في المقام الأول.
لقد كتبت نصًا بسيطًا إلى حد ما من لغة بيثون يرسل مقاييس وهمية لكل يوم على مدار السنوات الأربع الماضية ويعمل كل ساعة باستخدام كرون.
نظرًا لأن جميع أعمال ClickHouse DBMS تستند إلى حقيقة أن هذا النظام سوف يقوم عاجلاً أم آجلاً بجميع الأعمال في الخلفية ، ولكن من غير المعروف متى ، لم أتمكن من الانتظار حتى تتكيف القطع الضخمة القديمة لبدء الدمج بأخرى صغيرة جديدة. أصبح من الواضح أننا بحاجة إلى إيجاد طريقة لأتمتة التحسينات القسرية.
المعلومات في جداول نظام ClickHouse
دعونا نلقي نظرة على هيكل الجدول
- اسم قاعدة البيانات (
database
); - اسم الطاولة (
table
); - اسم القسم والمعرف (
partition
&partition_id
); - عندما تم إنشاء القطعة (
modification_time
); - الحد الأدنى والحد الأقصى للتاريخ في المقطع (التقسيم باليوم) (
min_date
&max_date
);
هناك أيضا طاولة
- اسم قاعدة البيانات (
Tables.database
); - اسم الطاولة (
Tables.table
); - عمر المقياس عند تطبيق التجميع التالي (
age
);
لذلك:
- لدينا جدول الأجزاء وجدول قواعد التجميع.
- نحن نوحد تقاطعهم ونتلقى جميع * طاولات GraphiteMergeTree.
- نحن نبحث عن جميع الأقسام التي فيها:
- أكثر من قطعة واحدة
- أو حان الوقت لتطبيق قاعدة التجميع التالية ، و
modification_time
أقدم من هذه اللحظة.
تطبيق
هذا الطلب
SELECT
concat(p.database, '.', p.table) AS table,
p.partition_id AS partition_id,
p.partition AS partition,
-- Самое "старое" правило, которое может быть применено для
-- партиции, но не в будущем, см (*)
max(g.age) AS age,
-- Количество кусков в партиции
countDistinct(p.name) AS parts,
-- За самую старшую метрику в партиции принимается 00:00:00 следующего дня
toDateTime(max(p.max_date + 1)) AS max_time,
-- Когда партиция должна быть оптимизированна
max_time + age AS rollup_time,
-- Когда самый старый кусок в партиции был обновлён
min(p.modification_time) AS modified_at
FROM system.parts AS p
INNER JOIN
(
-- Все правила для всех таблиц *GraphiteMergeTree
SELECT
Tables.database AS database,
Tables.table AS table,
age
FROM system.graphite_retentions
ARRAY JOIN Tables
GROUP BY
database,
table,
age
) AS g ON
(p.table = g.table)
AND (p.database = g.database)
WHERE
-- Только активные куски
p.active
-- (*) И только строки, где правила аггрегации уже должны быть применены
AND ((toDateTime(p.max_date + 1) + g.age) < now())
GROUP BY
table,
partition
HAVING
-- Только партиции, которые младше момента оптимизации
(modified_at < rollup_time)
-- Или с несколькими кусками
OR (parts > 1)
ORDER BY
table ASC,
partition ASC,
age ASC
يُرجع كل قسم من أقسام الجدول * GraphiteMergeTree التي يجب دمجها لتحرير مساحة على القرص. يبقى الأمر كذلك بالنسبة للأشياء الصغيرة: قم بمراجعتها جميعًا بطلب OPTIMIZE ... FINAL
. أخذ التنفيذ النهائي أيضًا في الاعتبار حقيقة أنه لا توجد حاجة للمس الأقسام ذات السجل النشط.
هذا ما يفعله المشروع.
إذا قمت بتشغيل البرنامج على خادم باستخدام ClickHouse ، فسيبدأ العمل ببساطة في وضع البرنامج الخفي. مرة واحدة في الساعة ، سيتم تنفيذ استعلام ، والتحقق مما إذا كانت هناك أقسام جديدة أقدم من ثلاثة أيام يمكن تحسينها.
في المستقبل القريب - لتوفير حزم deb على الأقل ، وإذا أمكن - أيضًا rpm.
بدلا من خاتمة
على مدار الأشهر التسعة الماضية أو أكثر ، كنت داخل شركتي
تم إنفاق عدة لترات من البيرة وأيام إدارة على تطوير الطلب ، جنبًا إلى جنب مع
المصدر: www.habr.com