Ողջույն, հաբր.
Եթե ինչ-որ մեկը շահագործում է համակարգը
ClickHouse-ը լավ է լուծում նկարագրված խնդիրները։ Օրինակ, շշուկից 2TiB տվյալներ փոխանցելուց հետո դրանք տեղավորվում են 300GiB-ի մեջ: Ես մանրամասն չեմ անդրադառնա համեմատության վրա, այս թեմայի վերաբերյալ շատ հոդվածներ կան: Բացի այդ, մինչև վերջերս ամեն ինչ կատարյալ չէր մեր ClickHouse պահեստի հետ:
Սպառված տարածքի հետ կապված խնդիրներ
Առաջին հայացքից ամեն ինչ պետք է լավ աշխատի։ Հետևելով retention
), այնուհետև ստեղծեք աղյուսակ՝ գրաֆիտ-վեբի համար ընտրված հետին պլանի առաջարկության համաձայն.
Հասկանալու համար, թե որն է, դուք պետք է իմանաք, թե ինչպես են աշխատում ներդիրները և տվյալների հետագա կյանքի ուղին * ընտանիքի շարժիչների աղյուսակներում:MergeTree ClickHouse (գծապատկերները վերցված են
- Տեղադրված է
блок
տվյալները։ Մեր դեպքում դա չափիչն էր, որը եկավ:
- Յուրաքանչյուր այդպիսի բլոկ դասավորված է ըստ բանալիի, նախքան սկավառակի վրա գրվելը:
ORDER BY
նշված է աղյուսակը ստեղծելիս: - Տեսակավորումից հետո՝
кусок
(part
) տվյալները գրվում են սկավառակի վրա:
- Սերվերը հետևում է ֆոնին այնպես, որ նման կտորներ շատ չլինեն, և գործարկում է ֆոն
слияния
(merge
, այսուհետ միաձուլվել):
- Սերվերը դադարում է միաձուլումների գործարկումն ինքնուրույն, հենց որ տվյալները դադարում են ակտիվորեն հոսել դեպի
партицию
(partition
), բայց դուք կարող եք գործընթացը սկսել ձեռքով հրամանովOPTIMIZE
. - Եթե բաժանման մեջ մնացել է միայն մեկ կտոր, ապա դուք չեք կարողանա միաձուլումը կատարել սովորական հրամանի միջոցով, դուք պետք է օգտագործեք
OPTIMIZE ... FINAL
Այսպիսով, առաջին չափումները գալիս են: Եվ նրանք որոշակի տեղ են զբաղեցնում: Հետագա իրադարձությունները կարող են որոշակիորեն տարբերվել՝ կախված բազմաթիվ գործոններից.
- Բաժանման բանալին կարող է լինել կամ շատ փոքր (օրական) կամ շատ մեծ (մի քանի ամիս):
- Պահպանման կազմաձևը կարող է տեղավորել մի քանի կարևոր տվյալների համախմբման շեմեր ակտիվ բաժանման ներսում (որտեղ չափումները գրանցվում են), կամ գուցե ոչ:
- Եթե շատ տվյալներ կան, ապա ամենավաղ կտորները, որոնք ֆոնային միաձուլման պատճառով կարող են արդեն հսկայական լինել (եթե ընտրեք ոչ օպտիմալ բաժանման բանալի), չեն միաձուլվի թարմ փոքր կտորների հետ:
Եվ դա միշտ ավարտվում է նույնով: ClickHouse-ում չափումների զբաղեցրած տարածքը մեծանում է միայն այն դեպքում, եթե՝
- չդիմել
OPTIMIZE ... FINAL
ձեռքով կամ - շարունակական հիմունքներով մի մտցրեք տվյալները բոլոր բաժիններում, որպեսզի վաղ թե ուշ սկսվի ֆոնային միաձուլումը
Երկրորդ մեթոդը, թվում է, ամենահեշտն է իրագործելի, և, հետևաբար, այն սխալ է և առաջինը փորձարկվել է:
Ես գրեցի բավականին պարզ python սցենար, որն ուղարկում էր կեղծ չափումներ ամեն օրվա համար վերջին 4 տարիների ընթացքում և աշխատում էր cron ամեն ժամ:
Քանի որ ClickHouse DBMS-ի ամբողջ աշխատանքը հիմնված է այն փաստի վրա, որ այս համակարգը վաղ թե ուշ կկատարի ամբողջ ֆոնային աշխատանքը, բայց հայտնի չէ, թե երբ, ես չկարողացա սպասել այն պահին, երբ հին հսկայական կտորները կսկսեն միաձուլվել: նոր փոքրերը. Պարզ դարձավ, որ մենք պետք է ճանապարհ փնտրենք հարկադիր օպտիմալացումների ավտոմատացման համար:
Տեղեկություններ ClickHouse համակարգի աղյուսակներում
Եկեք նայենք աղյուսակի կառուցվածքին
- դբ անունը (
database
); - սեղանի անվանումը (
table
); - բաժանման անվանումը և ID-ն (
partition
&partition_id
); - երբ ստեղծվեց կտորը (
modification_time
); - նվազագույն և առավելագույն ամսաթիվը մեկ կտորով (բաժանումը կատարվում է օրական) (
min_date
&max_date
);
Առկա է նաև սեղան
- դբ անունը (
Tables.database
); - սեղանի անվանումը (
Tables.table
); - մետրային տարիքը, երբ պետք է կիրառվի հաջորդ ագրեգացումը (
age
);
So.
- Մենք ունենք կտորների աղյուսակ և համախմբման կանոնների աղյուսակ:
- Մենք միավորում ենք դրանց խաչմերուկը և ստանում բոլոր աղյուսակները *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-ով, այն պարզապես կսկսի աշխատել դեյմոն ռեժիմով: Ժամը մեկ անգամ հարցումը կկատարվի՝ ստուգելով, թե արդյոք հայտնվել են երեք օրից ավելի հին բաժանմունքներ, որոնք կարող են օպտիմիզացվել:
Մեր անմիջական ծրագրերն են տրամադրել առնվազն դեբային փաթեթներ, իսկ հնարավորության դեպքում նաև պտույտ/րոպե:
Փոխարենը մի եզրակացության
Վերջին 9+ ամիսների ընթացքում ես եղել եմ իմ ընկերության ներսում
Հարցումը մշակելու համար ծախսվել է մի քանի լիտր գարեջուր և ադմինիստրատիվ օրեր
Source: www.habr.com