Описание
CollapsingMergeTree наследуется от MergeTree
и добавляет логику схлопывания строк во время слияния.
Движок таблицы CollapsingMergeTree асинхронно удаляет (схлопывает)
пары строк, если все поля ключа сортировки (ORDER BY) совпадают, кроме специального поля Sign,
которое может принимать значение 1 или -1.
Строки, для которых нет пары с противоположным значением Sign, сохраняются.
Подробнее см. в разделе Collapsing этого документа.
Этот движок может значительно уменьшить объем хранилища,
что, в свою очередь, повышает эффективность запросов
SELECT.Параметры
Sign, имеют то же значение, что и в MergeTree.
Sign— имя столбца, указывающего тип строки:1— «строка состояния»,-1— «строка отмены». Тип: Int8.
Создание таблицы
- Описание параметров запроса см. в разделе описание запроса.
- При создании таблицы
CollapsingMergeTreeтребуются те же секции запроса, что и при создании таблицыMergeTree.
Схлопывание
Данные
Sign.
- Если
Sign=1, это означает, что строка является строкой состояния: строкой, содержащей поля, которые представляют текущее корректное состояние. - Если
Sign=-1, это означает, что строка является строкой отмены: строкой, используемой для отмены состояния объекта с теми же атрибутами.
Sign.
Вторая строка выше содержит текущее состояние.
Поскольку нам нужно только последнее состояние активности пользователя, исходная строка состояния и строка отмены,
которую мы вставили, могут быть удалены, как показано ниже, путём схлопывания недействительного (старого) состояния объекта:
CollapsingMergeTree выполняет именно такое схлопывание во время слияния частей данных.
Почему для каждого изменения нужны две строки,
дополнительно рассматривается в разделе Алгоритм.
- Программа, записывающая данные, должна хранить состояние объекта, чтобы иметь возможность отменить его. Строка отмены должна содержать копии полей ключа сортировки строки состояния и противоположное значение
Sign. Это увеличивает первоначальный объем хранилища, но позволяет быстро записывать данные. - Длинные, постоянно растущие массивы в столбцах снижают эффективность движка из-за повышенной нагрузки при записи. Чем проще данные, тем выше эффективность.
- Результаты
SELECTсильно зависят от согласованности истории изменений объекта. Будьте внимательны при подготовке данных для вставки. Если данные несогласованы, результаты могут быть непредсказуемыми. Например, отрицательные значения у неотрицательных метрик, таких как глубина сеанса.
Алгоритм
ORDER BY) сокращается не более чем до двух строк:
«строки состояния» с Sign = 1 и «строки отмены» с Sign = -1.
Иными словами, в ClickHouse записи схлопываются.
Для каждой результирующей части данных ClickHouse сохраняет:
Кроме того, если «строк состояния» как минимум на две больше, чем «строк отмены»,
или «строк отмены» как минимум на две больше, чем «строк состояния», слияние продолжается.
Однако ClickHouse рассматривает эту ситуацию как логическую ошибку и записывает ее в журнал сервера.
Такая ошибка может возникнуть, если одни и те же данные вставляются более одного раза.
Таким образом, схлопывание не должно изменять результаты вычисления статистики.
Изменения постепенно схлопываются, так что в итоге остается только последнее состояние почти каждого объекта.
Столбец
Sign обязателен, потому что алгоритм слияния не гарантирует,
что все строки с одинаковым ключом сортировки окажутся в одной и той же результирующей части данных и даже на одном и том же физическом сервере.
ClickHouse обрабатывает запросы SELECT несколькими потоками и не может предсказать порядок строк в результате.
Агрегация необходима, если нужно получить полностью «схлопнутые» данные из таблицы CollapsingMergeTree.
Чтобы завершить схлопывание, напишите запрос с GROUP BY и агрегатными функциями, учитывающими знак.
Например, чтобы вычислить количество, используйте sum(Sign) вместо count().
Чтобы вычислить сумму чего-либо, используйте sum(Sign * x) вместе с HAVING sum(Sign) > 0 вместо sum(x),
как в примере ниже.
Агрегаты count, sum и avg можно вычислить таким способом.
Агрегат uniq можно вычислить, если у объекта есть хотя бы одно несхлопнутое состояние.
Агрегаты min и max вычислить нельзя,
потому что CollapsingMergeTree не сохраняет историю схлопнутых состояний.
Если вам нужно извлечь данные без агрегации
(например, чтобы проверить, присутствуют ли строки, чьи последние значения соответствуют определенным условиям),
вы можете использовать модификатор
FINAL для предложения FROM. Он выполнит слияние данных перед возвратом результата.
Для CollapsingMergeTree возвращается только последняя строка состояния для каждого ключа.Примеры
Пример использования
UAct с помощью CollapsingMergeTree:
INSERT, чтобы создать две разные части данных.
Если вставить данные одним запросом, ClickHouse создаст только одну часть данных и никогда не выполнит слияние.
INSERT мы создали две части данных.
Запрос SELECT выполнялся в двух потоках, поэтому строки вернулись в случайном порядке.
Однако схлопывание не произошло, потому что слияния частей данных ещё не было,
а ClickHouse выполняет слияние частей данных в фоновом режиме в непредсказуемый момент.
Поэтому нам нужна агрегация,
которую мы выполняем с помощью агрегатной функции sum
и предложения HAVING:
FINAL в предложении FROM.
Такой способ выборки данных менее эффективен и не рекомендуется при работе с большими объёмами сканируемых данных (миллионами строк).
Пример другого подхода
Sign.
В этом примере мы будем использовать приведённые ниже данные:
PageViews и Duration, чтобы в них можно было хранить отрицательные значения.
Поэтому при создании таблицы UAct с помощью
collapsingMergeTree мы меняем типы этих столбцов с UInt8 на Int16: