🟡 Итак, вводные:
— Clickhouse очень требователен к ресурсам памяти
— Код написан аналитиком, фокус которого - на результате, не на оптимизации и выборе лучшего решения
— В 95% случаев возникает ошибка Out of memory, запрос прерывается, кластер недоступен на 20-30 секунд
Специфика расчета:
— Участвует множество CTE, к некоторым выражениям идет 2+ обращений
— В JOIN участвуют 2 большие таблицы фактов
— Для связи нет единого идентификатора 1:1
— JOIN похож на CROSS JOIN, т.е. на каждое событие клеятся все транзакции (по совпадению клиента)
Логи ошибки
clickhouse-server.err.log:<Fatal> Application: Child process was terminated by signal 9 (KILL). If it is not done by 'forcestop' command or manually, the possible cause is OOM Killer (see 'dmesg' and look at the '/var/log/kern.log' for the details).
🟢 Текущее решение проблемы - оптимизация кода
— Разбиваем одну dbt-модель на несколько: выполняем расчет поэтапно
— Появляется промежуточная материализация (таблица, на которую ссылаемся несколько раз)
— Пробуем применять фильтры как можно раньше, чтобы было меньше строк
— Конфигурируем физическое хранение данных: PARTITION_BY, ORDER_BY
🩷 Рекомендации
— Для витрин с нетривиальной логикой в обязательном порядке нужно добавлять документацию, а именно: желаемый результат, описание шагов преобразований, их назначение и порядок. Потому что без нее для любого человека (включая автора) становится трудно понимать, что это за код, зачем он так написан и что должно получиться
— Для любой витрины сначала проработать идею на концептуальном уровне (= написать документацию), и только потом приступать к написанию кода
— Для текущего кода есть более простое и оптимальное решение без множества CTE & JOINs, а именно: поместить данные в одну таблицу (UNION ALL) и пройтись оконными функциями
— Значения констант (для фильтрации) я бы советовал присваивать в заголовке кода модели через Jinja variable set для прозрачности и простоты внесения изменений
🟤 Мои выводы и идеи:
— Невозможно (сложно) уследить за каждой моделью dbt / запросом
— На этапе PR review неизвестно, как поведет себя запрос в PROD env (и когда возникнет проблема)
— Впоследствие нет желания оптимизировать / рефакторить каждый запрос по-отдельности
— При этом хочется дать каждому члену команды доступный, универсальный и надежный инструмент вне зависимости от уровня подготовки и понимания специфики расчетов / требований к ресурсам на низком уровне
📊 Поэтому: Рассмотреть переход на альтернативные движки для расчетов (heavy lifting): Trino / Spark, а Clickhouse оставить только как сверхбыстрый доступ к слою витрин данных.
— В идеале это transient cluster: поднял - посчитал - погасил (оплата только за время расчетов)
— Широкий набор доступных функций и возможностей трансформации
— Желательна максимальная поддержка dbt: наличие адаптера, artifacts, modules
— Интеграция с Kafka Connect (sink)
Кажется, идеально подходят движки Trino / Spark + S3 (Delta / Hudi / Iceberg)
💬 Что думаете?
🌐 @data_apps | Навигация по каналу