Пользовательский ключ партиционирования
В большинстве случаев вам не нужен ключ партиционирования, а в большинстве других случаев вам не нужен ключ партиционирования более детализированный, чем по месяцам.
Никогда не используйте слишком детализированное партиционирование. Не партиционируйте ваши данные по идентификаторам клиентов или именам. Вместо этого сделайте идентификатор клиента или имя первым столбцом в выражении ORDER BY.
Партиционирование доступно для таблиц семейства MergeTree, включая реплицированные таблицы и материализованные представления.
Партиция - это логическая комбинация записей в таблице по заданному критерию. Вы можете задать партицию по произвольному критерию, например, по месяцу, по дню или по типу события. Каждая партиция хранится отдельно для упрощения манипуляций с этими данными. При доступе к данным ClickHouse использует наименьший возможный подмножество партиций. Партиции улучшают производительность для запросов, содержащих ключ партиционирования, так как ClickHouse будет фильтровать по этой партиции перед выбором частей и гранул внутри партиции.
Партиция указывается в предложении PARTITION BY expr
при создании таблицы. Ключ партиции может быть любым выражением из столбцов таблицы. Например, чтобы задать партиционирование по месяцу, используйте выражение toYYYYMM(date_column)
:
Ключ партиции также может быть кортежем выражений (аналогично первичному ключу). Например:
В этом примере мы задаем партиционирование по типам событий, произошедшим в текущую неделю.
По умолчанию ключ партиции с плавающей запятой не поддерживается. Чтобы использовать его, активируйте настройку allow_floating_point_partition_key.
При вставке новых данных в таблицу эти данные хранятся как отдельная часть (фрагмент), отсортированная по первичному ключу. Через 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
- уровень фрагмента (глубина слияния, из которого он образован).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' и так далее - это директории частей. Каждая часть относится к соответствующей партиции и содержит данные только за определенный месяц (таблица в этом примере имеет партиционирование по месяцам).
Директория detached
содержит части, которые были отделены от таблицы с помощью запроса DETACH. Поврежденные части также перемещаются в эту директорию, вместо того чтобы быть удаленными. Сервер не использует части из директории detached
. Вы можете добавлять, удалять или изменять данные в этой директории в любое время - сервер не узнает об этом, пока вы не выполните запрос ATTACH.
Обратите внимание, что на работающем сервере вы не можете вручную изменять набор частей или их данные в файловой системе, так как сервер этого не знает. Для нереализованных таблиц вы можете сделать это, когда сервер остановлен, но это не рекомендуется. Для реплицированных таблиц набор частей не может быть изменен ни в каком случае.
ClickHouse позволяет выполнять операции с партициями: удалять их, копировать из одной таблицы в другую или создавать резервную копию. Смотрите список всех операций в разделе Манипуляции с партициями и частями.
Оптимизация Group By с использованием ключа партиционирования
Для некоторых комбинаций ключа партиционирования таблицы и ключа group by запроса может быть возможно выполнить агрегацию для каждой партиции независимо. Это избавит нас от необходимости сливать частично агрегированные данные из всех потоков выполнения в конце, поскольку мы предоставим гарантию, что каждое значение ключа group by не может появиться в рабочих наборах двух различных потоков.
Типичный пример:
Производительность такого запроса во многом зависит от структуры таблицы. Поэтому оптимизация не включена по умолчанию.
Ключевые факторы для хорошей производительности:
- количество партиций, участвующих в запросе, должно быть достаточно большим (более
max_threads / 2
), иначе запрос не будет в полной мере использовать ресурсы машины - партиции не должны быть слишком маленькими, чтобы пакетная обработка не перешла в построчную обработку
- партиции должны быть сопоставимы по размеру, чтобы все потоки выполняли примерно одинаковый объем работы
Рекомендуется применять некоторую хеш-функцию к столбцам в предложении partition by
, чтобы равномерно распределить данные между партициями.
Соответствующие настройки:
allow_aggregate_partitions_independently
- управляет, включена ли оптимизацияforce_aggregate_partitions_independently
- принудительно включает ее использование, когда это применимо с точки зрения корректности, но отключается внутренней логикой, оценивающей ее целесообразностьmax_number_of_partitions_for_independent_aggregation
- жесткий лимит на максимальное количество партиций, которое может иметь таблица