Использование кластера ClickHouse
Содержание
Особенности кластера
Atomic и MergeTree
Сервер ClickHouse может работать самостоятельно или в составе кластера. Для управления структурой таких баз данных используются привычные операции CREATE DATABASE
, DROP DATABASE
, CREATE TABLE
, DROP TABLE
, ALTER TABLE
и т.д.
CREATE DATABASE db;
DROP DATABASE db;
CREATE TABLE errors_flapping (
`date` DateTime,
`host` UInt32,
`port_name` String,
`count` UInt64
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, host, port_name)
TTL date + toIntervalMonth(6)
SETTINGS index_granularity = 8192;
При создании баз данных по умолчанию используется тип Atomic
, а таблицы должны принадлежать семейству MergeTree
:
MergeTree
,ReplacingMergeTree
,SummingMergeTree
,AggregatingMergeTree
,CollapsingMergeTree
,VersionedCollapsingMergeTree
,GraphiteMergeTree
.
ON CLUSTER
Если выполнять описанные выше операции на узле кластера ClickHouse, то действовать они будут только на текущий узел. Для того, чтобы операция выполнялась на всех узлах, необходимо дописывать к операциям по изменению структуры базы данных ключевые слова ON CLUSTER
с указанием имени кластера. В таком случае указанная операция будет выполнена на всех узлах кластера.
CREATE DATABASE db ON CLUSTER core;
DROP DATABASE db ON CLUSTER core;
Если создать в кластере таблицу семейства MergeTree
, указав ключевые слова ON CLUSTER
с именем кластера, то на каждом узле будет создана своя таблица, но данные между ними не будут ни распределяться, ни синхронизироваться.
CREATE TABLE errors_flapping ON CLUSTER core (
`date` DateTime,
`host` UInt32,
`port_name` String,
`count` UInt64
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, host, port_name)
TTL date + toIntervalMonth(6)
SETTINGS index_granularity = 8192;
Replicated*MergeTree
Чтобы данные таблиц синхронизировались, нужно использовать в базах данных кластеров таблицы семейства Replicated*MergeTree
:
ReplicatedMergeTree
,ReplicatedSummingMergeTree
,ReplicatedReplacingMergeTree
,ReplicatedAggregatingMergeTree
,ReplicatedCollapsingMergeTree
,ReplicatedVersionedCollapsingMergeTree
,ReplicatedGraphiteMergeTree
.
Уже приводившися выше запрос создания таблицы в таком случае примет следующий вид:
CREATE TABLE errors_flapping ON CLUSTER core (
`date` DateTime,
`host` UInt32,
`port_name` String,
`count` UInt64
) ENGINE = ReplicatedMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, host, port_name)
TTL date + toIntervalMonth(6)
SETTINGS index_granularity = 8192;
Содержимое таких таблиц будет реплицироваться так, что данные, вставленные в таблицу на любой из узлов, появятся и на другом.
Replicated
Для того, чтобы не нужно было указывать ключевые слова ON CLUSTER
в операциях по изменению структуры таблиц, можно воспользоваться типом баз данных Replicated
. Однако для создания самой такой базы данных ключевые слова ON CLUSTER
указать всё же нужно:
CREATE DATABASE db ON CLUSTER core ENGINE = Replicated('/clickhouse/databases/{uuid}', '{shard}', '{replica}');
Аргументы в скобках указывают путь в координаторе ClickHouse Keeper, который будет использоваться для отслеживания операций по изменению структуры таблиц в реплицируемой базе данных. Теперь можно управлять структурой таблиц в этой базе данных, не указывая ключевые слова ON CLUSTER
:
CREATE TABLE errors_flapping (
`date` DateTime,
`host` UInt32,
`port_name` String,
`count` UInt64
) ENGINE = ReplicatedMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, host, port_name)
TTL date + toIntervalMonth(6)
SETTINGS index_granularity = 8192;
Преобразование существующих таблиц
Если кластер настраивается не "с нуля", а один из узлов кластера создаётся из уже существующего сервера, то можно преобразовать имеющиеся таблицы в их реплицируемые варианты. Тип базы данных при этом останется прежним - Atomic
.
Первым делом смотрим структуру каждой таблицы с помощью выражения SHOW CREATE TABLE <таблица>
и создаём такие же таблицы с другим именем, но с реплицируемым типом: вместо MergeTree
- ReplicatedMergeTree
, вместо CollapsingMergeTree
- ReplicatedCollapsingMergeTree
и т.д. Не забываем при создании таблиц указывать также ключевые слова ON CLUSTER
, чтобы создать таблицы на всех узлах кластера.
Далее к каждой новой таблице нужно присоединить разделы из старой таблицы.
Предположим, что в базе данных default
есть таблица apilog
, реплицируемый вариант которой называется apilog_replicated
. В таком случае можно сгенерировать выражения для подключения разделов старой таблицы к новой при помощи следующего запроса:
SELECT DISTINCT CONCAT('ALTER TABLE apilog_replicated ATTACH PARTITION ID \'', partition_id, '\' FROM apilog;')
FROM system.parts
WHERE database = 'default'
AND table = 'apilog'
AND active > 0
FORMAT Raw;
Дале нужно выполнить сгенерированные запросы, после чего разделы таблиц будут одновременно присутстовать как в старой таблице, так и в новой. Содержимое реплицируемых таблиц скопируется также на остальные узлы кластера.
Теперь можно поменять имена таблиц при помощи запроса следующего вида:
RENAME TABLE apilog TO apilog_old;
RENAME TABLE apilog_replicated TO apilog ON CLUSTER core;
Если приложение продолжает исправно работать, то старые таблицы можно удалить с помощью запросов следующего вида:
DROP TABLE apilog_old;