Рубріки: HighloadТеория

Удаление и обновление данных в Clickhouse

Игорь Грегорченко

В Clickhouse нет поддержки удалений и обновлений. Однако существует большое [https://ruhighload.com/doc/clickhouse/ количество движков] для разных задач.

Если существует необходимость обновлять и удалять данные в таблицах, пригодятся два движка – CollapsingMergeTree и ReplacingMergeTree.

Обновление с помощью ReplacingMergeTree

 

Это простой движок, который позволяет автоматически удалять дубликаты записей на основе первичного ключа. Например, есть таблица атрибутов с информацией о пользователях:

**users**

user_id | email | team | position

Каждая запись однозначно определена первичным ключом (user_id). Некоторые колонки таблицы могут меняться (team и position). Именно для таких случаев подходит движок ReplacingMergeTree:

CREATE TABLE users

(

user_id UInt32,

email String,

team String,

position String,

updated_date date

)

ENGINE = **ReplacingMergeTree**(updated_date, (**user_id**), 8192)


## Обновляемая таблица users с уникальным ключом user_id

При вставке новых данных таблица работает привычным образом:
INSERT INTO users VALUES(1, 'den@ruhighload.com', 'ruhighload', 'engineer', today());

После вставки данные появятся в таблице:

:) SELECT * FROM users;

SELECT *
FROM users 

┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┐
│       1 │ den@ruhighload.com │ ruhighload │ engineer │   2018-04-14 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┘

1 rows in set. Elapsed: 0.003 sec. 

 

Попробуем вставить другие данные с тем же ключом:
INSERT INTO users VALUES(1, 'den@ruhighload.com', 'ruhighload', '**author**', today());

В результате увидим такие данные в таблице:

:) SELECT * FROM users;

SELECT *
FROM users 

┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┐
│       **1** │ den@ruhighload.com │ ruhighload │ **engineer** │   2018-04-14 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┘
┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┐
│       **1** │ den@ruhighload.com │ ruhighload │ **author**   │   2018-04-14 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┘

2 rows in set. Elapsed: 0.003 sec. 

 

Увидим обе записи. Дело в том, что Clickhouse “схлопывает” данные в фоне в неопределенный момент времени. Для того, чтобы сделать правильную выборку нужно к названию таблицы добавить модификатор FINAL:

:) SELECT * FROM users **FINAL**;

SELECT *
FROM users
FINAL 

┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┐
│       **1** │ den@ruhighload.com │ ruhighload │ **author**   │   2018-04-14 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┘

1 rows in set. Elapsed: 0.005 sec. 

 

Этот движок удобно использовать для хранения статических счетчиков. Т.е. метрик, которые переодически пересчитываются и отправляются в систему аналитики. Например, для хранения времени сессий пользователей:

**session_durations**

session_id | duration | date/time


## Для каждой уникальной session_id будет хранится только один duration

В зависимости от метода подсчета, можно такое использовать [https://ruhighload.com/doc/clickhouse/table_engines/summingmergetree/ SummingMergeTree].

Удаление с помощью CollapsingMergeTree

 

Движок CollapsingMergeTree работает похожим образом. Однако кроме основных колонок, для него необходимо указывать еще и колонку версии:

CREATE TABLE users

(

user_id UInt32,

email String,

team String,

position String,

updated_date date,

**version Int8**

)

ENGINE = **CollapsingMergeTree**(updated_date, (**user_id**), 8192, **version**)


## version должна всегда иметь тип Int8

Если при вставке указать version = -1, запись будет удалена. При значениях version = 1 запись будет оставлена в таблице. Например:

INSERT INTO users VALUES(1, 'den@ruhighload.com', 'ruhighload', 'author', today(), **1**);

INSERT INTO users VALUES(2, 'anton@ruhighload.com', 'ruhighload', 'author', today(), **1**);


## вставка данных

После этой вставки в таблице будут две записи:

:) SELECT * FROM users FINAL;

SELECT *
FROM users
FINAL 

┌─user_id─┬─email────────────────┬─team───────┬─position─┬─updated_date─┬─version─┐
│       **2** │ anton@ruhighload.com │ ruhighload │ author   │   2018-04-14 │       **1** │
└─────────┴──────────────────────┴────────────┴──────────┴──────────────┴─────────┘
┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┬─version─┐
│       **1** │ den@ruhighload.com │ ruhighload │ author   │   2018-04-14 │       **1** │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┴─────────┘

2 rows in set. Elapsed: 0.004 sec. 

 

Для удаления одной из записей необходимо вставить ее с version = -1:

INSERT INTO users VALUES(**2**, 'anton@ruhighload.com', 'ruhighload', 'author', today(), **-1**);


## удаление записи

Теперь данные в таблице будут выглядеть так (не забывайте использовать FINAL):

:) SELECT * FROM users FINAL;

SELECT *
FROM users
FINAL 

┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┬─version─┐
│       **1** │ den@ruhighload.com │ ruhighload │ author   │   2018-04-14 │       1 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┴─────────┘

1 rows in set. Elapsed: 0.003 sec. 

## в таблице осталась только одна запись

Движок CollapsingMergeTree также обновляет данные, в случае их изменения:

INSERT INTO users VALUES(1, 'den@ruhighload.com', 'ruhighload', '**human**', today(), 1);

Данные изменятся:

:) SELECT * FROM users FINAL;

SELECT *
FROM users
FINAL 

┌─user_id─┬─email──────────────┬─team───────┬─position─┬─updated_date─┬─version─┐
│       1 │ den@ruhighload.com │ ruhighload │ **human**    │   2018-04-14 │       1 │
└─────────┴────────────────────┴────────────┴──────────┴──────────────┴─────────┘

1 rows in set. Elapsed: 0.004 sec. 

<h2>TL;DR

 

Для реализации удаления и обновления данных в Clickhouse можно использовать движки ReplacingMergeTree и CollapsingMergeTree. Для корректной работы выборок с этими движками необходимо использовать модификатор FINAL.

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023