Обзор
Существует два основных способа миграции данных из самоуправляемого ClickHouse (OSS) в ClickHouse Cloud:
- С помощью функции
remoteSecure(), при котором данные напрямую передаются или извлекаются. - С помощью команд
BACKUP/RESTOREчерез облачное объектное хранилище
Это руководство по миграции посвящено подходу
BACKUP/RESTOREи содержит практический пример миграции базы данных или целого сервиса из ClickHouse с открытым исходным кодом в Cloud через S3 бакет.
Предварительные требования
- У вас установлен Docker
- У вас есть S3 бакет и пользователь IAM
- Вы можете создать новый сервис ClickHouse Cloud
Чтобы шаги из этого руководства было проще повторить и воспроизвести, мы будем использовать один из рецептов Docker Compose для кластера ClickHouse с двумя сегментами и двумя репликами.
Подготовка OSS
Сначала поднимем кластер ClickHouse, используя конфигурацию Docker Compose из нашего репозитория examples. Если у вас уже запущен кластер ClickHouse, этот шаг можно пропустить.
- Клонируйте репозиторий examples на локальный компьютер
- В терминале перейдите в каталог
examples/docker-compose-recipes/recipes/cluster_2S_2R - Убедитесь, что Docker запущен, затем запустите кластер ClickHouse:
docker compose upВы увидите:
[+] Running 7/7
✔ Container clickhouse-keeper-01 Created 0.1s
✔ Container clickhouse-keeper-02 Created 0.1s
✔ Container clickhouse-keeper-03 Created 0.1s
✔ Container clickhouse-01 Created 0.1s
✔ Container clickhouse-02 Created 0.1s
✔ Container clickhouse-04 Created 0.1s
✔ Container clickhouse-03 Created 0.1sВ новом окне терминала, открытом в корне папки, выполните следующую команду, чтобы подключиться к первому узлу кластера:
docker exec -it clickhouse-01 clickhouse-clientОт таблицы MergeTree к таблице ReplicatedMergeTree
ClickHouse Cloud работает с SharedMergeTree.
При восстановлении резервной копии ClickHouse автоматически преобразует таблицы с ReplicatedMergeTree в таблицы SharedMergeTree.
Скорее всего, если вы используете кластер, ваши таблицы уже работают на движке ReplicatedMergeTree.
Если нет, перед созданием резервной копии вам нужно будет преобразовать все таблицы MergeTree в ReplicatedMergeTree.
Чтобы наглядно показать, как преобразовать таблицы MergeTree в ReplicatedMergeTree, мы начнем с таблицы MergeTree, а затем преобразуем ее в ReplicatedMergeTree.
Мы выполним первые два шага из руководства по данным New York taxi, чтобы создать демонстрационную таблицу и загрузить в нее данные.
Для удобства эти шаги приведены ниже.
Выполните следующие команды, чтобы создать новую базу данных и загрузить данные из S3 бакета в новую таблицу:
CREATE DATABASE nyc_taxi;
CREATE TABLE nyc_taxi.trips_small_adapted (
trip_id UInt32,
pickup_datetime DateTime,
dropoff_datetime DateTime,
pickup_longitude Nullable(Float64),
pickup_latitude Nullable(Float64),
dropoff_longitude Nullable(Float64),
dropoff_latitude Nullable(Float64),
passenger_count UInt8,
trip_distance Float32,
fare_amount Float32,
extra Float32,
tip_amount Float32,
tolls_amount Float32,
total_amount Float32,
payment_type Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
pickup_ntaname LowCardinality(String),
dropoff_ntaname LowCardinality(String)
)
ENGINE = MergeTree
PRIMARY KEY (pickup_datetime, dropoff_datetime);INSERT INTO nyc_taxi.trips_small_adapted
SELECT
trip_id,
pickup_datetime,
dropoff_datetime,
pickup_longitude,
pickup_latitude,
dropoff_longitude,
dropoff_latitude,
passenger_count,
trip_distance,
fare_amount,
extra,
tip_amount,
tolls_amount,
total_amount,
payment_type,
pickup_ntaname,
dropoff_ntaname
FROM s3(
'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{0..2}.gz',
'TabSeparatedWithNames'
);Выполните следующую команду, чтобы отсоединить таблицу с помощью DETACH.
DETACH TABLE nyc_taxi.trips_small_adapted;Затем подключите её как реплицируемую:
ATTACH TABLE nyc_taxi.trips_small_adapted AS REPLICATED;Наконец, восстановите метаданные реплики:
SYSTEM RESTORE REPLICA nyc_taxi.trips_small_adapted;Проверьте, что она была преобразована в ReplicatedMergeTree:
SELECT engine
FROM system.tables
WHERE name = 'trips_small_adapted' AND database = 'nyc_taxi';┌─engine──────────────┐
│ ReplicatedMergeTree │
└─────────────────────┘Теперь вы готовы перейти к настройке своего сервиса ClickHouse Cloud для последующего восстановления резервной копии из вашего S3 бакета.
Distributed таблицы с ReplicatedMergeTree
Если в вашей конфигурации используются distributed таблицы между несколькими сегментами, вам потребуется локальная таблица ReplicatedMergeTree на каждом узле и таблица Distributed в качестве точки входа для запросов.
Выполните следующую команду, чтобы создать локальную реплицируемую таблицу на всех узлах кластера:
CREATE DATABASE IF NOT EXISTS nyc_taxi ON CLUSTER 'cluster_2S_2R';
CREATE TABLE nyc_taxi.trips_small_dist_local ON CLUSTER 'cluster_2S_2R'
(
trip_id UInt32,
pickup_datetime DateTime,
dropoff_datetime DateTime,
pickup_longitude Nullable(Float64),
pickup_latitude Nullable(Float64),
dropoff_longitude Nullable(Float64),
dropoff_latitude Nullable(Float64),
passenger_count UInt8,
trip_distance Float32,
fare_amount Float32,
extra Float32,
tip_amount Float32,
tolls_amount Float32,
total_amount Float32,
payment_type Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
pickup_ntaname LowCardinality(String),
dropoff_ntaname LowCardinality(String)
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
PRIMARY KEY (pickup_datetime, dropoff_datetime);Затем создайте на её основе таблицу Distributed:
CREATE TABLE nyc_taxi.trips_small_dist ON CLUSTER 'cluster_2S_2R'
(
trip_id UInt32,
pickup_datetime DateTime,
dropoff_datetime DateTime,
pickup_longitude Nullable(Float64),
pickup_latitude Nullable(Float64),
dropoff_longitude Nullable(Float64),
dropoff_latitude Nullable(Float64),
passenger_count UInt8,
trip_distance Float32,
fare_amount Float32,
extra Float32,
tip_amount Float32,
tolls_amount Float32,
total_amount Float32,
payment_type Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
pickup_ntaname LowCardinality(String),
dropoff_ntaname LowCardinality(String)
)
ENGINE = Distributed('cluster_2S_2R', 'nyc_taxi', 'trips_small_dist_local', rand());Вставьте данные через distributed таблицу:
INSERT INTO nyc_taxi.trips_small_dist
SELECT
trip_id,
pickup_datetime,
dropoff_datetime,
pickup_longitude,
pickup_latitude,
dropoff_longitude,
dropoff_latitude,
passenger_count,
trip_distance,
fare_amount,
extra,
tip_amount,
tolls_amount,
total_amount,
payment_type,
pickup_ntaname,
dropoff_ntaname
FROM s3(
'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{0..2}.gz',
'TabSeparatedWithNames'
);Подготовка ClickHouse Cloud
Вы будете восстанавливать данные в новый сервис ClickHouse Cloud. Чтобы создать новый сервис ClickHouse Cloud, выполните следующие шаги.
Откройте Cloud Console
Перейдите на https://console.clickhouse.cloud/
Создайте новый сервис

Настройте и создайте сервис
Выберите нужный регион и конфигурацию, затем нажмите Create service

Создайте роль доступа
Откройте SQL Console

Настройте доступ к S3
Чтобы восстановить резервную копию из S3, вам нужно настроить безопасный доступ между ClickHouse Cloud и вашим S3 бакетом.
-
Выполните шаги из "Безопасный доступ к данным S3", чтобы создать роль доступа и получить ARN роли.
-
Обновите политику S3 бакета, созданную на шаге "Как создать S3 бакет и роль IAM", добавив ARN роли из предыдущего шага.
Обновлённая политика S3 бакета будет выглядеть примерно так:
{
"Version": "2012-10-17",
"Id": "Policy123456",
"Statement": [
{
"Sid": "abc123",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789123:role/ClickHouseAccess-001",
"arn:aws:iam::123456789123:user/docs-s3-user"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::ch-docs-s3-bucket",
"arn:aws:s3:::ch-docs-s3-bucket/*"
]
}
]
}Политика включает оба ARN:
- пользователь IAM (
docs-s3-user): позволяет вашему самоуправляемому кластеру ClickHouse создавать резервные копии в S3 - роль ClickHouse Cloud (
ClickHouseAccess-001): позволяет вашему сервису ClickHouse Cloud восстанавливать данные из S3
Создание резервной копии (в самоуправляемом развертывании)
Резервную копию каждого сегмента нужно создавать отдельно. Подключитесь к узлу в каждом сегменте и выполните команду резервного копирования, указав уникальный путь назначения для каждого сегмента.
Замените BUCKET_URL, KEY_ID и SECRET_KEY своими учётными данными AWS.
В руководстве "Как создать S3 бакет и роль IAM"
показано, как получить их, если у вас их ещё нет.
Сегмент 1:
BACKUP DATABASE nyc_taxi
TO S3(
'BUCKET_URL/backup_s1.zip',
'KEY_ID',
'SECRET_KEY'
)Сегмент 2:
BACKUP DATABASE nyc_taxi
TO S3(
'BUCKET_URL/backup_s2.zip',
'KEY_ID',
'SECRET_KEY'
)Если всё настроено правильно, вы увидите ответ, похожий на приведённый ниже, с уникальным идентификатором, присвоенным резервной копии, и её статусом.
Query id: efcaf053-75ed-4924-aeb1-525547ea8d45
┌─id───────────────────────────────────┬─status─────────┐
│ e73b99ab-f2a9-443a-80b4-533efe2d40b3 │ BACKUP_CREATED │
└──────────────────────────────────────┴────────────────┘Если вы проверите свой ранее пустой S3 бакет, то увидите, что в нем появилось несколько папок:

Если вы выполняете полную миграцию, то можете запустить следующую команду, чтобы создать резервную копию всего сервера:
BACKUP
TABLE system.users,
TABLE system.roles,
TABLE system.settings_profiles,
TABLE system.row_policies,
TABLE system.quotas,
TABLE system.functions,
ALL EXCEPT DATABASES INFORMATION_SCHEMA, information_schema, system
TO S3(
'BUCKET_ID',
'KEY_ID',
'SECRET_ID'
)
SETTINGS
compression_method='lzma',
compression_level=3;Приведенная выше команда создает резервные копии:
- Всех пользовательских баз данных и таблиц
- Учетных записей пользователей и паролей
- Ролей и разрешений
- Профилей настроек
- Политик доступа к строкам
- Квот
- Пользовательских функций
Если вы используете другого поставщика облачных услуг (CSP), можно использовать синтаксис TO S3() (как для AWS, так и для GCP) и TO AzureBlobStorage().
Для очень больших баз данных рассмотрите возможность использования ASYNC, чтобы выполнять резервное копирование в фоновом режиме:
BACKUP DATABASE my_database
TO S3('https://your-bucket.s3.amazonaws.com/backup.zip', 'key', 'secret')
ASYNC;
-- Returns immediately with backup ID
-- Example result:
-- ┌─id──────────────────────────────────┬─status────────────┐
-- │ abc123-def456-789 │ CREATING_BACKUP │
-- └─────────────────────────────────────┴───────────────────┘Затем идентификатор резервной копии можно использовать для отслеживания прогресса резервного копирования:
SELECT *
FROM system.backups
WHERE id = 'abc123-def456-789'Также можно создавать инкрементные резервные копии. Подробнее о резервном копировании см. в документации по backup and restore.
Восстановление в ClickHouse Cloud
Восстанавливайте резервную копию каждого сегмента по очереди в сервис ClickHouse Cloud. Установите ROLE_ARN в
значение, полученное в разделе "Безопасный доступ к данным S3".
При втором (и каждом последующем) восстановлении используйте SETTINGS allow_non_empty_tables=true, чтобы
данные сегмента добавлялись в уже восстановленные таблицы, а не возникала ошибка конфликта:
Сегмент 1:
RESTORE DATABASE nyc_taxi
FROM S3(
'BUCKET_URL/backup_s1.zip',
extra_credentials(role_arn = 'ROLE_ARN')
)Сегмент 2:
RESTORE DATABASE nyc_taxi
FROM S3(
'BUCKET_URL/backup_s2.zip',
extra_credentials(role_arn = 'ROLE_ARN')
)
SETTINGS allow_non_empty_tables=true;Аналогичным образом можно выполнить полное восстановление сервиса:
RESTORE
TABLE system.users,
TABLE system.roles,
TABLE system.settings_profiles,
TABLE system.row_policies,
TABLE system.quotas,
ALL EXCEPT DATABASES INFORMATION_SCHEMA, information_schema, system
FROM S3(
'BUCKET_URL',
extra_credentials(role_arn = 'ROLE_ARN')
)После завершения восстановления убедитесь, что данные доступны в Cloud:
-- ClickHouse Cloud восстанавливает все данные в локальную таблицу
SELECT count() from nyc_taxi.trips_small_dist_local;
3000317Поскольку ClickHouse Cloud использует SharedMergeTree внутренне, старая distributed таблица больше не нужна. Её можно удалить и заменить представлением, сохранив исходное имя таблицы для ваших запросов:
DROP TABLE drop table nyc_taxi.trips_small_dist;
CREATE VIEW nyc_taxi.trips_small_dist AS SELECT * FROM nyc_taxi.trips_small_dist_local;
SELECT count() from nyc_taxi.trips_small_dist;
3000317Нераспределённые таблицы ReplicatedMergeTree будут восстановлены как SharedMergeTree:
SELECT count() FROM nyc_taxi.trips_small_adapted;
3000317