Saluton, habr.
Se iu ekspluatas la sistemon
ClickHouse bone solvas la priskribitajn problemojn. Ekzemple, post translokado de 2TiB de datumoj de flustro, ili konvenas en 300GiB. Mi ne detale detalos pri la komparo; estas multaj artikoloj pri ĉi tiu temo. Krome, ĝis antaŭ nelonge, ne ĉio estis perfekta kun nia ClickHouse-stokado.
Problemoj kun konsumita spaco
Unuavide, ĉio devus funkcii bone. Sekvante retention
), tiam kreu tabelon laŭ la rekomendo de la elektita backend por grafito-retejo:
Por kompreni kiun, vi devas scii kiel funkcias enigaĵoj kaj la pluan vivvojon de datumoj en tabeloj de motoroj de la * familio.MergeTree ClickHouse (diagramoj prenitaj de
- enigita
блок
datumoj. En nia kazo, estis la metrikoj kiuj alvenis.
- Ĉiu tia bloko estas ordigita laŭ la ŝlosilo antaŭ esti skribita al disko.
ORDER BY
specifita dum kreado de la tabelo. - Post ordigo,
кусок
(part
) datumoj estas skribitaj al disko.
- La servilo monitoras en la fono tiel ke ne estas multaj tiaj pecoj, kaj lanĉas fonon
слияния
(merge
, ĉi-poste kunfandi).
- La servilo ĉesas funkcii kunfandiĝas memstare tuj kiam datumoj ĉesas aktive flui en la
партицию
(partition
), sed vi povas komenci la procezon permane per la komandoOPTIMIZE
. - Se restas nur unu peco en la subdisko, tiam vi ne povos ruli la kunfandiĝon per la kutima komando; vi devas uzi
OPTIMIZE ... FINAL
Do, la unuaj metrikoj alvenas. Kaj ili okupas iom da spaco. Postaj okazaĵoj povas varii iom depende de multaj faktoroj:
- La dispartiga ŝlosilo povas esti aŭ tre malgranda (tage) aŭ tre granda (pluraj monatoj).
- La konserva agordo povas ĝustigi plurajn signifajn datumajn agregsojlojn ene de la aktiva sekcio (kie metrikoj estas registritaj), aŭ eble ne.
- Se estas multe da datumoj, tiam la plej fruaj pecoj, kiuj pro fona kunfandiĝo eble jam estas grandegaj (se vi elektas neoptimuman dispartigan ŝlosilon), ne kunfandiĝos kun freŝaj malgrandaj pecoj.
Kaj ĉiam finiĝas same. La spaco okupita de metrikoj en ClickHouse nur pliiĝas se:
- ne aplikas
OPTIMIZE ... FINAL
permane aŭ - ne enmetu datumojn en ĉiujn subdiskojn daŭrante, tiel ke baldaŭ aŭ malfrue fono-kunfandiĝo komenciĝos
La dua metodo ŝajnas esti la plej facila por efektivigi kaj, tial, ĝi estas malĝusta kaj estis provita unue.
Mi skribis sufiĉe simplan python-skripton, kiu sendis simulajn metrikojn por ĉiutage dum la pasintaj 4 jaroj kaj kuris cron ĉiun horon.
Ĉar la tuta funkciado de ClickHouse DBMS baziĝas sur la fakto, ke ĉi tiu sistemo pli aŭ malpli frue faros la tutan fonan laboron, sed oni ne scias kiam, mi ne povis atendi la momenton, kiam la malnovaj grandegaj pecoj degnas komenci kunfandiĝi kun novaj malgrandaj. Evidentiĝis, ke ni bezonas serĉi manieron aŭtomatigi devigitajn optimumigojn.
Informoj en ClickHouse-sistemaj tabeloj
Ni rigardu la tabelstrukturon
- db nomo (
database
); - nomo de tabelo (
table
); - nomo kaj diskidentigilo (
partition
&partition_id
); - kiam la peco estis kreita (
modification_time
); - minimuma kaj maksimuma dato en peco (dispartigo estas farita tage) (
min_date
&max_date
);
Estas ankaŭ tablo
- db nomo (
Tables.database
); - nomo de tabelo (
Tables.table
); - metrika aĝo kiam la sekva agregado devus esti aplikita (
age
);
Do:
- Ni havas tabelon de pecoj kaj tabelon de agregaj reguloj.
- Ni kombinas ilian intersekciĝon kaj ricevas ĉiujn tabelojn *GraphiteMergeTree.
- Ni serĉas ĉiujn sekciojn en kiuj:
- pli ol unu peco
- aŭ venis la tempo por apliki la sekvan agregan regulon, kaj
modification_time
pli malnova ol ĉi tiu momento.
Реализация
Ĉi tiu peto
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
redonas ĉiun el la *GraphiteMergeTree-tabelsekcioj, kies kunfandiĝo devus liberigi diskospacon. La nura afero por fari estas trarigardi ilin ĉiujn kun peto OPTIMIZE ... FINAL
. La fina efektivigo ankaŭ konsideras la fakton, ke ne necesas tuŝi sekciojn kun aktiva registrado.
Ĝuste ĉi tion faras la projekto
Se vi rulas la programon sur servilo kun ClickHouse, ĝi simple komencos funkcii en demona reĝimo. Unufoje hore peto estos ekzekutita, kontrolante ĉu novaj subdiskoj pli malnovaj ol tri tagoj aperis optimumeblaj.
Niaj tujaj planoj estas provizi almenaŭ deb-pakaĵojn, kaj se eble ankaŭ rpm.
Anstataŭ konkludo
Dum la pasintaj 9+ monatoj mi estis en mia firmao
Pluraj litroj da biero kaj administraj tagoj estis elspezitaj por disvolvi la peton, kune kun
fonto: www.habr.com