درود، حبر.
اگر کسی از سیستم سوء استفاده کند
ClickHouse مشکلات توصیف شده را به خوبی حل می کند. به عنوان مثال، پس از انتقال 2TiB داده از Whisper، آنها در 300GiB قرار می گیرند. من در مورد مقایسه با جزئیات صحبت نمی کنم؛ مقالات زیادی در مورد این موضوع وجود دارد. علاوه بر این، تا همین اواخر، همه چیز با فضای ذخیره سازی ClickHouse ما عالی نبود.
مشکلات فضای مصرفی
در نگاه اول، همه چیز باید به خوبی کار کند. ذیل retention
، سپس یک جدول مطابق با توصیه باطن انتخاب شده برای graphite-web ایجاد کنید:
برای اینکه بفهمید کدام یک، باید بدانید که درج ها چگونه کار می کنند و مسیر زندگی بیشتر داده ها در جداول موتورهای خانواده *MergeTree ClickHouse (نمودارهای گرفته شده از
- درج شده است
блок
داده ها. در مورد ما، این معیارها بود که رسید.
- هر بلوک از این قبیل، قبل از اینکه روی دیسک نوشته شود، بر اساس کلید مرتب شده است.
ORDER BY
هنگام ایجاد جدول مشخص شده است. - پس از مرتب سازی،
кусок
(part
) داده ها روی دیسک نوشته می شوند.
- سرور در پس زمینه نظارت می کند تا چنین قطعاتی زیاد نباشد و پس زمینه را راه اندازی می کند
слияния
(merge
، از این پس ادغام می شوند).
- به محض اینکه دادهها بهطور فعال در سرور جریان نمییابند، سرور بهخودی خود ادغام را متوقف میکند
партицию
(partition
، اما می توانید با دستور به صورت دستی فرآیند را شروع کنیدOPTIMIZE
. - اگر فقط یک قطعه در پارتیشن باقی مانده باشد، نمی توانید با استفاده از دستور معمول ادغام را اجرا کنید، باید از آن استفاده کنید.
OPTIMIZE ... FINAL
بنابراین، اولین معیارها می رسند. و مقداری فضا را اشغال می کنند. رویدادهای بعدی ممکن است بسته به عوامل زیادی تا حدودی متفاوت باشد:
- کلید پارتیشن بندی می تواند بسیار کوچک (یک روز) یا بسیار بزرگ (چند ماه) باشد.
- پیکربندی حفظ ممکن است با چندین آستانه تجمع داده مهم در پارتیشن فعال (جایی که معیارها ثبت می شوند) مطابقت داشته باشد، یا شاید نه.
- اگر دادههای زیادی وجود داشته باشد، اولین تکهها، که به دلیل ادغام پسزمینه ممکن است در حال حاضر بزرگ باشند (اگر یک کلید پارتیشن بندی غیربهینه را انتخاب کنید)، خود را با تکههای کوچک تازه ادغام نمیکنند.
و همیشه یکسان تمام می شود. فضای اشغال شده توسط متریک ها در ClickHouse تنها در صورتی افزایش می یابد که:
- اعمال نمی شود
OPTIMIZE ... FINAL
به صورت دستی یا - داده ها را به طور مداوم در همه پارتیشن ها وارد نکنید، تا دیر یا زود یک ادغام پس زمینه شروع شود
به نظر می رسد روش دوم ساده ترین روش است و بنابراین نادرست است و ابتدا امتحان شده است.
من یک اسکریپت پایتون نسبتاً ساده نوشتم که معیارهای ساختگی را برای هر روز در 4 سال گذشته ارسال می کرد و cron را هر ساعت اجرا می کرد.
از آنجایی که کل عملیات ClickHouse DBMS بر این واقعیت استوار است که این سیستم دیر یا زود تمام کارهای پس زمینه را انجام می دهد، اما مشخص نیست چه زمانی، من نتوانستم منتظر لحظه ای باشم که قطعات عظیم قدیمی شروع به ادغام شدن با آن کنند. کوچک های جدید مشخص شد که ما باید به دنبال راهی برای خودکارسازی بهینهسازیهای اجباری باشیم.
اطلاعات در جداول سیستم ClickHouse
بیایید نگاهی به ساختار جدول بیندازیم
- نام db (
database
); - نام جدول (
table
); - نام و شناسه پارتیشن (
partition
&partition_id
); - زمانی که قطعه ساخته شد (
modification_time
); - حداقل و حداکثر تاریخ در یک قطعه (پارتیشن بندی به صورت روز انجام می شود) (
min_date
&max_date
);
یک میز هم هست
- نام db (
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 و در صورت امکان دور در دقیقه است.
به جای یک نتیجه گیری
در بیش از 9 ماه گذشته من در شرکت خود بودم
چندین لیتر آبجو و روزهای مدیریت برای توسعه این درخواست صرف شد
منبع: www.habr.com