Cluster обеспечивает доступ в реальном времени к таблицам базы данных на кластере, указанном в конфигурации сервера. Это аналог движка баз данных Remote для именованного кластера: соотношение между ними такое же, как между табличными функциями cluster и remote.
Список таблиц и их структура запрашиваются у кластера по мере необходимости, поэтому база данных всегда отражает его текущее состояние. Каждая таблица доступна через хранилище на движке Distributed, которое перенаправляет запросы SELECT и INSERT в именованный кластер.
Это удобно, если нужно объединить несколько кластеров ClickHouse или подключить целый кластер к clickhouse-local либо к другому кластеру, не перечисляя его адреса: достаточно один раз задать кластер в конфигурации, указав учётные данные для каждой реплики, параметры защищённых соединений и секрет для межсерверного взаимодействия.
Создание базы данных
cluster_name— имя кластера из конфигурации сервера (см. Кластеры), как в движке таблицыDistributed. Поддерживаются макросы, например{cluster}: они раскрываются при каждом обращении.database— имя базы данных в кластере.
Remote, движок Cluster не принимает учётные данные в качестве параметров и не хранит секреты: для соединений используются настройки каждой реплики из конфигурации кластера (пользователь, пароль, защищённые соединения, сжатие и секрет для межсерверного взаимодействия). При каждом обращении кластер заново определяется по конфигурации, поэтому база данных учитывает её повторную загрузку и автоматическое обнаружение кластеров, как и таблица Distributed. Кластер должен существовать на момент создания базы данных. Если впоследствии он исчезнет из конфигурации, сервер всё равно запустится, но база данных будет сообщать об отсутствии кластера, пока он не появится в конфигурации снова.
Реплика, указывающая на текущий сервер, считается локальным сегментом: SELECT и INSERT выполняются напрямую от имени текущего пользователя. Поэтому ему нужны соответствующие привилегии на базовую базу данных и её таблицы, а учётные данные из конфигурации кластера используются только для удалённых реплик. Если на локальной реплике сегмента нет базы данных или таблицы, поиск переключается на удалённые реплики этого сегмента, как и в таблице Distributed.
Если в кластере несколько сегментов, каждая прокси-таблица читает данные из всех них, но метаданные — список таблиц и их структуру — получает из одного выбранного сегмента (предпочтение отдаётся локальному). Так же работает табличная функция cluster: для получения списка достаточно одного запроса вместо отдельного запроса к каждому сегменту. Поэтому предполагается, что во всех сегментах кластера одинаковый набор таблиц. Если таблица есть лишь в некоторых сегментах, прокси-таблица для неё создаётся, но запросы к ней завершаются ошибкой на сегментах, где таблицы нет. При выполнении INSERT в таблицу базы данных с несколькими сегментами каждая строка отправляется в случайный сегмент (прокси-таблицы Distributed используют неявный ключ сегментирования rand() с учётом заданных весов сегментов). Чтобы указать сегмент для запроса, задайте insert_shard_id. Неявный ключ используется только для распределения вставляемых строк: при чтении таблица ведёт себя как таблица Distributed без ключа сегментирования (в частности, optimize_skip_unused_shards и force_optimize_skip_unused_shards не используют его для исключения ненужных сегментов).
В частности, таблица, существующая только в сегменте, который не выбран для получения метаданных, не обнаруживается командами SHOW TABLES и EXISTS TABLE, а при обращении к ней по имени возвращается ошибка UNKNOWN_TABLE: прокси-таблицы для запросов к ней нет. Таблица, существующая в выбранном для получения метаданных сегменте, но отсутствующая в другом, видна, однако запросы через прокси могут завершаться ошибкой в том сегменте, где её нет.
Для прокси-таблицы Cluster не существует эквивалентного определения, которое можно выполнить повторно, поэтому SHOW CREATE TABLE возвращает ошибку THERE_IS_NO_QUERY. Это относится к следующим случаям:
- Доступ к таблице сейчас осуществляется через описанное выше переключение на удалённую реплику (на локальной реплике сегмента нет базы данных или таблицы). Таблица
Distributedдля всего кластера не выполняет такого переключения, а используемое при переключении подмножество кластера не имеет собственного имени. - Имя кластера базы данных содержит макросы.
Clusterраскрывает их при каждом обращении, аDistributed— только при создании таблицы. Поэтому после изменения конфигурации ни выражение с макросом, ни его текущее раскрытое значение не воспроизведут прежнее поведение. - После повторной загрузки конфигурации кластер с одним сегментом может стать кластером с несколькими сегментами. Тогда действующая прокси-таблица получает неявный ключ
rand()для распределения вставляемых строк, а в определении таблицы, сохранённом до повторной загрузки, этого ключа нет. Безусловное включение ключа в определение тоже не даёт эквивалентного результата: отдельная таблицаDistributedиспользовала бы его для исключения сегментов при чтении, тогда какCREATE TABLEне позволяет задать ключ сегментирования только для вставки.
Примечания
- Движок предоставляет представление кластера только для чтения:
CREATE TABLE,DROP TABLE,ALTERи аналогичные DDL-операторы для базы данныхClusterне поддерживаются. Управляйте схемой непосредственно в кластере, например с помощью DDL-запросов с предложениемON CLUSTER. - Права доступа проверяются на удалённых серверах для пользователей, указанных в определении кластера (или для текущего пользователя, если кластер использует секрет для межсерверного взаимодействия), а локально — с учётом обычных привилегий для базы данных и её таблиц.
- Особенности работы движка баз данных
Remote— правила видимости таблиц локального сегмента, полнота списка таблиц, сообщения об ошибках при недоступности кластера и цепочки прокси-баз данных — также относятся к движкуCluster; см. примечания к нему.
Пример
Создайте базу данныхCluster, которая обращается к базе данных default в кластере test_shard_localhost, указанном в конфигурации сервера, и используйте её: