# Задачи на отработку: ### **Задача 1.** Таблица `sales` | id | region | sale_date | amount | | --- | --- | --- | --- | | 1 | RU | 2024-05-01 | 100.0 | | 2 | RU | 2024-05-15 | 120.0 | | 3 | US | 2024-06-01 | 90.0 | | 4 | US | 2024-07-03 | 150.0 | | 5 | DE | 2024-07-04 | 160.0 | 1. Создай таблицу с `PARTITION BY toYYYYMM(sale_date)`. CREATE TABLE IF NOT EXISTS sales ( id UInt8, region String, sale_sate DateTime64, amount Float64 ) ENGINE = MergeTree() PARTITION BY toYYYYMM(sale_date) ORDER BY (sale_date, region); 2. Выполни `ALTER TABLE ... DROP PARTITION '202405'`. УДАЛИЛАСЬ ПАРТИЦИЯ 3. Что произойдет, если не указывать `PARTITION BY`? ЕСЛИ МЫ ГОВОРИМ ПРО ПРОЦЕСС СОЗДАНИЯ, ТО В ТАКОМ СЛУЧАЕ ВСЕ ДАННЫЕ БУДУТ НАХОДИТЬСЯ ПО УМОЛЧАНИЮ В ОДНОЙ ПАРТИЦИИ. ### **Задача 2.** Есть таблица `events`, и ты хочешь логически хранить данные **по типу события**. | id | event_type | event_date | | --- | --- | --- | | 1 | login | 2024-06-01 | | 2 | click | 2024-06-01 | | 3 | click | 2024-06-02 | | 4 | purchase | 2024-06-03 | | 5 | login | 2024-06-04 | 1. Создай таблицу с `PARTITION BY event_type`. CREATE TABLE IF NOT EXISTS sales ( id UInt8, event_type String, event_date Date ) ENGINE = MergeTree() PARTITION BY event_type ORDER BY (event_type, event_date); 2. Удали все события `click` (подсказка: это `ALTER TABLE DROP PARTITION 'click'`). 3. Чем такой подход может быть опасен (подумай про кардинальность значений)? СЕЙЧАС СОБЫТИЙ ПО ФАКТУ 3, ЭТО МАЛО И УДАЛЕНИЕ БУДЕТ ПРОИСХОДИТЬ БЫСТРО, А ЕСЛИ ПАРТИЦИЙ БУДЕТ 1000, ТО В ТАКОМ СЛУЧАЕ СИСТЕМА БУДЕТ ТОРМОЗИТЬ. ### **Задача 3.** Ты хочешь разбить таблицу `logs` на 100 партиций по `user_id`, чтобы равномерно распределить объём данных. | id | user_id | log_time | | --- | --- | --- | | 1 | 123 | 2024-07-17 10:00:00 | | 2 | 456 | 2024-07-17 10:01:00 | | 3 | 789 | 2024-07-17 10:02:00 | 1. Создай таблицу с `PARTITION BY cityHash64(user_id) % 100`. CREATE TABLE IF NOT EXISTS logs ( id UInt32, user_id UInt32, log_time DateTime64 ) ENGINE = MergeTree() PARTITION BY cityHash64(user_id) % 100 ORDER BY (user_id, log_time); 2. Что ты выиграешь с точки зрения баланса? Я СБАЛАНСИРОВАННО РАЗДЕЛЮ ВСЕ ЛОГИ ПО ПАРТИЦИЯМ ПО УНИКАЛЬНОМУ ЮЗЕР АЙДИ 3. Почему такой тип `PARTITION` не ускорит `SELECT * WHERE user_id = 456`? ПОТОМУ ЧТО В ТАКОМ СЛУЧАЕ ПРИДЕТСЯ ВСЕ РАВНО СКАНИРОВАТЬ ВСЕ ПАРТИЦИИ, ТО ЕСТЬ ВСЮ БАЗУ ДАННЫХ, ВВИДУ ТОГО, ЧТО АЙДИШНИК 456 КЛИКХАУЦС НЕ СМОЖЕТ ПОДСТАВИТЬ В cityHash64(user_id) ДЛЯ РАСЧЕТА В ХЭЩ ФУНКЦИИ. ПОЭТОМУ ОПТИМИЗАТОРУ НЕОБХОДИМО БУДЕТ ЗАГЛЯНУТЬ В 100 ФАЙЛОВ НА ДИСКЕ . ### **Задача 4.** В таблице `visits` данные зависят от региона и времени. | id | region | visit_date | | --- | --- | --- | | 1 | RU | 2024-06-01 | | 2 | RU | 2024-06-15 | | 3 | US | 2024-06-03 | | 4 | US | 2024-07-01 | | 5 | RU | 2024-07-05 | 1. Создай таблицу с `PARTITION BY (region, toYYYYMM(visit_date))`. CREATE TABLE IF NOT EXISTS visits ( id UInt8, region String, visit_date Date ) ENGINE = MergeTree() PARTITION BY (region, toYYYYMM(visit_date)) ORDER BY (visit_date, id); 2. Как будет выглядеть имя партиции? "RU-202406" "US-202406" "US-202407" "RU-202407" 3. Сможешь ли ты эффективно удалить **все июльские данные по `RU`**? НЕТ КОНЕЧНО, ТАК КАК ЭТИ ДАННЫЕ НАХОДЯТСЯ В ДВУХ ПАРТИЦИЯХ, ТО НЕОБХОДИМО БУДЕТ С ПОМОЩЬЮ УДАЛЯТЬ ЧЕРЕЗ "RU-202407".