Пользовательский ключ партиционирования
В большинстве случаев ключ партиционирования не нужен, а в большинстве остальных случаев нет необходимости в ключе партиционирования с более мелкой детализацией, чем по месяцам, за исключением сценариев наблюдаемости (observability), где часто используется партиционирование по дням.
Не следует использовать чрезмерно детализированное партиционирование. Не партиционируйте данные по идентификаторам или именам клиентов. Вместо этого сделайте идентификатор или имя клиента первым столбцом в выражении ORDER BY.
Партиционирование доступно для таблиц семейства MergeTree, включая реплицируемые таблицы и материализованные представления.
Партиция — это логическое объединение записей в таблице по заданному критерию. Вы можете задать партицию по произвольному критерию, например по месяцу, по дню или по типу события. Каждая партиция хранится отдельно, что упрощает операции с этими данными. При доступе к данным ClickHouse использует минимально возможное подмножество партиций. Партиции повышают производительность запросов, содержащих ключ партиционирования, потому что ClickHouse будет фильтровать по этой партиции до выбора партиций (parts) и гранул внутри партиции.
Партиция задаётся в предложении PARTITION BY expr при создании таблицы. Ключ партиционирования может быть любым выражением над столбцами таблицы. Например, чтобы указать партиционирование по месяцам, используйте выражение toYYYYMM(date_column):
Ключ партиционирования может также представлять собой кортеж выражений (аналогично первичному ключу). Например:
В этом примере мы задаём секционирование по типам событий, произошедших в течение текущей недели.
По умолчанию тип данных с плавающей запятой не поддерживается в качестве ключа секционирования. Чтобы его использовать, включите настройку allow_floating_point_partition_key.
При вставке новых данных в таблицу эти данные сохраняются как отдельная часть (chunk), отсортированная по первичному ключу. Через 10–15 минут после вставки части одной и той же секции объединяются в единую часть.
Слияние работает только для частей данных, у которых одинаковое значение выражения секционирования. Это означает, что не следует делать секционирование слишком детализированным (более чем примерно тысяча секций). В противном случае запрос SELECT будет выполняться неэффективно из‑за неоправданно большого количества файлов в файловой системе и открытых файловых дескрипторов.
Используйте таблицу system.parts для просмотра частей таблицы и её секций. Например, предположим, что у нас есть таблица visits с секционированием по месяцам. Выполним запрос SELECT к таблице system.parts:
Столбец partition содержит имена партиций. В этом примере есть две партиции: 201901 и 201902. Вы можете использовать значение этого столбца, чтобы указать имя партиции в запросах ALTER ... PARTITION.
Столбец name содержит имена частей данных партиции. Вы можете использовать этот столбец, чтобы указать имя части в запросе ALTER ATTACH PART.
Разберём имя части: 201901_1_9_2_11:
201901— имя партиции.1— минимальный номер блока данных.9— максимальный номер блока данных.2— уровень части (глубина дерева MergeTree, из которого она сформирована).11— версия мутации (если часть была изменена мутацией).
Части таблиц старого типа имеют имена вида: 20190117_20190123_2_2_0 (минимальная дата — максимальная дата — минимальный номер блока — максимальный номер блока — уровень).
Столбец active показывает статус части. 1 — активна; 0 — неактивна. Неактивные части — это, например, исходные части, оставшиеся после слияния в более крупную часть. Повреждённые части данных также помечаются как неактивные.
Как видно из примера, существует несколько отдельных частей одной и той же партиции (например, 201901_1_3_1 и 201901_1_9_2). Это означает, что эти части ещё не были слиты. ClickHouse периодически сливает вставленные части данных, примерно через 15 минут после вставки. Кроме того, вы можете выполнить внеплановое слияние с помощью запроса OPTIMIZE. Пример:
Неактивные части будут удалены примерно через 10 минут после слияния.
Другой способ просмотреть набор частей и партиций — перейти в каталог таблицы: /var/lib/clickhouse/data/<database>/<table>/. Например:
Папки '201901_1_1_0', '201901_1_7_1' и так далее являются каталогами частей. Каждая часть относится к соответствующему разделу (partition) и содержит данные только за определённый месяц (в этом примере таблица разбита на разделы по месяцам).
Каталог detached содержит части, которые были отсоединены от таблицы с помощью запроса DETACH. Повреждённые части также перемещаются в этот каталог вместо удаления. Сервер не использует части из каталога detached. Вы можете добавлять, удалять или изменять данные в этом каталоге в любое время — сервер не узнает об этом, пока вы не выполните запрос ATTACH.
Обратите внимание, что на рабочем сервере вы не можете вручную изменять набор частей или их данные в файловой системе, так как сервер не узнает об этом. Для нереплицируемых таблиц вы можете делать это, когда сервер остановлен, но это не рекомендуется. Для реплицируемых таблиц набор частей не может быть изменён ни при каких обстоятельствах.
ClickHouse позволяет выполнять операции с партициями: удалять их, копировать из одной таблицы в другую или создавать резервную копию. См. полный список операций в разделе Manipulations With Partitions and Parts.
Оптимизация Group By с использованием ключа партиционирования
Для некоторых комбинаций ключа партиционирования таблицы и ключа группировки запроса (GROUP BY) агрегацию можно выполнять независимо для каждой партиции.
Тогда нам не придется в конце объединять частично агрегированные данные со всех потоков выполнения,
поскольку у нас есть гарантия, что каждое значение ключа группировки не может встречаться в рабочих наборах данных двух разных потоков.
Типичный пример:
Производительность такого запроса в значительной степени зависит от структуры таблицы. Поэтому эта оптимизация по умолчанию не включена.
Ключевые факторы высокой производительности:
- количество секций, задействованных в запросе, должно быть достаточно большим (больше, чем
max_threads / 2), иначе запрос будет недостаточно эффективно использовать ресурсы сервера - секции не должны быть слишком маленькими, чтобы пакетная обработка не вырождалась в построчную обработку
- секции должны быть сопоставимы по размеру, чтобы все потоки выполняли примерно одинаковый объём работы
Рекомендуется применить некоторую хеш-функцию к столбцам в выражении partition by, чтобы равномерно распределить данные между секциями.
Соответствующие настройки:
allow_aggregate_partitions_independently— управляет тем, включено ли использование оптимизацииforce_aggregate_partitions_independently— принудительно включает её использование, когда это допустимо с точки зрения корректности, но может быть отключено внутренней логикой, оценивающей её целесообразностьmax_number_of_partitions_for_independent_aggregation— жёсткое ограничение на максимальное количество секций, которое может иметь таблица