Поздрав, хабр.
Ако некој го експлоатира системот
ClickHouse добро ги решава опишаните проблеми. На пример, по преносот на 2TiB податоци од шепот, тие се вклопуваат во 300GiB. Нема да се задржам на споредбата во детали; има многу написи на оваа тема. Покрај тоа, до неодамна, не беше сè совршено со нашето складирање на ClickHouse.
Проблеми со потрошениот простор
На прв поглед, сè треба да работи добро. Следи retention
), потоа креирајте табела според препораката на избраниот заднина за графит-веб:
За да разберете кој, треба да знаете како работат инсертите и понатамошниот животен пат на податоците во табелите на мотори од семејството *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, таа едноставно ќе почне да работи во режим на демон. Еднаш на час ќе се изврши барање, проверувајќи дали се појавиле нови партиции постари од три дена што може да се оптимизираат.
Нашите непосредни планови се да обезбедиме барем деб пакети, а ако е можно и вртежи во минута.
Наместо заклучок
Во текот на изминатите 9+ месеци бев во мојата компанија
Неколку литри пиво и административни денови беа потрошени за развивање на барањето, заедно со
Извор: www.habr.com