Как равномерно распределить по шардам ClickHouse уже существующие данные, зачем профилировать запросы, какие профилировщики поддерживает эта колоночная СУБД и каким образом их использовать.
Ребалансировка шардов в ClickHouse
Какой бы быстрой не была база данных, ее работу всегда хочется ускорить еще больше. Одним из популярных способов ускорения распределенной СУБД является шардирование — горизонтальное масштабирование за счет физического разделения данных на разные сегменты (шарды, shards), которые располагаются на разных машинах. При этом создается большая распределенная distributed-таблица, которая маршрутизирует запросы к таблицам по шардам, обращаться к данным в которых можно также и напрямую. В ClickHouse данные располагаются на разных шардах, каждый из которых представляет собой группу копий данных (реплик) для обеспечения отказоустойчивости СУБД и параллельного выполнения SQL-запроса. Чтобы шардирование было эффективным, следует выбирать ключ шардирования так, чтобы равномерно распределить данные по всем шардам, обеспечив их взаимную независимость.
Для шардирования в ClickHouse используется специальный табличный движок distributed. Этот механизм не обеспечивает хранение данных, а маршрутизирует запросы на шардированные таблицы с последующей обработкой результатов. Подробнее про работу с distribured-движком в ClickHouse мы писали здесь. Ключ шардирования, как и движок distributed указывается при создании таблицы в DDL-запросе CREATE TABLE, например:
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = Distributed(cluster, database, table[, sharding_key[, policy_name]]) [SETTINGS name=value, ...]
Некоторые СУБД поддерживают автоматическую ребалансировку шардов, чтобы сделать распределение данных более равномерным. В ClickHouse нет такой встроенной возможности. Но можно перебалансировать шарды самостоятельно следующими способами:
- настроить шард для распределенной таблицы, позволяя выполнять запись в новый шард. Хотя такое решение может привести к дисбалансу нагрузки и появлению горячих точек в кластере, оно обычно подходит для сценариев с не очень высокой пропускной способностью записи. Таблица остается распределенной, но это не помогает сбалансировать существующие данные.
- изменить существующий кластер и записывать данные исключительно в новый шард до тех пор, пока кластер не будет сбалансирован, отслеживая это вручную. Этот подход имеет те же ограничения, что и предыдущий.
- отсоединить разделы распределенной таблицы и вручную переместить их на другой узел перед повторным подключением к новому шарду. Так можно перебалансировать существующие данные, но надо учитывать необходимость их повторной балансировки. Для экспорта данных из исходного кластера в новый можно использовать команду INSERT FROM SELECT. Этот подход не эффективен для очень больших наборов данных и потенциально может привести к значительному увеличению количества операций ввода-вывода в исходном кластере и высокому потреблению сетевых ресурсов.
Профилирование запросов
Еще одним способом повышения производительности хранилища данных является профилирование – анализ плана запросов к нему и их оптимизация. ClickHouse поддерживает PGO-оптимизацию запросов на основе профиля времени выполнения (Profile-Guided Optimization). Согласно бенчмаркинговым тестам, этот метод оптимизации компилятора, при котором программа оптимизируется на основе ее профиля времени выполнения, на 15% повышает производительность ClickHouse. Это достигается благодаря тому, что компилятор принимает более обоснованные решения при сортировке базовых блоков, зная, какой участок кода выполняется чаще. При этом различают 2 подхода к профилированию:
- на основе выборки, который может создать профиль с очень низкими издержками времени выполнения. Профилировщики выборки используются для сбора информации о времени выполнения, например аппаратных счетчиков, во время выполнения приложения. Обычно они очень эффективны и не требуют больших затрат времени выполнения. Образцы данных, собранные профилировщиком, можно использовать во время компиляции, чтобы определить, какие области кода выполняются наиболее часто.
- на основе инструментирования версии кода, которая собирает более подробную информацию о профиле. Этот подход требует некоторых издержек во время выполнения при профилировании, но обеспечивает более подробные результаты, чем профилировщик выборки. Он также обеспечивает воспроизводимые результаты, по крайней мере, в той степени, в которой код ведет себя согласованно при каждом запуске.
Оба типа профилей могут предоставлять счетчики выполнения инструкций в коде, а также информацию о принятых ветвях и вызовах функций.
ClickHouse в режиме инструментирования может работать медленно, поэтому не рекомендуется использовать его в производственных средах, где нужна высокая производительность. После запуска инструментированного ClickHouse на рабочей нагрузке с помощью передачи флагу -fprofile-generate параметра CXXFLAGS, его надо перекомпилировать, используя флаги компилятора -fprofile-use и ранее собранные профили.
По умолчанию ClickHouse запускает профилировщик на основе выборки, который позволяет анализировать выполнение запросов, чтобы найти участки исходного кода, которые чаще всего используются во время выполнения запроса. Так можно отслеживать затраченное время процессора на вычисления, включая время простоя на ожидание данных.
Профилировщик запросов автоматически включен в ClickHouse Cloud, пример работы с которым рассмотрен в прошлой статье, а в самостоятельном развертывании его нужно включить, настроив раздел trace_log в конфигурации сервера. В этом разделе настраивается системная таблица trace_log, в которую сохраняются результаты работы профилировщика для работающего сервера. После перезапуска сервера ClickHouse не очищает эту таблицу, поэтому все сохраненные адреса виртуальной памяти могут стать недействительными.
Также следует настроить параметры query_profiler_cpu_time_period_ns и/или query_profiler_real_time_period_ns. Эти настройки сеанса позволяют настраивать таймеры профилировщика. Они позволяют получить разную частоту выборки для всего сервера, отдельных пользователей или их профилей, для интерактивного сеанса и для каждого отдельного запроса. Частота выборки по умолчанию составляет одну выборку в секунду. Такая частота позволяет собрать достаточно информации о кластере ClickHouse. Работая с такой частотой, профилировщик не влияет на производительность сервера ClickHouse. Если нужно профилировать каждый отдельный запрос, можно использовать более высокую частоту выборки.
Для анализа системной таблицы trace_log надо установить пакет clickhouse-common-static-dbg и разрешите функции самоанализа с помощью параметра allow_introspection_functions, которая изначально отключена по соображениям безопасности. Функции addressToLine(), addressToLineWithInlines(), addressToSymbol() и demangle() позволяют получить имена функций и их позиции в коде ClickHouse. Чтобы получить профиль по какому-то запросу, нужно агрегировать данные из таблицы trace_log по отдельным функциям или по всем трассировкам стека. Для визуализации информации из таблицы trace_log можно использовать внешние визуальные интерфейсы, например, Flamegraph и Speedscope.
Следующий пример фильтрацию данных в таблице trace_log по идентификатору запроса и текущей дате с агрегацией по трассировке стека. Функции самоанализа addressToLine(),addressToSymbol() и demangle() позволят получить отчет о названии символов и соответствующих функциях исходного кода, а также их расположении.
SELECT count(), arrayStringConcat(arrayMap(x -> concat(demangle(addressToSymbol(x)), '\n ', addressToLine(x)), trace), '\n') AS sym FROM system.trace_log WHERE (query_id = 234324) AND (event_date = today()) GROUP BY trace ORDER BY count() DESC LIMIT 10
Узнайте больше про администрирование и эксплуатацию ClickHouse для аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники
- https://clickhouse.com/docs/en/guides/sre/scaling-clusters
- https://clickhouse.com/docs/en/operations/optimizing-performance/sampling-query-profiler
- https://clickhouse.com/docs/en/operations/optimizing-performance/profile-guided-optimization
- https://clang.llvm.org/docs/UsersManual.html#using-sampling-profilers