Немного здесь написано: https://groups.google.com/d/msg/clickhouse/Ivj7BU6uNBU/IlehlZGcAQAJ
Явного ограничения нет. Таблица с 800 столбцов будет работать нормально.
Далее, чем больше столбцов, тем больше сложность INSERT и оверхед на один INSERT.
При использовании MergeTree, ClickHouse хранит каждый столбец в отдельном файле,
и на каждый INSERT создаёт "кусок" данных со всеми столбцами (куски данных затем мерджатся в фоне).
Я думаю, что 10 000 столбцов будут работать довольно плохо, хотя это не проверялось.
Скорее всего, стоит делать по-другому.
Например, хранить в отдельной таблице множества идентификаторов посетителей для разных сегментов (SegmentID, UserID), и соединять с таблицей событий а также объединять/пересекать с помощью IN.
Явного ограничения нет. Таблица с 800 столбцов будет работать нормально.
Далее, чем больше столбцов, тем больше сложность INSERT и оверхед на один INSERT.Возможно ли решить это batch загрузкой? Для моей задачи это вполне допустимо.
При использовании MergeTree, ClickHouse хранит каждый столбец в отдельном файле,
и на каждый INSERT создаёт "кусок" данных со всеми столбцами (куски данных затем мерджатся в фоне).Это так же работает, если я в INSERT-е записываю, например, 50 столбцов из 1000? Есть ли какая-то оптимизация для хранения значений по умолчанию для столбцов? Ну то есть, в среднем я планирую, что в одной строчке у меня будет около 50 столбцов иметь значение не по умолчанию.
Я думаю, что 10 000 столбцов будут работать довольно плохо, хотя это не проверялось.
Скорее всего, стоит делать по-другому.
Например, хранить в отдельной таблице множества идентификаторов посетителей для разных сегментов (SegmentID, UserID), и соединять с таблицей событий а также объединять/пересекать с помощью IN.Не совсем понял схемы. Основные запросы, которые я планирую выполнять, это получить количество уникальных пользователей, которые, например, находятся в N определенных сегментов и при этом не находятся в K других сегментов. Сейчас для этого используются вероятностные структуры данных, но есть определенные ситуации, где они нас не устраивают.
Добавление и удаление столбца (ALTER) - дешёвые операции. При добавлении столбца ничего физически с данными не происходит: новые данные не записываются. При удалении столбца, происходит удаление файлов с данными столбцов.
При этом, ALTER таблицы прерывает и блокирует фоновые слияния а также передачу данных на реплики, также блокирует INSERT-ы и дожидается текущих INSERT-ов.
Поэтому выполнять ALTER-ы слишком часто не стоит.Явного ограничения нет. Таблица с 800 столбцов будет работать нормально.
Далее, чем больше столбцов, тем больше сложность INSERT и оверхед на один INSERT.Возможно ли решить это batch загрузкой? Для моей задачи это вполне допустимо.
Да, загрузка достаточно большими блоками поможет.
При использовании MergeTree, ClickHouse хранит каждый столбец в отдельном файле,
и на каждый INSERT создаёт "кусок" данных со всеми столбцами (куски данных затем мерджатся в фоне).Это так же работает, если я в INSERT-е записываю, например, 50 столбцов из 1000? Есть ли какая-то оптимизация для хранения значений по умолчанию для столбцов? Ну то есть, в среднем я планирую, что в одной строчке у меня будет около 50 столбцов иметь значение не по умолчанию.
Для старых блоков с данными, в которых не было столбца, его значения не хранятся.
В остальных случаях, значения по-умолчанию хранятся, но стоит иметь ввиду, что частые значения по-умолчанию очень хорошо сжимаются - почти до нуля.
Я думаю, что 10 000 столбцов будут работать довольно плохо, хотя это не проверялось.
Скорее всего, стоит делать по-другому.
Например, хранить в отдельной таблице множества идентификаторов посетителей для разных сегментов (SegmentID, UserID), и соединять с таблицей событий а также объединять/пересекать с помощью IN.Не совсем понял схемы. Основные запросы, которые я планирую выполнять, это получить количество уникальных пользователей, которые, например, находятся в N определенных сегментов и при этом не находятся в K других сегментов. Сейчас для этого используются вероятностные структуры данных, но есть определенные ситуации, где они нас не устраивают.
Пишите
SELECT uniqExact(UserID) FROM table
WHERE SegmentID = 1
AND UserID IN (SELECT UserID FROM table WHERE SegmentID IN (2, 3))
AND UserID IN (SELECT UserID FROM table WHERE SegmentID IN (4, 5, 6))
...
В таблице сделайте первичный ключ, начинающийся с SegmentID.
Про сжатие понял - это очень хорошо. Не понял, влияет ли это на производительность INSERT-ов? То есть вставка в широкую таблицу будет иметь одинаковые накладные расходы независимо от количества столбцов, что я вставляю? Ну то есть для таблицы в 1000 столбцов будет происходить запись в 1000 файлов даже если я вставляю только 20 столбцов?
Пишите
SELECT uniqExact(UserID) FROM table
WHERE SegmentID = 1
AND UserID IN (SELECT UserID FROM table WHERE SegmentID IN (2, 3))
AND UserID IN (SELECT UserID FROM table WHERE SegmentID IN (4, 5, 6))
...
В таблице сделайте первичный ключ, начинающийся с SegmentID.
Такой запрос будет эффективно работать в случае, если количество уникальных UserID будет несколько сотен миллионов, а количество уникальный пар (UserID, SegmentID) - несколько миллиардов? Или лучше подумать в сторону оптимизации и выполнять что-то вроде:SELECT count() FROM tableWHERE (Segment_1 = 1 AND Segment_2 = 1 AND Segment_3 = 0) OR Segment_4 = 1