Частичная перезагрузка данных

297 views
Skip to first unread message

Kirill Solokhov

unread,
Sep 21, 2016, 9:05:28 AM9/21/16
to ClickHouse
Коллеги, представим гипотетическую ситуацию, что необходимо перезагрузить часть данных (неправильно записано какое-то поле итд). Например при работе с Google BigQuery такой проблемы не возникает, достаточно распространенный сценарий это партиционировать данные по дням(своя таблица на каждый день, в запросе перечисляется список участвующих таблиц(партиций)) и в случае каких-либо проблем можно удалить определенный день (таблицу). В ClickHouse исходя из документации размер партиции один месяц, то есть если надо перезагрузить один месяц - проблем не будет. Есть ли способ изменить размер партиции? Или другие варианты? На ум приходят только хаки вроде шардирования по дням, и удаления шардов для частичной перезагрузки. 

Также представим что мы делаем запросы к Distributed таблице которая смотрит на ReplicatedMergeTree. Можно ли на каком нибудь шарде атомарно заменить таблицы? Например создаем новые таблицы name_tmp на всех репликах, загружаем туда данные, удаляем исходные таблицы и переименовываем темповые. Не поломаются ли в таком случае запросы к Distributed таблице?

man...@gmail.com

unread,
Sep 21, 2016, 9:18:26 PM9/21/16
to ClickHouse
Ключ партиционирования изменить нельзя.
У нас в далёких планах есть как возможность задать произвольный ключ партиционирования, так и возможность DELETE.

Вариант с таблицей на каждый день используется на практике, но только для случаев, когда данные нужно хранить в течение небольшого количества дней.
Например, такой вариант используется в Вебвизоре - там данные хранятся 14 дней.
Для данных, хранящихся, например, в течение года, будет работать не очень хорошо.



Также представим что мы делаем запросы к Distributed таблице которая смотрит на ReplicatedMergeTree. Можно ли на каком нибудь шарде атомарно заменить таблицы?

RENAME, в том числе, множественный, работает атомарно, в пределах одного сервера.
С Distributed таблицей всё будет Ок, запросы продолжат выполняться.

Для того, чтобы всё понимать, следует иметь ввиду, что RENAME таблиц, Distributed-таблицы и репликация, не связаны с друг другом и работают независимо.

1. Distributed-таблицы и конфигурация кластера в <remote_servers> в конфиге, определяют то, на какие серверы пойдёт распределённый запрос.
На этих серверах могут быть созданы произвольные локальные таблицы. Это могут быть Replicated-таблицы (обычно), которые сами следят за консистентностью данных на репликах. А могут быть не Replicated-таблицы, для которых вы самостоятельно каким-то образом обеспечили дублирование данных на серверах-репликах. В самом изощрённом случае, таблицы на шардах и репликах, могут быть даже разных типов - Distributed-таблица про это не знает. Впрочем, они должны иметь одинаковые имена и структуру.

2. Вы можете создать несколько Replicated-таблиц с одним путём к метаданным в ZooKeeper. Такие таблицы будут репликами друг-друга. Когда вы пишете данные в любую из таблиц, эти данные разъезжаются по всем таблицам. При этом, совершенно не важно, где именно расположены таблицы-реплики. Например, для целей тестирования, две таблицы-реплики могут располагаться на одном сервере. Также, таблицы-реплики могут называться по-разному и быть расположены в разных базах данных. Впрочем, они должны иметь одинаковую структуру. Имя таблицы никак не зависит от пути к метаданным в ZooKeeper.

3. Запрос RENAME позволяет переименовывать или переносить между базами данных таблицу, позволяет атомарно выполнять сразу несколько таких переименований. Запрос RENAME работает в рамках одного сервера.

Это предоставляет максимальную гибкость, но в то же время, даёт много шансов что-нибудь перепутать.


Давайте разберём на примере.
Пусть у нас есть кластер из двух серверов: один шард, два сервера-реплики.
Создадим на каждом таблицу A_local типа ReplicatedMergeTree, с одним и тем же параметром пути в ZooKeeper, но с разными идентификаторами реплик:

server1: CREATE TABLE A_local ... ENGINE = ReplicatedMergeTree('/clickhouse_perftest/tables/shard1/A', 'replica1', ...)
server2: CREATE TABLE A_local ... ENGINE = ReplicatedMergeTree('/clickhouse_perftest/tables/shard1/A', 'replica2', ...)

Таблицы A_local на этих серверах являются репликами друг друга.

А ещё, пусть у нас прописана конфигурация кластера в <remote_servers>:

<remote_servers>
    <cluster>
        <shard>
            <replica>
                <host>server1</host>
                <port>9000</port>
            </replica>
            <replica>
                <host>server2</host>
                <port>9000</port>
            </replica>
        </shard>
    </cluster>
</remote_servers>

Создадим ещё обоих серверах таблицу A_distributed типа Distributed, которая будет смотреть на наш кластер.

Запросы в таблицу A_distributed будут попадать в таблицу A_local на одной из реплик.
(По факту, при выборе реплики есть предпочтение localhost. Но эти детали не важны для нашего примера.)


Теперь предположим, что мы создали ещё таблицы-реплики B_local:

server1: CREATE TABLE B_local ... ENGINE = ReplicatedMergeTree('/clickhouse_perftest/tables/shard1/B', 'replica1', ...)
server2: CREATE TABLE B_local ... ENGINE = ReplicatedMergeTree('/clickhouse_perftest/tables/shard1/B', 'replica2', ...)

и теперь хотим поменять A и B местами, чтобы распределённые запросы работали на данных таблицы B_local.

Есть следующие способы это сделать:

1. Можно было бы просто удалить и создать заново Distributed-таблицы, чтобы они смотрели на таблицы B_local.
Это не атомарно.

2. Можно создать распределённую таблицу B_distributed, чтобы она смотрела на таблицы B_local.
Затем выполнить атомарный RENAME TABLE A_distributed TO A_distributed_old, B_distributed TO A_distributed
Это атомарно. Запросы SELECT будут идти без даунтайма.
Неудобство в том, что локальные таблицы с используемыми данными теперь называются по-другому.

3. Переименование локальных таблиц:
Будем выполнять запрос RENAME TABLE A_local TO A_local_old, B_local TO A_local
на каждом из серверов.
Запрос работает атомарно в пределах одного сервера.
Рассмотрим, что будет, когда мы сделаем переименование на одном сервере и ещё не сделали на другом.
Будет необычная ситуация: таблицы A_local на server1 и A_local на server2 будут содержать разные данные и не будут репликами друг-друга,
 а таблицы A_local на server1 и B_local на server2 будут репликами друг-друга.
При этом, для Distributed таблицы не имеет значения, как соотносятся друг с другом данные на серверах, указанных в качестве <replica> в конфигурации кластера.
Когда мы сделаем переименование на обоих серверах, то всё будет как задумано.
За исключением, возможно, пути в ZooKeeper: '/clickhouse_perftest/tables/shard1/B', который не меняется при переименовании таблицы.

Kirill Solokhov

unread,
Sep 22, 2016, 5:59:51 AM9/22/16
to ClickHouse
Большое спасибо за развернутый ответ! Нет ли какого-нибудь очень приблизительного эстимейшена, когда может появится возможность задавать ключ партиционирования?

man...@gmail.com

unread,
Sep 22, 2016, 10:54:40 PM9/22/16
to ClickHouse
Нет.
Reply all
Reply to author
Forward
0 new messages