О CollapsingMergeTree в ClickHouse человеческим языком

Основная страница документации всем хороша, но уж больно лаконична.
Итак, читаем:

Изменением какого либо объекта будем называть пару (?старые значения, ?новые значения). Старые значения могут отсутствовать, если объект создался. Новые значения могут отсутствовать, если объект удалился. Если объект изменился, но был раньше и не удалился — присутствует оба значения.

В обычном MergeTree, если вставить новую строку с тем же primary key (PK), она молча вставится, и у вас будет дубликат с тем же PK в таблице. Используя же CollapsingMergeTree, мы можем быстро изменять данные в таблице — такой своеобразный аналог UPDATE. Но есть загвоздка: чтобы внести изменение, нужно знать предыдущее значение строки с тем же PK, которое мы хотим перезаписать. Т.е. вместо UPDATE мы отменяем старую строку и вставляем новую.
Читаем дальше, как это работает.

При слиянии, для каждой группы идущих подряд одинаковых значений первичного ключа (столбцов, по которым сортируются данные), остаётся не более одной строки со значением столбца sign_column = -1 («отрицательной строки») и не более одной строки со значением столбца sign_column = 1 («положительной строки»). То есть — производится схлопывание записей из лога изменений.

Сервер ClickHouse «схлопывает» строки, т.е. оставляет не больше двух: одну «старую» со специальным столбцом sign_column = -1 и одну новую с sign_column = 1. Это делается для уменьшения объема хранимых данных.

Если количество положительных и отрицательных строк совпадает — то пишет первую отрицательную и последнюю положительную строку. Если положительных на 1 больше, чем отрицательных — то пишет только последнюю положительную строку. Если отрицательных на 1 больше, чем положительных — то пишет только первую отрицательную строку.

Например, мы вставляем первую запись:
insert into test (dt, objectId, col1, sign) VALUES ('2018-03-01', 12345, 100, 1)
Если мы хотим ее изменить, то нужно вставить две строки:
insert into test (dt, objectId, col1, sign) VALUES ('2018-03-01', 12345, 100, -1)
insert into test (dt, objectId, col1, sign) VALUES ('2018-03-01', 12345, 200, 1)

После схлопывания останется только последняя строка.

Иначе — логическая ошибка, и ни одна из таких строк не пишется. (Логическая ошибка может возникать, если случайно один кусок лога был вставлен более одного раза. Поэтому, об ошибке всего лишь пишется в лог сервера, и слияние продолжает работать.)

А конкретно вот такое пишется в лог в 1.1.54370:
CollapsingSortedBlockInputStream: Incorrect data: number of rows with sign = 1 (4) differs with number of rows with sign = -1 (1) by more than one (for key: 17532)

Зачем вообще такие сложности со знаком? Дело в том, что «схлопывание» происходит пачкой в неизвестный момент времени в фоновом режиме. Могут пройти десятки минут, прежде чем строки схлопнутся. Такая же проблема характерна и для ReplacingMergeTree. Все это время между вставкой и схлопыванием обычный SELECT из таблицы будет задваивать значения. Но это можно обойти, учитывая в запросе колонку со знаком — подробнее ниже.

Теперь если требуется написать запрос для агрегации, то нужно учесть знак:

Существует несколько способов получения полностью «схлопнутых» данных из таблицы типа CollapsingMergeTree:
1. Написать запрос с GROUP BY и агрегатными функциями, учитывающими знак. Например, чтобы посчитать количество, надо вместо count() написать sum(Sign); чтобы посчитать сумму чего-либо, надо вместо sum(x) написать sum(Sign * x) и т. п., а также добавить HAVING sum(Sign) > 0. Не все величины можно посчитать подобным образом. Например, агрегатные функции min, max не могут быть переписаны.

Если же нужно получить не агрегаты, а последние значения отдельных строк, то можно воспользоваться модификатором FINAL, но это работает медленно.

Подводя итоги:
CollapsingMergeTree полезен, если у вас данные постоянно изменяются и при этом вы знаете старое значение (храните в быстром хранилище в памяти?). Также он может быть полезен, если вы ведете журнал, в который могут «прилетать» изменения, например: журнал платежей, в который иногда приходят отмены платежа.

Альтернативы CollapsingMergeTree, если вам нужно изменять/удалять данные:

  • Использовать движок ReplacingMergeTree — но есть та же проблема с отложенным схлопыванием. Чтобы получить последнюю версию строчек, вам придется или делать SELECT … FROM table FINAL — медленно, либо SELECT … FROM (SELECT argMax(col1, ver), argMax(col2, ver) FROM table WHERE … GROUP BY PK1, PK2…) — требует много памяти. Если вы делаете SELECT редко, то можно перед его выполнением остановить запись INSERT и схлопнуть все принудительно OPTIMIZE TABLE table PARTITION XXXXXX FINAL
  • С версии 1.1.54388 от 2018-06-28 доступны мутации ALTER TABLE … UPDATE и ALTER TABLE … DELETE, однако они не предназначены для частого использования и опять же выполняются в фоне.
  • Копирование данных во временную таблицу, удаление всей партиции ALTER TABLE DROP PARTITION, вливка данных назад с нужными изменениями.
  • Для SummingMergeTree — если вы считаете агрегаты, то можно скопировать удаляемые данные во временную таблицу, затем влить их назад, умножив на -1. Функция SUM(col) теперь по этим строкам будет выдавать 0. Теперь можно вставлять исправленные значения. Постепенно мержер схлопнет в фоне старые строки и удалит.
Рубрика: big data, clickhouse | Метки: | Добавить комментарий

debug_backtrace to string

Convert debug_backtrace to string

Рубрика: PHP | Добавить комментарий

Как сделать звонок через pjsua

/usr/local/bin/pjsua --id sip:user@provider.ru --registrar sip:provider.ru --realm '*' --username user --password p@$$w0rd --null-audio --snd-auto-close=3 --duration=5 "sip:79991234567@provider.ru"
P.S. работает только из TTY

Рубрика: администрирование | Добавить комментарий

Как сохранить страницу в archive.org

Как сохранить снимок страницы в Интернет-архив archive.org Wayback Machine:
https://web.archive.org/save/URL

Рубрика: HTTP, WWW | Добавить комментарий

Удалить драйвер Windows

Как удалить драйвер в Windows:
В командной строке (Win+R)
pnputil.exe -e > C:\drivers.txt
Открываем drivers.txt и ищем драйверы, которые хотим удалить
Удаляем по имени oem##.inf:
pnputil.exe -f -d oem##.inf

Via

Рубрика: Windows, администрирование | Добавить комментарий

Домашняя метеостанция. GeekWeek 2016


Презентация

Рубрика: arduino, diy, митап | Добавить комментарий

Get Windows advertisingId in NodeJS

1. Install Visual studio 2013
2. Install windows.system.userprofile
npm install windows.system.userprofile
3. Code:

Рубрика: NodeJS, web analytics, Windows | Добавить комментарий

Heroes of Might and Magic 3 HD wallpaper rampart

Обои на рабочий стол Герои меча и магии 3 — оплот.
1920×1080

heroes3 rampart hd wallpaper

Рубрика: Без рубрики, игры | Метки: , | Добавить комментарий

[SOLVED] Use of undefined constant CURLINFO_PRIMARY_IP

Error:
PHP Notice: Use of undefined constant CURLINFO_PRIMARY_IP - assumed 'CURLINFO_PRIMARY_IP'
PHP Warning: curl_getinfo() expects parameter 2 to be long, string given

solution:

Рубрика: PHP | Добавить комментарий

Тест Badoo

Рубрика: Без рубрики | Добавить комментарий