111 lines
4.5 KiB
SQL
111 lines
4.5 KiB
SQL
# Задачи на отработку:
|
||
|
||
### **Задача 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". |