Налаштування ClickHouse MergeTree Engine для аналітики

Зростання даних перетворює швидкі звіти на багатогодинне очікування. Ми налаштовуємо ClickHouse MergeTree під ключ: проєктуємо схему зберігання, оптимізуємо запити й регламенти обслуговування. Аналітика знову дає відповіді за секунди, а звітність перестає залежати від ручної вибірки.
Часті запитання

Чому аналітика на ClickHouse MergeTree деградує зі зростанням даних

У ClickHouse таблиця MergeTree зберігає дані не єдиним масивом, а набором відсортованих частин: рядки розкладаються за ключем сортування, і всередині кожної частини лежить розріджений первинний індекс — мітки через кожні кілька тисяч рядків.

Поки обсяг невеликий, планувальник за цими мітками швидко відсікає непотрібні діапазони, і запит читає рівно те, що попросили.

Зі зростанням обсягу даних механіка ламається: якщо фільтри у звітах ідуть не за ключем сортування, ні первинний індекс, ні розбиття за місяцями не допомагають, і кожен запит перетворюється на читання всієї таблиці.

Другий ефект — фонові злиття. Чим більше вставок дрібними пакетами, тим більше частин потрібно склеїти, тим частіше сервер упирається в межу одночасних злиттів і відповідає помилкою про занадто велику кількість частин.

Деградація аналітичних запитів іде нелінійно: повільні звіти замість секунд починають рахувати хвилини, а важкі агрегації з групуванням за висококардинальним ключем падають через пам'ять, коли проміжний результат не вміщається в ліміт на запит.

Вузьке місце сховища тут майже завжди одне: схема таблиці не збігається з тим, як її запитують. Сирі події лежать одним шаром, кожна побудова звіту перераховує агрегати заново, і зростання обсягу даних б'є напряму по часу відповіді. Розбираємо, як це закривається.

Що дає грамотна схема зберігання: ефект у часі та обсягах

У ClickHouse фізичний порядок рядків задає MergeTree: ключ сортування в ORDER BY визначає, які блоки даних запит узагалі читає, а не лише як швидко фільтрує. Коли звіт ходить за часом і клієнтом, ключ із цих двох полів перетворює повне сканування на читання вузького діапазону.

На типовій аналітиці звіт за добу по великій таблиці прискорюється на порядок — з десятків секунд до часток секунди, і це не разова оптимізація, а властивість схеми.

Партиціювання за місяцем разом із політикою TTL робить зберігання керованим: застарілі партиції видаляються цілком, без перезапису таблиці та без просідання вставок.

Колонкове стиснення плюс підбір кодека під характер колонок — окремо числові, окремо словникові через LowCardinality — дають стиснення в 4–8 разів щодо початкового обсягу. Реєстр перестає зростати лінійно разом із потоком подій.

Окремий ефект — зниклий клас відмов. При неправильному ключі зростає кількість дрібних кусків, фонові злиття не встигають за вставками, і завантаження починає падати з помилкою про занадто велику кількість частин.

Правильна грануляція партицій і ключа знімає цей сценарій: вставки йдуть стабільно, злиття вкладаються у фонове вікно без конкуренції за диск.

Навантаження на сховище розподіляється передбачувано: запити читають менше даних, тому аналітика не блокує завантаження. У сумі це і є вимірюваний результат перебудови схеми — стабільний час відповіді звітів на зростаючому обсязі та відсутність деградації під піковим записом.

Варіанти організації аналітичного зберігання: порівняння підходів

Схема зберігання в ClickHouse MergeTree визначає, де вважається агрегат — на льоту при кожній вибірці чи заздалегідь у момент запису. Від цього залежать час відповіді звітів і обсяг перерахунку, який знадобиться при зміні метрики.

Нижче три схеми, між якими реально обирають на старті аналітичного контуру.

Варіант Коли підходить Обмеження
Одна широка таблиця Зрізи ще уточнюються, склад метрик змінюється часто Важкі вибірки, дорога деталізація за дрібними розрізами
Шари з агрегатами Список звітів стабільний, важлива швидкість відповіді Агрегати перезбираються при правці логіки
Окремі таблиці під зрізи Кілька команд зі своїми розрізами та своїм темпом завантаження Більше об'єктів, дублюється завантаження, складніше звіряти

На практиці варіанти комбінують: широка таблиця зберігає події, матеріалізовані представлення підтримують агреговані шари за частими зрізами, партиції нарізані за датою події, а термін життя записів заданий правилом очищення за горизонтом зберігання. Тоді новий зріз — це додавання представлення, а не перезаливання всього сховища.

Орієнтир при виборі такий: якщо запит звіту читає рядків на порядок більше, ніж повертає, агрегат пора виносити в окремий шар; якщо зрізів більше п'яти і вони живуть своїм життям — розносити по таблицях.

Партиціювання, ключ сортування та термін життя записів при цьому залишаються спільними й налаштовуються один раз для всього контуру.

Етапи налаштування сховища аналітики

Налаштування MergeTree починається не з вибору движка, а з розуміння того, які запити до сховища виконуються щодня.

Порядок робіт практично однаковий для будь-якого впровадження: спочатку вимірюємо, потім проєктуємо, і лише потім перевіряємо на навантаженні, близькому до реального. Нижче — послідовність, за якою йдуть наші інженери.

  1. Аудит запитів і профілю навантаження. Збираємо перелік регулярних звітів і разових вибірок, дивимося заміри часу за кожним, відзначаємо, які поля фільтруються й групуються найчастіше. Результат — список запитів, які справді варто оптимізувати, і тих, що можна не чіпати.
  2. Проєктування схеми. Визначаємо склад таблиць, типи колонок і розподіл за шарами: сирі дані, проміжні та попередньо розраховані агрегати. Це прибирає повторні важкі обчислення на кожному зверненні до панелі звітів.
  3. Підбір ключа сортування. Порядок колонок у ключі вирішує, чи потрапить запит у вузький діапазон читання чи буде сканувати таблицю цілком. Варіанти перевіряємо на реальних вибірках з аудиту, а не за інтуїцією.
  4. Налаштування зберігання. Розбиваємо дані за датами, задаємо терміни життя та окремі правила для рідко запитуваних періодів. Обсяг сховища перестає зростати безконтрольно, при цьому історія за потрібний горизонт залишається доступною, а старі зрізи читаються без деградації.
  5. Попередній розрахунок повторюваних звітів. Виносимо найчастіші агрегації в матеріалізовані представлення, щоб панелі відкривалися за секунди, а не перераховували мільйони рядків при кожному зверненні.
  6. Перевірка на реальному навантаженні. Прогоняємо типові сценарії одночасно, як це буде в роботі: дивимося час відгуку, споживання пам'яті й диска, поведінку при піковому записі. Тут же перевіряємо, що відкат на попередню схему проходить без втрати даних.
  7. Передача в експлуатацію. Віддаємо регламенти обслуговування, налаштування моніторингу та задокументовані процедури резервного копіювання й відновлення, щоб команда могла супроводжувати сховище самостійно.

Комплект артефактів: схеми таблиць, конфігурації, регламенти

Ми передаємо не лише працюючий кластер, а й повний набір артефактів, за якими його можна розвивати й обслуговувати силами своєї команди. Усе лежить у вашому репозиторії та в системі контролю версій — з історією змін, а не «усними домовленостями з минулим підрядником».

  • Схеми таблиць — DDL-скрипти з движком MergeTree: ключ сортування, розбиття за партиціями, правила TTL і матеріалізовані представлення. До кожної таблиці коментар, чому вибрано саме такий ключ і що зламається при його зміні.
  • Конфігурації сховища — параметри злиття кусків, ліміти пам'яті на запит, налаштування реплікації та розподілених таблиць, увімкнені кодеки стиснення за колонками.
  • Політики доступу — ролі та рівні прав: окремі облікові записи для сервісів запису, аналітиків і чергового інженера; квоти на важкі вибірки; для частини команд — доступ лише на читання.
  • Регламент обслуговування — розклад злиття партицій, контроль зростання кількості кусків, порядок дій при відставанні репліки та правила відкату на попередню схему.
  • Схема потоків даних — звідки й з якою періодичністю надходять дані, де буферизуються, що робити при затримці джерела або дублях.
  • Моніторинг і оповіщення — перелік метрик, порогові значення та список тих, хто отримує повідомлення, з пріоритетами.
  • Інструкція з експлуатації — типові операції, розбір частих відмов і межі, за якими потрібно кликати інженера.
  • Журнал рішень — які варіанти схеми та зберігання розглядалися, які відхилено й чому: це економить час при наступному доопрацюванні.

Комплект розрахований на те, щоб новий інженер у команді розібрався у сховищі за документами, а не за листуванням. Якщо знадобиться розширення — приходимо вже до готової бази знань.

Кейс: як прискорили аналітичні запити на потокових даних

Продуктовий сервіс із безперервним потоком подій: десятки мільйонів записів на добу складалися в одну таблицю ClickHouse без виразного ключа сортування.

Звіти за воронкою збиралися хвилинами, частина запитів обривалася за часом очікування, а реєстр зростав приблизно на третину щомісяця.

Точка, з якої починали

  • Час відповіді звіту — у 9 разів вищий за цільовий: аналітики чекали результат і перераховували зрізи вручну.
  • Частка запитів, що падали, — 12% у години пік, тобто відмови припадали саме на найбільш навантажені вікна.
  • Обсяг реєстру зростав швидше за сам потік подій: старі партиції ніхто не вичищав.

Що змінили

Перерозмітили таблицю: партиціювання за датою, ключ сортування за орендарем і типом події, щоб фільтри звітів потрапляли в межі блоків і читалося менше даних.

Важкі агрегати винесли в матеріалізовані представлення з попереднім розрахунком, вставки перевели на пакетний запис, а для історичних даних повісили політику зберігання з автоматичним очищенням.

Що стало

Час відповіді звіту скоротився в 12 разів — вивантаження перестало бути окремою задачею аналітика. Частка запитів, що падали, зійшла до нуля, обсяг активного реєстру зменшився втричі, при цьому відкат до будь-якої з останніх партицій залишається доступним. Нові типи подій додаємо за тією ж схемою, без перезаливання таблиці.

Чим MergeTree відрізняється від інших движків ClickHouse?

У ClickHouse движок задається при створенні таблиці й визначає формат зберігання, доступні вибірки та поведінку при вставці.

MergeTree — не один движок, а сімейство зі спільною механікою: дані пишуться відсортованими кусками, за ключем сортування будується розріджений індекс, а фонові злиття укрупнюють куски й згортають дублі.

Log-сімейство (Log, TinyLog, StripeLog) влаштовано простіше: колонка — окремий файл, індексу та злиттів немає. Такі таблиці дешеві на запис і підходять для довідників і проміжних буферів, але вибірка за ключем читає файл цілком, а паралельний запис обмежений.

Реплікація в ReplicatedMergeTree іде через координатор: вузли обмінюються не файлами, а описом частин і операцій, тому відстала репліка доганяє за журналом.

Це не те саме, що розподілений доступ: репліки — копії одних і тих самих даних, а таблиця Distributed розкладає запит за шардами й збирає результат.

Різниця всередині сімейства теж суттєва: ReplacingMergeTree залишає останню версію рядка, SummingMergeTree підсумовує значення при злитті, CollapsingMergeTree позначає видалення. Вибір движка змінює не лише швидкість, а й те, які дані взагалі опиняться в таблиці після злиттів.

Практичний критерій простий: потрібні точкові читання та злиття — беремо MergeTree; потрібна дедуплікація при вставці — варіант із версіями; потрібні дані на кількох вузлах — репліковані таблиці під Distributed. Для дрібних довідників Log-сімейство чесно дешевше.

Технічні сумніви перед перебудовою сховища

Перебудова схеми на працюючому сховищі — питання не «зламається чи ні», а порядку операцій і точок відкату. Нижче — відповіді на три інженерні заперечення, які звучать перед стартом майже завжди.

Дані при перебудові таблиць загубляться?

Перебудова йде через нові партиції: записи дублюються в цільову структуру, звіряються за контрольними сумами рядок за рядком, і лише після збіжності перемикається читання. Стара структура залишається на диску до кінця перевірки — відкат займає хвилини.

Міграція даних виконується порціями, тому окреме вікно недоступності не потрібне: сховище продовжує віддавати запити.

Чи доведеться переписувати звіти та вивантаження?

Зазвичай ні. Імена полів і типи зберігаємо, а при зміні гранулярності додаємо шар представлень із попереднім контрактом для аналітики.

Сумісність звітів перевіряємо порівнянням вивантажень до й після перебудови: розбіжності понад допуск ловимо на тестовому контурі, а не на бойовому.

Що буде з працюючим продакшеном?

Перебудову ведемо на репліці, перемикання трафіку — у вікно мінімального навантаження. Фонові задачі обмежені за ресурсами, щоб не забирати пропускну здатність у живих запитів.

Ризики впровадження закриваємо поетапно: спочатку партиціювання та стиснення, потім перехід на цільову структуру, із заздалегідь зафіксованим планом відкату.

Обговоримо задачу та повернемося з оцінкою й планом

Щоб оцінка впровадження була не «на око», а по суті, потрібні ваші вхідні дані. Опишіть задачу у двох словах — яка аналітика потрібна, хто і як часто будує звіти, — і додайте технічний контекст щодо навантаження й запитів. Надішліть те, що є: чернетку схеми, приклад вивантаження, список полів.

  • Звідки йдуть дані: черга, збирач логів, вивантаження змін з операційної бази — з якою частотою і в якому форматі надходять події.
  • Профіль навантаження: скільки рядків на добу й на місяць, середній і піковий потік, потрібна глибина зберігання.
  • Типові запити: 5-10 найчастіших із фільтрами, групуваннями та періодом — саме вони визначають порядок сортування в ключі та розбиття на партиції.
  • Свіжість даних: допустима затримка між подією та її появою у звіті — секунди чи години; від цього залежить періодичність вставок і набір вбудованих агрегатів.
  • Відмовостійкість: чи потрібні репліки, скільки копій даних, чи є окремі вузли для координації кластера.
  • Поточний стан: де буде розгорнуто, скільки місця на дисках, що вже пробували й які вузькі місця бачили — важкі злиття, роздуте число частин, повільні з'єднання таблиць.

Далі за цими вхідними збираємо план робіт: схему таблиць, порядок ключів і партицій, політики зберігання та проріджування, регламент обслуговування — і оцінку впровадження за етапами. Наступний крок — обговоримо задачу та повернемося з планом і термінами.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139