Pozdrav, habr.
Ako netko iskorištava sustav
ClickHouse dobro rješava opisane probleme. Na primjer, nakon prijenosa 2TiB podataka iz šapta, oni stanu u 300GiB. Neću se posebno zadržavati na usporedbi, ima dosta članaka na ovu temu. Osim toga, donedavno nije sve bilo savršeno s našim ClickHouse skladištem.
Problemi s potrošenim prostorom
Na prvi pogled sve bi trebalo dobro funkcionirati. Praćenje retention
), zatim izradite tablicu prema preporuci odabrane pozadine za graphite-web:
Da biste razumjeli koji, morate znati kako rade umetci i daljnji životni put podataka u tablicama motora obitelji *Spoji stablo ClickHouse (grafikoni preuzeti sa
- Umetnuto
блок
podaci. U našem slučaju, to je bila metrika koja je stigla.
- Svaki takav blok se sortira prema ključu prije nego što se zapiše na disk.
ORDER BY
naveden prilikom izrade tablice. - Nakon sortiranja,
кусок
(part
) podaci se zapisuju na disk.
- Poslužitelj prati u pozadini kako ne bi bilo puno takvih komada i pokreće pozadinu
слияния
(merge
, u nastavku spojiti).
- Poslužitelj prestaje samostalno izvoditi spajanja čim podaci prestanu aktivno teći u
партицию
(partition
), ali proces možete pokrenuti ručno pomoću naredbeOPTIMIZE
. - Ako je u particiji ostao samo jedan dio, tada nećete moći pokrenuti spajanje koristeći uobičajenu naredbu; morate koristiti
OPTIMIZE ... FINAL
Dakle, stižu prve metrike. I zauzimaju malo prostora. Naknadni događaji mogu donekle varirati ovisno o mnogim čimbenicima:
- Particioni ključ može biti vrlo mali (dan) ili vrlo velik (nekoliko mjeseci).
- Konfiguracija zadržavanja može odgovarati nekoliko značajnih pragova agregacije podataka unutar aktivne particije (gdje se bilježe metrike) ili možda ne.
- Ako postoji mnogo podataka, tada se najraniji dijelovi, koji zbog pozadinskog spajanja već mogu biti ogromni (ako odaberete neoptimalan ključ particioniranja), neće sami spojiti sa svježim malim dijelovima.
I uvijek završi isto. Prostor koji zauzimaju metrike u ClickHouseu povećava se samo ako:
- ne primjenjivati
OPTIMIZE ... FINAL
ručno ili - nemojte kontinuirano unositi podatke u sve particije, tako da će prije ili kasnije započeti pozadinsko spajanje
Čini se da je drugu metodu najlakše implementirati i stoga je netočna i isprobana je prva.
Napisao sam prilično jednostavnu python skriptu koja je slala lažne metrike za svaki dan u posljednje 4 godine i pokretala cron svaki sat.
Budući da se cijeli rad ClickHouse DBMS-a temelji na činjenici da će ovaj sustav prije ili kasnije obaviti sve pozadinske poslove, ali ne zna se kada, nisam mogao dočekati trenutak kada će se stari ogromni komadi udostojiti da se počnu spajati s nove male. Postalo je jasno da moramo tražiti način automatizacije prisilnih optimizacija.
Podaci u tablicama sustava ClickHouse
Pogledajmo strukturu tablice
- db ime (
database
); - naziv tablice (
table
); - naziv particije i ID (
partition
&partition_id
); - kada je djelo stvoreno (
modification_time
); - minimalni i maksimalni datum u komadu (podjela se vrši po danima) (
min_date
&max_date
);
Tu je i stol
- db ime (
Tables.database
); - naziv tablice (
Tables.table
); - metrička dob kada bi se trebala primijeniti sljedeća agregacija (
age
);
Dakle:
- Imamo tablicu komada i tablicu pravila združivanja.
- Kombiniramo njihovo sjecište i dobijemo sve tablice *GraphiteMergeTree.
- Tražimo sve particije u kojima:
- više od jednog komada
- ili je došlo vrijeme za primjenu sljedećeg pravila zbrajanja, i
modification_time
stariji od ovog trenutka.
Provedba
Ovaj zahtjev
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
vraća svaku od *GraphiteMergeTree particija tablice čije bi spajanje trebalo osloboditi prostor na disku. Jedino što preostaje je proći ih sve sa zahtjevom OPTIMIZE ... FINAL
. Konačna implementacija također uzima u obzir činjenicu da nema potrebe dirati particije s aktivnim snimanjem.
To je upravo ono što projekt radi
Ako pokrenete program na poslužitelju s ClickHouseom, on će jednostavno početi raditi u daemon modu. Svakih sat vremena izvršavat će se zahtjev kojim se provjerava jesu li se pojavile nove particije starije od tri dana koje je moguće optimizirati.
Naši neposredni planovi su osigurati barem deb pakete, a ako je moguće i rpm.
Umjesto zaključka
Tijekom proteklih 9+ mjeseci bio sam u svojoj tvrtki
Nekoliko litara piva i admin dana potrošeno je na razvoj zahtjeva, zajedno s
Izvor: www.habr.com