Изменение настроек таблицы
Существуют запросы, которые изменяют настройки таблицы или сбрасывают их в значения по умолчанию. В одном запросе можно изменить сразу несколько настроек. Если настройка с указанным именем не существует, то генерируется исключение.
Синтаксис
ALTER TABLE [db].name [ON CLUSTER cluster] MODIFY|RESET SETTING ...
Примечание
Эти запросы могут применяться только к таблицам на движке MergeTree.
MODIFY SETTING
Изменяет настройки таблицы.
Синтаксис
MODIFY SETTING setting_name=value [, ...]
Пример
CREATE TABLE example_table (id UInt32, data String) ENGINE=MergeTree() ORDER BY id; ALTER TABLE example_table MODIFY SETTING max_part_loading_threads=8, max_parts_in_total=50000;
RESET SETTING
Сбрасывает настройки таблицы в значения по умолчанию. Если настройка уже находится в состоянии по умолчанию, то никакие действия не выполняются.
Синтаксис
RESET SETTING setting_name [, ...]
Пример
CREATE TABLE example_table (id UInt32, data String) ENGINE=MergeTree() ORDER BY id SETTINGS max_part_loading_threads=8; ALTER TABLE example_table RESET SETTING max_part_loading_threads;
Смотрите также
Манипуляции с партициями и кусками
Для работы с партициями доступны следующие операции:
- DETACH PARTITION — перенести партицию в директорию detached ;
- DROP PARTITION — удалить партицию;
- ATTACH PARTITION | PART — добавить партицию/кусок в таблицу из директории detached ;
- ATTACH PARTITION FROM — скопировать партицию из другой таблицы;
- REPLACE PARTITION — скопировать партицию из другой таблицы с заменой;
- MOVE PARTITION TO TABLE — переместить партицию в другую таблицу;
- CLEAR COLUMN IN PARTITION — удалить все значения в столбце для заданной партиции;
- CLEAR INDEX IN PARTITION — очистить построенные вторичные индексы для заданной партиции;
- FREEZE PARTITION — создать резервную копию партиции;
- UNFREEZE PARTITION — удалить резервную копию партиции;
- FETCH PARTITION | PART — скачать партицию/кусок с другого сервера;
- MOVE PARTITION | PART — переместить партицию/кускок на другой диск или том.
- UPDATE IN PARTITION — обновить данные внутри партиции по условию.
- DELETE IN PARTITION — удалить данные внутри партиции по условию.
DETACH PARTITION | PART
ALTER TABLE table_name [ON CLUSTER cluster] DETACH PARTITION|PART partition_expr
Перемещает заданную партицию в директорию detached . Сервер не будет знать об этой партиции до тех пор, пока вы не выполните запрос ATTACH.
ALTER TABLE mt DETACH PARTITION '2020-11-21'; ALTER TABLE mt DETACH PART 'all_2_2_0';
Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
После того как запрос будет выполнен, вы сможете производить любые операции с данными в директории detached . Например, можно удалить их из файловой системы.
Запрос реплицируется — данные будут перенесены в директорию detached и забыты на всех репликах. Обратите внимание, запрос может быть отправлен только на реплику-лидер. Чтобы узнать, является ли реплика лидером, выполните запрос SELECT к системной таблице system.replicas. Либо можно выполнить запрос DETACH на всех репликах — тогда на всех репликах, кроме реплик-лидеров (поскольку допускается несколько лидеров), запрос вернет ошибку.
DROP PARTITION | PART
ALTER TABLE table_name [ON CLUSTER cluster] DROP PARTITION|PART partition_expr
Удаляет партицию. Партиция помечается как неактивная и будет полностью удалена примерно через 10 минут.
Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
Запрос реплицируется — данные будут удалены на всех репликах.
ALTER TABLE mt DROP PARTITION '2020-11-21'; ALTER TABLE mt DROP PART 'all_4_4_0';
DROP DETACHED PARTITION | PART
ALTER TABLE table_name [ON CLUSTER cluster] DROP DETACHED PARTITION|PART partition_expr
Удаляет из detached кусок или все куски, принадлежащие партиции. Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
ATTACH PARTITION | PART
ALTER TABLE table_name [ON CLUSTER cluster] ATTACH PARTITION|PART partition_expr
Добавляет данные в таблицу из директории detached . Можно добавить данные как для целой партиции, так и для отдельного куска. Примеры:
ALTER TABLE visits ATTACH PARTITION 201901; ALTER TABLE visits ATTACH PART 201901_2_2_0;
Как корректно задать имя партиции или куска, см. в разделе Как задавать имя партиции в запросах ALTER.
Этот запрос реплицируется. Реплика-иницатор проверяет, есть ли данные в директории detached . Если данные есть, то запрос проверяет их целостность. В случае успеха данные добавляются в таблицу.
Если реплика, не являющаяся инициатором запроса, получив команду присоединения, находит кусок с правильными контрольными суммами в своей собственной папке detached , она присоединяет данные, не скачивая их с других реплик. Если нет куска с правильными контрольными суммами, данные загружаются из любой реплики, имеющей этот кусок.
Вы можете поместить данные в директорию detached на одной реплике и с помощью запроса ALTER . ATTACH добавить их в таблицу на всех репликах.
ATTACH PARTITION FROM
ALTER TABLE table2 [ON CLUSTER cluster] ATTACH PARTITION partition_expr FROM table1
Копирует партицию из таблицы table1 в таблицу table2 .
Обратите внимание, что:
- Данные не удаляются ни из table1 , ни из table2 .
- table1 может быть временной таблицей.
Следует иметь в виду:
- Таблицы должны иметь одинаковую структуру.
- Для таблиц должен быть задан одинаковый ключ партиционирования, одинаковый ключ сортировки и одинаковый первичный ключ.
- Для таблиц должна быть задана одинаковая политика хранения (диск, на котором хранится партиция, должен быть доступен для обеих таблиц).
Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
REPLACE PARTITION
ALTER TABLE table2 [ON CLUSTER cluster] REPLACE PARTITION partition_expr FROM table1
Копирует партицию из таблицы table1 в таблицу table2 с заменой существующих данных в table2 .
Обратите внимание, что:
- Данные из table1 не удаляются.
- table1 может быть временной таблицей.
Следует иметь в виду:
- Таблицы должны иметь одинаковую структуру.
- Для таблиц должен быть задан одинаковый ключ партиционирования, одинаковый ключ сортировки и одинаковый первичный ключ.
- Для таблиц должна быть задана одинаковая политика хранения (диск, на котором хранится партиция, должен быть доступен для обеих таблиц).
Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
MOVE PARTITION TO TABLE
ALTER TABLE table_source [ON CLUSTER cluster] MOVE PARTITION partition_expr TO TABLE table_dest
Перемещает партицию из таблицы table_source в таблицу table_dest (добавляет к существующим данным в table_dest ) с удалением данных из таблицы table_source .
Следует иметь в виду:
- Таблицы должны иметь одинаковую структуру.
- Для таблиц должен быть задан одинаковый ключ партиционирования, одинаковый ключ сортировки и одинаковый первичный ключ.
- Для таблиц должна быть задана одинаковая политика хранения (диск, на котором хранится партиция, должен быть доступен для обеих таблиц).
- Движки таблиц должны быть одинакового семейства (реплицированные или нереплицированные).
CLEAR COLUMN IN PARTITION
ALTER TABLE table_name [ON CLUSTER cluster] CLEAR COLUMN column_name IN PARTITION partition_expr
Сбрасывает все значения в столбце для заданной партиции. Если для столбца определено значение по умолчанию (в секции DEFAULT ), то будет выставлено это значение.
ALTER TABLE visits CLEAR COLUMN hour in PARTITION 201902
CLEAR INDEX IN PARTITION
ALTER TABLE table_name [ON CLUSTER cluster] CLEAR INDEX index_name IN PARTITION partition_expr
Работает как CLEAR COLUMN , но сбрасывает индексы вместо данных в столбцах.
FREEZE PARTITION
ALTER TABLE table_name [ON CLUSTER cluster] FREEZE [PARTITION partition_expr] [WITH NAME 'backup_name']
Создаёт резервную копию для заданной партиции. Если выражение PARTITION опущено, резервные копии будут созданы для всех партиций.
Примечание
Создание резервной копии не требует остановки сервера.
Для таблиц старого стиля имя партиций можно задавать в виде префикса (например, 2019 ). В этом случае, резервные копии будут созданы для всех соответствующих партиций. Подробнее о том, как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.
Запрос формирует для текущего состояния таблицы жесткие ссылки на данные в этой таблице. Ссылки размещаются в директории /var/lib/clickhouse/shadow/N/. , где:
- /var/lib/clickhouse/ — рабочая директория ClickHouse, заданная в конфигурационном файле;
- N — инкрементальный номер резервной копии.
- если задан параметр WITH NAME , то вместо инкрементального номера используется значение параметра ‘backup_name’ .
Примечание
При использовании нескольких дисков для хранения данных таблицы директория shadow/N появляется на каждом из дисков, на которых были куски, попавшие под выражение PARTITION .
Структура директорий внутри резервной копии такая же, как внутри /var/lib/clickhouse/ . Запрос выполнит chmod для всех файлов, запрещая запись в них.
Обратите внимание, запрос ALTER TABLE t FREEZE PARTITION не реплицируется. Он создает резервную копию только на локальном сервере. После создания резервной копии данные из /var/lib/clickhouse/shadow/ можно скопировать на удалённый сервер, а локальную копию удалить.
Резервная копия создается почти мгновенно (однако, сначала запрос дожидается завершения всех запросов, которые выполняются для соответствующей таблицы).
ALTER TABLE t FREEZE PARTITION копирует только данные, но не метаданные таблицы. Чтобы сделать резервную копию метаданных таблицы, скопируйте файл /var/lib/clickhouse/metadata/database/table.sql
Чтобы восстановить данные из резервной копии, выполните следующее:
- Создайте таблицу, если она ещё не существует. Запрос на создание можно взять из .sql файла (замените в нём ATTACH на CREATE ).
- Скопируйте данные из директории data/database/table/ внутри резервной копии в директорию /var/lib/clickhouse/data/database/table/detached/ .
- С помощью запросов ALTER TABLE t ATTACH PARTITION добавьте данные в таблицу.
Восстановление данных из резервной копии не требует остановки сервера.
Подробнее о резервном копировании и восстановлении данных читайте в разделе Резервное копирование данных.
UNFREEZE PARTITION
ALTER TABLE table_name [ON CLUSTER cluster] UNFREEZE [PARTITION 'part_expr'] WITH NAME 'backup_name'
Удаляет с диска «замороженные» партиции с указанным именем. Если секция PARTITION опущена, запрос удаляет резервную копию всех партиций сразу.
FETCH PARTITION | PART
ALTER TABLE table_name [ON CLUSTER cluster] FETCH PARTITION|PART partition_expr FROM 'path-in-zookeeper'
Загружает партицию с другого сервера. Этот запрос работает только для реплицированных таблиц.
Запрос выполняет следующее:
- Загружает партицию/кусок с указанного шарда. Путь к шарду задается в секции FROM (‘path-in-zookeeper’). Обратите внимание, нужно задавать путь к шарду в ZooKeeper.
- Помещает загруженные данные в директорию detached таблицы table_name . Чтобы прикрепить эти данные к таблице, используйте запрос ATTACH PARTITION | PART.
ALTER TABLE users FETCH PARTITION 201902 FROM '/clickhouse/tables/01-01/visits'; ALTER TABLE users ATTACH PARTITION 201902;
- FETCH PART
ALTER TABLE users FETCH PART 201901_2_2_0 FROM '/clickhouse/tables/01-01/visits'; ALTER TABLE users ATTACH PART 201901_2_2_0;
Следует иметь в виду:
- Запрос ALTER TABLE t FETCH PARTITION|PART не реплицируется. Он загружает партицию в директорию detached только на локальном сервере.
- Запрос ALTER TABLE t ATTACH реплицируется — он добавляет данные в таблицу сразу на всех репликах. На одной из реплик данные будут добавлены из директории detached , а на других — из соседних реплик.
Перед загрузкой данных система проверяет, существует ли партиция и совпадает ли её структура со структурой таблицы. При этом автоматически выбирается наиболее актуальная реплика среди всех живых реплик.
Несмотря на то что запрос называется ALTER TABLE , он не изменяет структуру таблицы и не изменяет сразу доступные данные в таблице.
MOVE PARTITION | PART
Перемещает партицию или кусок данных на другой том или диск для таблиц с движком MergeTree . Смотрите Хранение данных таблицы на нескольких блочных устройствах.
ALTER TABLE table_name [ON CLUSTER cluster] MOVE PARTITION|PART partition_expr TO DISK|VOLUME 'disk_name'
Запрос ALTER TABLE t MOVE :
- Не реплицируется, т.к. на разных репликах могут быть различные конфигурации политик хранения.
- Возвращает ошибку, если указан несконфигурированный том или диск. Ошибка также возвращается в случае невыполнения условий перемещения данных, которые указаны в конфигурации политики хранения.
- Может возвращать ошибку в случае, когда перемещаемые данные уже оказались перемещены в результате фонового процесса, конкурентного запроса ALTER TABLE t MOVE или как часть результата фоновой операции слияния. В данном случае никаких дополнительных действий от пользователя не требуется.
ALTER TABLE hits MOVE PART '20190301_14343_16206_438' TO VOLUME 'slow' ALTER TABLE hits MOVE PARTITION '2019-09-01' TO DISK 'fast_ssd'
UPDATE IN PARTITION
Манипулирует данными в указанной партиции, соответствующими заданному выражению фильтрации. Реализовано как мутация mutation.
ALTER TABLE [db.]table [ON CLUSTER cluster] UPDATE column1 = expr1 [, ...] [IN PARTITION partition_id] WHERE filter_expr
Пример
ALTER TABLE mt UPDATE x = x + 1 IN PARTITION 2 WHERE p = 2;
Смотрите также
DELETE IN PARTITION
Удаляет данные в указанной партиции, соответствующие указанному выражению фильтрации. Реализовано как мутация mutation.
ALTER TABLE [db.]table [ON CLUSTER cluster] DELETE [IN PARTITION partition_id] WHERE filter_expr
Пример
ALTER TABLE mt DELETE IN PARTITION 2 WHERE p = 2;
Смотрите также
Как задавать имя партиции в запросах ALTER
Чтобы задать нужную партицию в запросах ALTER . PARTITION , можно использовать:
- Имя партиции. Посмотреть имя партиции можно в столбце partition системной таблицы system.parts. Например, ALTER TABLE visits DETACH PARTITION 201901 .
- Кортеж из выражений или констант, совпадающий (в типах) с кортежем партиционирования. В случае ключа партиционирования из одного элемента, выражение следует обернуть в функцию tuple(. ) . Например, ALTER TABLE visits DETACH PARTITION tuple(toYYYYMM(toDate(‘2019-01-25’))) .
- Строковый идентификатор партиции. Идентификатор партиции используется для именования кусков партиции на файловой системе и в ZooKeeper. В запросах ALTER идентификатор партиции нужно указывать в секции PARTITION ID , в одинарных кавычках. Например, ALTER TABLE visits DETACH PARTITION ID ‘201901’ .
- Для запросов ATTACH PART и DROP DETACHED PART: чтобы задать имя куска партиции, используйте строковой литерал со значением из столбца name системной таблицы system.detached_parts. Например, ALTER TABLE visits ATTACH PART ‘201901_1_1_0’ .
Использование кавычек в имени партиций зависит от типа данных столбца, по которому задано партиционирование. Например, для столбца с типом String имя партиции необходимо указывать в кавычках (одинарных). Для типов Date и Int* кавычки указывать не нужно.
Замечание: для таблиц старого стиля партицию можно указывать и как число 201901 , и как строку ‘201901’ . Синтаксис для таблиц нового типа более строг к типам (аналогично парсеру входного формата VALUES).
Правила, сформулированные выше, актуальны также для запросов OPTIMIZE. Чтобы указать единственную партицию непартиционированной таблицы, укажите PARTITION tuple() . Например:
OPTIMIZE TABLE table_not_partitioned PARTITION tuple() FINAL;
IN PARTITION указывает на партицию, для которой применяются выражения UPDATE или DELETE в результате запроса ALTER TABLE . Новые куски создаются только в указанной партиции. Таким образом, IN PARTITION помогает снизить нагрузку, когда таблица разбита на множество партиций, а вам нужно обновить данные лишь точечно.
Репликация данных
Репликация поддерживается только для таблиц семейства MergeTree:
- ReplicatedMergeTree
- ReplicatedSummingMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
Репликация работает на уровне отдельных таблиц, а не всего сервера. То есть, на сервере могут быть расположены одновременно реплицируемые и не реплицируемые таблицы.
Репликация не зависит от шардирования. На каждом шарде репликация работает независимо.
Реплицируются сжатые данные запросов INSERT , ALTER (см. подробности в описании запроса ALTER).
Запросы CREATE , DROP , ATTACH , DETACH и RENAME выполняются на одном сервере и не реплицируются:
- Запрос CREATE TABLE создаёт новую реплицируемую таблицу на том сервере, где его выполнили. Если таблица уже существует на других серверах, запрос добавляет новую реплику.
- DROP TABLE удаляет реплику, расположенную на том сервере, где выполняется запрос.
- Запрос RENAME переименовывает таблицу на одной реплик. Другими словами, реплицируемые таблицы на разных репликах могут называться по-разному.
ClickHouse хранит метаинформацию о репликах в Apache ZooKeeper. Используйте ZooKeeper 3.4.5 или новее.
Для использовании репликации, установите параметры в секции zookeeper конфигурации сервера.
Не пренебрегайте настройками безопасности. ClickHouse поддерживает ACL схему digest подсистемы безопасности ZooKeeper.
Пример указания адресов кластера ZooKeeper:
zookeeper> node index="1"> host>example1host> port>2181port> node> node index="2"> host>example2host> port>2181port> node> node index="3"> host>example3host> port>2181port> node> zookeeper>
Можно указать любой имеющийся у вас ZooKeeper-кластер — система будет использовать в нём одну директорию для своих данных (директория указывается при создании реплицируемой таблицы).
Если в конфигурационном файле не настроен ZooKeeper, то вы не сможете создать реплицируемые таблицы, а уже имеющиеся реплицируемые таблицы будут доступны в режиме только на чтение.
При запросах SELECT , ZooKeeper не используется, т.е. репликация не влияет на производительность SELECT и запросы работают так же быстро, как и для нереплицируемых таблиц. При запросах к распределенным реплицированным таблицам поведение ClickHouse регулируется настройками max_replica_delay_for_distributed_queries and fallback_to_stale_replicas_for_distributed_queries.
При каждом запросе INSERT , делается около десятка записей в ZooKeeper в рамках нескольких транзакций. (Чтобы быть более точным, это для каждого вставленного блока данных; запрос INSERT содержит один блок или один блок на max_insert_block_size = 1048576 строк.) Это приводит к некоторому увеличению задержек при INSERT , по сравнению с нереплицируемыми таблицами. Но если придерживаться обычных рекомендаций — вставлять данные пачками не более одного INSERT в секунду, то это не составляет проблем. На всём кластере ClickHouse, использующим для координации один кластер ZooKeeper, может быть в совокупности несколько сотен INSERT в секунду. Пропускная способность при вставке данных (количество строчек в секунду) такая же высокая, как для нереплицируемых таблиц.
Для очень больших кластеров, можно использовать разные кластеры ZooKeeper для разных шардов. Впрочем, на кластере Яндекс.Метрики (примерно 300 серверов) такой необходимости не возникает.
Репликация асинхронная, мульти-мастер. Запросы INSERT и ALTER можно направлять на любой доступный сервер. Данные вставятся на сервер, где выполнен запрос, а затем скопируются на остальные серверы. В связи с асинхронностью, только что вставленные данные появляются на остальных репликах с небольшой задержкой. Если часть реплик недоступна, данные на них запишутся тогда, когда они станут доступны. Если реплика доступна, то задержка составляет столько времени, сколько требуется для передачи блока сжатых данных по сети. Количество потоков для выполнения фоновых задач можно задать с помощью настройки background_schedule_pool_size.
Движок ReplicatedMergeTree использует отдельный пул потоков для скачивания кусков данных. Размер пула ограничен настройкой background_fetches_pool_size, которую можно указать при перезапуске сервера.
По умолчанию, запрос INSERT ждёт подтверждения записи только от одной реплики. Если данные были успешно записаны только на одну реплику, и сервер с этой репликой перестал существовать, то записанные данные будут потеряны. Вы можете включить подтверждение записи от нескольких реплик, используя настройку insert_quorum .
Каждый блок данных записывается атомарно. Запрос INSERT разбивается на блоки данных размером до max_insert_block_size = 1048576 строк. То есть, если в запросе INSERT менее 1048576 строк, то он делается атомарно.
Блоки данных дедуплицируются. При многократной записи одного и того же блока данных (блоков данных одинакового размера, содержащих одни и те же строчки в одном и том же порядке), блок будет записан только один раз. Это сделано для того, чтобы в случае сбоя в сети, когда клиентское приложение не может понять, были ли данные записаны в БД, можно было просто повторить запрос INSERT . При этом не имеет значения, на какую реплику будут отправлены INSERT-ы с одинаковыми данными. Запрос INSERT идемпотентный. Параметры дедуплицирования регулируются настройками сервера merge_tree
При репликации, по сети передаются только исходные вставляемые данные. Дальнейшие преобразования данных (слияния) координируются и делаются на всех репликах одинаковым образом. За счёт этого минимизируется использование сети, и благодаря этому, репликация хорошо работает при расположении реплик в разных дата-центрах. (Стоит заметить, что дублирование данных в разных дата-центрах, по сути, является основной задачей репликации).
Количество реплик одних и тех же данных может быть произвольным. В Яндекс.Метрике в продакшене используется двукратная репликация. На каждом сервере используется RAID-5 или RAID-6, в некоторых случаях RAID-10. Это является сравнительно надёжным и удобным для эксплуатации решением.
Система следит за синхронностью данных на репликах и умеет восстанавливаться после сбоя. Восстановление после сбоя автоматическое (в случае небольших различий в данных) или полуавтоматическое (когда данные отличаются слишком сильно, что может свидетельствовать об ошибке конфигурации).
Создание реплицируемых таблиц
В начало имени движка таблицы добавляется Replicated . Например, ReplicatedMergeTree .
Параметры Replicated * MergeTree
- zoo_path — путь к таблице в ZooKeeper.
- replica_name — имя реплики в ZooKeeper.
- other_parameters — параметры движка, для которого создаётся реплицированная версия, например, версия для ReplacingMergeTree .
CREATE TABLE table_name ( EventDate DateTime, CounterID UInt32, UserID UInt32, ver UInt16 ) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/-/table_name', '', ver) PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID);
Пример в устаревшем синтаксисе
CREATE TABLE table_name ( EventDate DateTime, CounterID UInt32, UserID UInt32 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/-/table_name', '', EventDate, intHash32(UserID), (CounterID, EventDate, intHash32(UserID), EventTime), 8192);
Как видно в примере, эти параметры могут содержать подстановки в фигурных скобках. Эти подстановки заменяются на соответствующие значения из конфигурационного файла, из секции macros.
macros> layer>05layer> shard>02shard> replica>example05-02-1.yandex.rureplica> macros>
Путь к таблице в ZooKeeper должен быть разным для каждой реплицируемой таблицы. В том числе, для таблиц на разных шардах, должны быть разные пути. В данном случае, путь состоит из следующих частей:
/clickhouse/tables/ — общий префикс. Рекомендуется использовать именно его.
— — идентификатор шарда. В данном примере он состоит из двух частей, так как на кластере Яндекс.Метрики используется двухуровневое шардирование. Для большинства задач, оставьте только подстановку , которая будет раскрываться в идентификатор шарда.
table_name — имя узла для таблицы в ZooKeeper. Разумно делать его таким же, как имя таблицы. Оно указывается явно, так как, в отличие от имени таблицы, оно не меняется после запроса RENAME. Подсказка: можно также указать имя базы данных перед table_name , например db_name.table_name
Имя реплики — то, что идентифицирует разные реплики одной и той же таблицы. Можно использовать для него имя сервера, как показано в примере. Впрочем, достаточно, чтобы имя было уникально лишь в пределах каждого шарда.
Можно не использовать подстановки, а указать соответствующие параметры явно. Это может быть удобным для тестирования и при настройке маленьких кластеров. Однако в этом случае нельзя пользоваться распределенными DDL-запросами ( ON CLUSTER ).
При работе с большими кластерами мы рекомендуем использовать подстановки, они уменьшают вероятность ошибки.
Можно указать аргументы по умолчанию для движка реплицируемых таблиц в файле конфигурации сервера.
default_replica_path>/clickhouse/tables/// default_replica_path> default_replica_name> default_replica_name>
В этом случае можно опустить аргументы при создании таблиц:
CREATE TABLE table_name ( x UInt32 ) ENGINE = ReplicatedMergeTree ORDER BY x;
Это будет эквивалентно следующему запросу:
CREATE TABLE table_name ( x UInt32 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables///table_name', '') ORDER BY x;
Выполните запрос CREATE TABLE на каждой реплике. Запрос создаёт новую реплицируемую таблицу, или добавляет новую реплику к имеющимся.
Если вы добавляете новую реплику после того, как таблица на других репликах уже содержит некоторые данные, то после выполнения запроса, данные на новую реплику будут скачаны с других реплик. То есть, новая реплика синхронизирует себя с остальными.
Для удаления реплики, выполните запрос DROP TABLE . При этом, удаляется только одна реплика — расположенная на том сервере, где вы выполняете запрос.
Восстановление после сбоя
Если при старте сервера, недоступен ZooKeeper, реплицируемые таблицы переходят в режим только для чтения. Система будет пытаться периодически установить соединение с ZooKeeper.
Если при INSERT недоступен ZooKeeper, или происходит ошибка при взаимодействии с ним, будет выкинуто исключение.
При подключении к ZooKeeper, система проверяет соответствие между имеющимся в локальной файловой системе набором данных и ожидаемым набором данных (информация о котором хранится в ZooKeeper). Если имеются небольшие несоответствия, то система устраняет их, синхронизируя данные с реплик.
Обнаруженные битые куски данных (с файлами несоответствующего размера) или неизвестные куски (куски, записанные в файловую систему, но информация о которых не была записана в ZooKeeper) переносятся в поддиректорию detached (не удаляются). Недостающие куски скачиваются с реплик.
Стоит заметить, что ClickHouse не делает самостоятельно никаких деструктивных действий типа автоматического удаления большого количества данных.
При старте сервера (или создании новой сессии с ZooKeeper), проверяется только количество и размеры всех файлов. Если у файлов совпадают размеры, но изменены байты где-то посередине, то это обнаруживается не сразу, а только при попытке их прочитать при каком-либо запросе SELECT . Запрос кинет исключение о несоответствующей чексумме или размере сжатого блока. В этом случае, куски данных добавляются в очередь на проверку, и при необходимости, скачиваются с реплик.
Если обнаруживается, что локальный набор данных слишком сильно отличается от ожидаемого, то срабатывает защитный механизм. Сервер сообщает об этом в лог и отказывается запускаться. Это сделано, так как такой случай может свидетельствовать об ошибке конфигурации — например, если реплика одного шарда была случайно сконфигурирована, как реплика другого шарда. Тем не менее, пороги защитного механизма поставлены довольно низкими, и такая ситуация может возникнуть и при обычном восстановлении после сбоя. В этом случае, восстановление делается полуавтоматически — «по кнопке».
Для запуска восстановления, создайте в ZooKeeper узел /path_to_table/replica_name/flags/force_restore_data с любым содержимым или выполните команду для восстановления всех реплицируемых таблиц:
$ sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data
Затем запустите сервер. При старте, сервер удалит эти флаги и запустит восстановление.
Восстановление в случае потери всех данных
Если на одном из серверов исчезли все данные и метаданные, восстановление делается следующим образом:
- Установите на сервер ClickHouse. Корректно пропишите подстановки в конфигурационном файле, отвечающие за идентификатор шарда и реплики, если вы их используете.
- Если у вас были нереплицируемые таблицы, которые должны быть вручную продублированы на серверах, скопируйте их данные (в директории /var/lib/clickhouse/data/db_name/table_name/ ) с реплики.
- Скопируйте с реплики определения таблиц, находящиеся в /var/lib/clickhouse/metadata/ . Если в определениях таблиц, идентификатор шарда или реплики, прописаны в явном виде — исправьте их, чтобы они соответствовали данной реплике. (Альтернативный вариант — запустить сервер и сделать самостоятельно все запросы ATTACH TABLE , которые должны были бы быть в соответствующих .sql файлах в /var/lib/clickhouse/metadata/ .)
- Создайте в ZooKeeper узел /path_to_table/replica_name/flags/force_restore_data с любым содержимым или выполните команду для восстановления всех реплицируемых таблиц: sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data
Затем запустите сервер (перезапустите, если уже запущен). Данные будут скачаны с реплик.
В качестве альтернативного варианта восстановления, вы можете удалить из ZooKeeper информацию о потерянной реплике ( /path_to_table/replica_name ), и затем создать реплику заново, как написано в разделе Создание реплицированных таблиц .
Отсутствует ограничение на использование сетевой полосы при восстановлении. Имейте это ввиду, если восстанавливаете сразу много реплик.
Преобразование из MergeTree в ReplicatedMergeTree
Здесь и далее, под MergeTree подразумеваются все движки таблиц семейства MergeTree , так же для ReplicatedMergeTree .
Если у вас была таблица типа MergeTree , репликация которой делалась вручную, вы можете преобразовать её в реплицируемую таблицу. Это может понадобиться лишь в случаях, когда вы уже успели накопить большое количество данных в таблице типа MergeTree , а сейчас хотите включить репликацию.
Если на разных репликах данные отличаются, то сначала синхронизируйте их, либо удалите эти данные на всех репликах кроме одной.
Переименуйте имеющуюся MergeTree таблицу, затем создайте со старым именем таблицу типа ReplicatedMergeTree . Перенесите данные из старой таблицы в поддиректорию detached в директории с данными новой таблицы ( /var/lib/clickhouse/data/db_name/table_name/ ). Затем добавьте эти куски данных в рабочий набор с помощью выполнения запросов ALTER TABLE ATTACH PARTITION на одной из реплик.
Преобразование из ReplicatedMergeTree в MergeTree
Создайте таблицу типа MergeTree с другим именем. Перенесите в её директорию с данными все данные из директории с данными таблицы типа ReplicatedMergeTree . Затем удалите таблицу типа ReplicatedMergeTree и перезапустите сервер.
Если вы хотите избавиться от таблицы ReplicatedMergeTree , не запуская сервер, то
- удалите соответствующий файл .sql в директории с метаданными ( /var/lib/clickhouse/metadata/ );
- удалите соответствующий путь в ZooKeeper ( /path_to_table/replica_name );
После этого, вы можете запустить сервер, создать таблицу типа MergeTree , перенести данные в её директорию, и перезапустить сервер.
Восстановление в случае потери или повреждения метаданных на ZooKeeper кластере
Если данные в ZooKeeper оказались утеряны или повреждены, то вы можете сохранить данные, переместив их в нереплицируемую таблицу, как описано в пункте выше.
Смотрите также
- background_schedule_pool_size
- background_fetches_pool_size
- execute_merges_on_single_replica_time_threshold
- max_replicated_fetches_network_bandwidth
- max_replicated_sends_network_bandwidth
ClickHouse: создание таблицы
Как и в остальных СУБД (систем управления базами данных), в ClickHouse есть много функций для работы с таблицами. Но перед тем, как работать с ними, сначала нужно создать базу данных, в которой эти таблицы будут храниться (это не касается временных таблиц, о которых речь также пойдет ниже).
Для создания базы данных в ClickHouse используется команда CREATE DATABASE , которая создает новую БД в хранилище ClickHouse. Для выбора уже созданной БД используется команда USE . Выглядят эти команды так (имена БД даны просто для примера):
CREATE DATABASE my_new_database
USE my_old_database
А в панели Timeweb Cloud база данных ClickHouse создается буквально в пару кликов:
- Зарегистрируйтесь или залогиньтесь на сайте и перейдите на страницу Базы данных, после чего нажмите на кнопку Создать.
- На следующей странице выберите в пункте Тип базы данных ClickHouse, заполните нужные параметры ниже и нажмите на кнопку Заказать справа.
Теперь можно переходить к работе с таблицами.
Создание таблиц в ClickHouse
Для создания таблиц используется команда CREATE TABLE , после которой вводится имя таблицы, а затем идут параметры столбцов. Давайте сразу перейдем к практике, а попутно будем объяснять встречающиеся команды другого типа.
Пример №1
Начнем с примера создания таблицы для хранения данных о моделях какой-нибудь популярной автомобильной марки:
CREATE TABLE autobrand_models ( model_id UInt32, model_name String, release_year UInt16, engine_type String, horsepower UInt16, price Decimal(10, 2) ) ENGINE = MergeTree() ORDER BY model_id;
В этом примере создается таблица autobrand_models с полями: model_id (идентификатор модели), model_name (название модели), release_year (год выпуска), engine_type (тип двигателя), horsepower (мощность двигателя в л.с.) и price (цена).
Поле model_id имеет тип UInt32 , что подразумевает использование 32-битного целого числа (то есть без дополнительных знаков). Поле price имеет тип Decimal(10, 2) , что означает использование десятичного числа с общим размером до 10 цифр и 2 цифрами после запятой. Поля model_name и engine_type принимают строковые значения ( String ), а release_year и horsepower — 16-битные целые значения ( UInt16 ). Таким образом, данная таблица позволяет хранить информацию о моделях автомобилей определенного бренда, включая их идентификатор, название, год выпуска, тип двигателя, его мощность и цену авто.
Также обратите внимание на две нижние строчки:
- ENGINE = MergeTree() — это означает, что в данном случае используется движок MergeTree , который является одним из наиболее распространенных для хранения данных в ClickHouse. Используемый движок определяет, как и где хранятся данные, какие запросы поддерживаются, а также реплицируются ли данные. Для ClickHouse разработано множество движков, но для простых таблиц, как в примере выше, очевидным выбором будет именно MergeTree .
- ORDER BY model_id; — в этой строке указывается, что данные будут упорядочены по столбцу с идентификаторами моделей.
Пример №2
Теперь о том, как использовать первичные ключи. Их можно указать по-разному: внутри списка столбцов или вне его.
В первом случае первичные ключи прописываются так:
CREATE TABLE db.new_table ( name01 type01, name02 type02, . PRIMARY KEY(expr01[, expr02. ]) )
Если же их нужно указать за пределами таблицы, то это будет выглядеть так:
CREATE TABLE db.new_table ( name01 type01, name02 type02, . ) PRIMARY KEY(expr01[, expr02. ]);
Как видим, разница в коде заключается в положении закрывающей скобки: во втором случае первичные ключи вынесены за ее пределы, то есть за пределы самой таблицы.
Давайте приведем пример конкретного применения первичных ключей:
CREATE TABLE shop.sales_by_category ( category_id UInt32, product_name String, sale_date Date, quantity UInt16, price Decimal(10, 2), revenue Decimal(10, 2), PRIMARY KEY(category_id, sale_date) ) ENGINE = MergeTree() ORDER BY (category_id, sale_date);
- category_id — id категории в формате 32-битного целого числа ( UInt32 );
- product_name — название продукта, строковое значение ( String );
- sale_date — дата продажи в формате даты ( Date );
- quantity — количество в формате 16-битного целого числа ( UInt16 );
- price — цена в десятичном формате с 2 знаками после запятой Decimal(10, 2) ;
- revenue — общий доход, также в формате Decimal(10, 2) ;
- PRIMARY KEY — первичные ключи, в данном случае они внутри списка и включают значения category_id и sale_date ;
- ORDER BY (category_id, sale_date) — определяет порядок сортировки данных в таблице. Данные могут быть отсортированы по столбцам category_id и sale_date .
Мы познакомились с типичной структурой таблиц ClickHouse, а теперь перейдем к некоторым специфическим табличным функциям.
Добавление комментариев к таблицам
Это делается при помощи команды COMMENT . Приведем пример добавления комментария с его последующим выводом. Добавить комментарий можно, например, так:
CREATE TABLE countdown (x String) ENGINE = Memory COMMENT 'Временная таблица для отчета';
А вот команда для его вывода:
SELECT name, comment FROM system.tables WHERE name = 'countdown';
В результате ClickHouse выведет нам в табличном виде следующее:
name | comment
-------------|------------------------------------------------
countdown | Временная таблица для отчета
Временные таблицы в ClickHouse
В ClickHouse есть возможность создавать временные таблицы, которые актуальны только для текущего запроса и создаются вне базы данных. После завершения сеанса или закрытия соединения временная таблица автоматически удаляется. Чтобы создать временную таблицу в ClickHouse, используется команда CREATE TEMPORARY TABLE . Рассмотрим простейшую структуру такой таблицы:
CREATE TEMPORARY TABLE temp_table ( id UInt32, name String ) ENGINE = Memory;
В данном примере создается временная таблица temp_table с полями id (идентификатор) и name (название). Тип движка таблицы указан как Memory , что означает, что данные будут храниться в оперативной памяти. Такая временная таблица полезна, когда нужно быстро сохранить и использовать данные в рамках текущего сеанса без необходимости их дальнейшего хранения.
Теперь более конкретный пример. Предположим, у нас есть база данных для интернет-магазина, и мы хотим провести анализ продаж за определенный период времени. Для этого нам может понадобиться создать временную таблицу, чтобы собрать данные из нескольких таблиц и выполнить аналитические запросы. Вот как это можно реализовать:
CREATE TEMPORARY TABLE temp_sales_data AS SELECT products.product_id, products.product_name, sales.sale_date, sales.sale_amount FROM products JOIN sales ON products.product_id = sales.product_id WHERE sales.sale_date BETWEEN '2024-01-01' AND '2024-01-31';
В этом примере мы создаем временную таблицу temp_sales_data , в которую помещаем данные о продуктах и продажах за январь 2024 года. Мы объединяем таблицы products и sales по идентификатору продукта и выбираем только те записи, у которых дата продажи входит в указанный период.
После создания временной таблицы temp_sales_data , мы можем выполнять различные аналитические запросы к этим данным, например, подсчитывать общую сумму продаж за месяц или находить самые популярные товары. Но обратите внимание, что временная таблица temp_sales_data будет автоматически удалена при закрытии сеанса подключения к базе данных. Это удобно для аналитики, так как у специалиста есть возможность быстро получить нужные данные для отчета, и при этом не требуется впоследствии удалять эту таблицу вручную, ведь иначе подобные отчеты засоряли бы базу данных. Добавим также, что если имя временной таблицы будет совпадать с именем другой таблицы без указания имени БД, в приоритете будет временная таблица.
Изменение структуры таблиц
В ClickHouse можно изменять структуру таблиц, что делается при помощи команды REPLACE . Только нужно помнить, что эта команда применима лишь для существующих таблиц, иначе система выдаст ошибку.
Предположим, у нас есть таблица myBigData с данными, и мы хотим заменить все записи в этой таблице, где CounterID меньше определенного значения. В ClickHouse можно сделать это буквально одной строкой:
REPLACE TABLE myBigData SELECT * FROM myBigData WHERE CounterID < 5356;
Итак, мы познакомились с обычными и временными таблицами в ClickHouse и узнали, как изменять данные в них и добавлять комментарии. А о продвинутых возможностях работы с таблицами ClickHouse смотрите другие наши статьи и документацию разработчиков.